Skip to content

fix(app-shell): a package's non-first app opens itself from the avatar menu, palette, switcher, Home tiles and report index - #29327

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-g711nv
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-g711nv

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Fixes #29024

Clause-②: no
Metadata-protocol: none

The two lines are copied from the claim (comment 6575066708) and its amendment (comment 6575119383).

维护者速读

  • 改了什么:头像菜单里的隐藏应用入口,改为链接到该应用自己的地址(appAddressSegment):包 ID 能回到它本身时用包 ID,否则用应用名。⌘K 面板的「切换应用」、顶栏应用切换器、首页「Your apps」磁贴(含 app:launcher 块)和空报表索引页的「其他应用」链接同病同治。
  • 为什么改:/apps/包ID 总是打开该包的第一个应用。一个与主应用同包的隐藏应用(例如设置类应用)从头像菜单点进去,落到的是主应用,这个隐藏应用从菜单根本到不了(QA QA run · release-18.3.0-w4-c3b1 (36/36) · 7fa9873f · 2026-11-02 · 29 PASS / 0 PARTIAL / 7 FAIL / 0 BLOCKED / 0 NOT-RUN #29002 复现 3 次)。同包的其他非首个应用在上述四处也会被带到第一个应用。
  • 风险与回滚:只改链接地址的计算;包内唯一或第一个应用的地址不变(仍是包 ID),这一点有测试钉住。HomeAppsStrip 新增必填 prop routeApps(内部组件,未导出)。回滚即撤销本 PR。
  • 先看:layout/AppHeader.tsx 隐藏应用 DropdownMenuItem 的 onClick;console/home/HomeAppsStrip.tsx 的 routeApps 与磁贴 to;新测试 AppHeader.hiddenAppAddress-29024.test.tsx。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/layout/__tests__/AppHeader.hiddenAppAddress-29024.test.tsx,预期 4 个用例通过。
  • 需要你做的:无,席位落地。

What changes

  • Avatar menu (layout/AppHeader.tsx): the hidden-app entry navigates to /apps/ plus appAddressSegment(metadataApps, app), the app's one address among the metadata app list, instead of appRouteSegment(app) ?? app.name (its package id). appAddressSegment is the existing helper in utils/appRoute.ts that AppContent already resolves the open app's address with; no new helper.
  • Same defect, same fix, measured at each site before editing and fixed the same way:
    • chrome/CommandPalette.tsx: the "Switch app" item hands onAppChange the app's address among the palette's apps (the metadata list, hidden apps included).
    • layout/AppSwitcher.tsx: each row hands onAppChange the app's address among the metadata list.
    • console/home/HomeAppsStrip.tsx: a tile links to the app's address among a new required prop, routeApps, the list /apps/SEGMENT resolves on. The strip only holds the launcher list (hidden apps filtered out), so resolving among the tiles would still misroute a visible app whose package's first app is hidden. Its two callers pass the metadata list: console/home/HomePage.tsx and views/app-launcher-renderer.tsx (the app:launcher block). The prop stays internal; the strip is not exported.
    • views/AppReportIndexView.tsx: the empty index's "Reports in your other apps" links carry the app's address among the metadata list.
  • Left as is: console/home/AppCard.tsx builds the same package-id address for its favourite, but nothing renders it (zero JSX call sites; exported only from console/home/index.ts, which nothing imports, and absent from the package's exports).
  • An app that is its package's only or first app keeps its package-id address everywhere.

Tests

  • layout/__tests__/AppHeader.hiddenAppAddress-29024.test.tsx, the card's reproduction through the avatar-menu harness of AppHeader.myOrganizations: com.qa.r6nav ships qsixn_app (first) and hidden qsixn_hidden_app; the hidden entry navigates to /apps/qsixn_hidden_app. A hidden app alone in its package keeps /apps/com.qa.solo; a hidden app that is its package's first app keeps /apps/com.qa.lead; visible apps are not menu entries.
  • chrome/CommandPalette.packageAppAddress-29024.test.tsx: a package's second app is switched to by name, the first by package id.
  • layout/__tests__/AppSwitcher.packageAppAddress-29024.test.tsx: same, plus a visible app behind its package's hidden first app is switched to by name.
  • console/home/__tests__/HomeAppsStrip.packageAppAddress-29024.test.tsx: tile hrefs for a second app, an app behind a hidden first app, and an app alone in its package.
  • views/__tests__/AppReportIndex.otherAppsAddress-29024.test.tsx: the other-apps links for a package's first and second app.
  • HomeAppsStrip.branding-27386 and HomeAppsStrip.tilesAreLinks-12305 pass routeApps (their pinned hrefs are unchanged).
  • Ablation (one-shot, scripts/ablation-replace.mjs, restored to HEAD's blob, git diff HEAD empty): the avatar entry back to the package-id address (app._packageId ?? app.name, what appRouteSegment(app) ?? app.name computes) turns the card's case red (expected /apps/qsixn_hidden_app, received /apps/com.qa.r6nav); the two keep-address cases stay green.

Acceptance notes

  • Finding for the seat, not fixed here: inside a package's non-first app, the sidebar's navigation links are built on appRouteSegment(activeApp) (UnifiedSidebar basePath; nav-menu-renderer builds its basePath the same way), so they point at the package's first app. Measured through the real UnifiedSidebar, MetadataProvider and route helpers (jsdom): with crm and crm_service sharing com.example.crm, inside crm_service its "Cases" entry links to /apps/com.example.crm/crm_case, which opens crm.
  • Real browser: NOT MEASURED. The two-app package was not staged on the showcase; the avatar-menu test above stands in for the card's browser reproduction.

Verification

Head fe50df22. The fix is commit 0e477fce (based on origin/main 47ee57fe); a5bf2129 merges origin/main 39951d2a (it changed CommandPalette.tsx, HomeAppsStrip.tsx and HomePage.tsx elsewhere; clean) and fe50df22 merges 5a2bdf9c (none of this PR's files; clean). The branch's delta against main is the 15 files above both times. Readings name their head; the final head's are CI's check-runs.

Tests
  • 0e477fce: the five new test files plus the two updated strip tests: 8 files (with a throwaway sidebar probe, since deleted), 24 tests passed.
  • 0e477fce: every ui test file naming a touched component (git grep for AppHeader, CommandPalette, AppSwitcher, HomeAppsStrip, HomePage, AppReportIndexView, AppLauncherRenderer): 199 files, 1833 tests passed, in five locked batches at --maxWorkers=2.
  • a5bf2129, after rebuilding the app-shell dependency closure: every app-shell test file naming CommandPalette, HomeAppsStrip or HomePage (the files the merge changed) plus the five new files: 110 files, 938 tests passed.
  • 0e477fce: ablation, see Tests.
Type-check and gates
  • turbo run type-check --filter=@object-ui/app-shell (tsc --noEmit and tsc -p tsconfig.test.json): 65 of 65 tasks successful on 0e477fce and again on a5bf2129.
  • a5bf2129: node scripts/pm/dispatch-gates.mjs --commands derived 34 families for this diff; all 34 ran with exit 0, pnpm --dir ui exec vitest run scripts/ among them (169 files passed, 2 skipped; 4900 tests passed). --ran reconciled 34 derived, 34 run, 0 NOT-MEASURED. The changeset, ADR-0087 and closing-keyword gates ran against this body.
  • node scripts/check-sdui-manifest.mjs: exit 0 (no registry change).
  • pnpm check:new-line-citations (under ui/): 0 new citations.
  • The CI-only type-check lanes and the whole-tree families are CI's; their check-runs on this PR are the reading.

Generated by Claude Code

…r menu, palette, switcher, Home tiles and report index

The avatar menu's hidden-app entry, the palette's app switch, the app
switcher's rows, Home's tiles and the report index's other-apps links
linked to an app's package id, which /apps/SEGMENT resolves to the
package's FIRST app. They now use appAddressSegment, the app's one
address: the package id where it resolves back to the app, else its name.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jSQKM1ZF6P3HSnWrEQ
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 2, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

席位核对 · ACCEPT · 2026-11-02T12:18Z

Head-sha: fe50df221e6774e50f7fa9ee20295789ee8df8d2

  • Shape: draft → main, Fixes #29024 in the body only. 15 files, +656 / −10 (666 lines ≤ 3000). No governed path: check-governed-merges --pr 29327 reports NOT governed (0 of 15 paths). Clause-②: no and Metadata-protocol: none are line-initial in the body and the changeset, as claimed (6575066708, amended 6575119383). The changeset is patch for @object-ui/app-shell.
  • Contract review: none owed (Clause-②: no; @object-ui/app-shell is "private": true, and HomeAppsStrip's new required routeApps prop is internal, passed by both its callers; no spec, metadata key or i18n change).
  • File surface: inside the amended claim: AppHeader.tsx (the card's hidden-app avatar entry), CommandPalette.tsx (one line, the app switch), AppSwitcher.tsx, HomeAppsStrip.tsx plus its two callers HomePage.tsx and app-launcher-renderer.tsx (one line each), AppReportIndexView.tsx (measured the same and fixed by the same call), their tests (two existing HomeAppsStrip tests get the new prop), and the changeset. AppCard.tsx left alone (no call site). The sidebar basePath is filed as console sidebar: inside a package's second app, the sidebar links open the package's first app #29328, not fixed here.
  • Read in the diff: each site swaps appRouteSegment(app) for appAddressSegment(<full app list>, app), the helper AppContent.tsx already resolves an open app with: the package id when it opens this app, else the app's name. Home's tiles resolve against the full metadata list, hidden apps included, so a visible app behind its package's hidden first app also opens itself. A package's first or only app keeps its package-id address (pinned).
  • Tests (dev): 24 / 24 new across five files; 199 files naming the touched components, 1833 passed; after merging main, 110 files / 938 passed; type-check app-shell 65 / 65. Ablation (AppHeader back to the package id) reds the card case with 3 controls green, restored. Derived gates 34 of 34.
  • Gates (check-runs on this head): 44 success, 11 skipped, 0 failed or pending. mergeable_state is clean.
  • NOT MEASURED: a real browser run on a staged two-app package; the AppHeader test drives the card's reproduction.
  • Serial: Console: unlabeled sidebar object entries and Home recents still read whole metadata lists #29235 (this seat) edits CommandPalette.tsx at :239, disjoint from this PR's :692 line; whichever lands second merges main.
  • Landing: ordinary queue landing, pr_ready then automerge_enable. Fixes #29024 closes the card on merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

console avatar menu: a hidden app that shares its package with the package's first app opens the first app instead of itself

1 participant