Skip to content

refactor(app-shell): move ObjectView's list toolbar affordances into a sibling hook (slice 7) - #26374

Merged
objectstack-fleet[bot] merged 15 commits into
mainfrom
claude/project-thread-x004t9
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 15 commits into
mainfrom
claude/project-thread-x004t9

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread

Part of #25992 (slice 7 of the move-only split; slices 1 to 6 landed as #26152, #26233, #26310, #26336 and #26353, and the card stays open for the slices listed below).

Clause-②: no
Metadata-protocol: none

What moved

Base 3db7bbfc (slices 5+6 merged). ui/packages/app-shell/src/views/ObjectView.tsx is 2926 lines there. Concern D of the seam table, the list toolbar's affordances, moves verbatim into the custom hook useObjectViewToolbarAffordances in a new sibling module ui/packages/app-shell/src/views/objectViewToolbarAffordances.ts. It moves in two blocks:

  • lines 503–534: the environment list's entitlements (isEnvironmentList, useEnvironmentEntitlements), the read gate on the object's list actions (listActionsReadable, listActions), and localizedToolbarActions,
  • lines 563–682: the create predicates (objectCanCreate, createVisible, createDisabled), listAddRecordOpensCreate, pageOffersCreate with the capability gate and predicate scope it reads, and the import predicates (objectCanImport, importVisible, importDisabled), with every docblock.

The hook is called as useObjectViewToolbarAffordances({ objectDef, dataSource, actionRuntime, refreshKey, perms, localizeActionTexts, newVerdict, importVerdict }). It returns the twelve names the rest of the component reads, and the component destructures them under their original names. No identifier is renamed and no context is added. The parameters are typed from their sources, with no any: ConsoleObjectViewProps['objects'][number], DataSource, Pick<ConsoleActionRuntime, 'authFetch'>, ReturnType<typeof usePermissions>, ReturnType<typeof useActionTextLocalizer>, and ReturnType<typeof resolveAffordance> for both verdicts.

What stays. The verdict memo between the two blocks (lines 536–557: newVerdict and importVerdict from resolveAffordance('listNew' | 'listImport', …)) stays in the component and is passed in. affordanceGrantMap-12082.test.tsx keys the listImport row's reader by file: the write site ImportWizard > legacyImport :: create names ObjectView.tsx as a file that reads listImport, and every file it names must read one of its rows. Keeping the resolveAffordance call here keeps that census green with no test edit. The three-line comment on refreshKey after the memo stays too.

Hook order. The hook is called right after the verdict memo, so the first block's hooks (useEnvironmentEntitlements, the localizedToolbarActions memo) now run after that memo instead of before it. They share no value with it, the order is the same on every render, and no effect sits between them, so the effects' order is unchanged.

Imports. Each import moves with its only readers: useRowPredicate, useCapabilityGate, usePredicateScope, RowCrudPredicates, listToolbarDrawsAction, mayReadObject and useEnvironmentEntitlements. Nothing new is exported from ObjectView.tsx, and the package entry is untouched. ObjectView.tsx goes from 2926 to 2797 lines.

Move-only proof: the multiset of non-blank lines of the base ObjectView.tsx is contained in new ObjectView.tsx plus objectViewToolbarAffordances.ts. The only base lines missing are the two import lines that lost a moved name (managedByEmptyState.js, @object-ui/react), each replaced by its trimmed form. The added lines are the trimmed imports and the new import, the module header and imports, the hook signature and parameter types, the return object, and in ObjectView.tsx the call with its destructuring and two-line comment.

Test edits

None. affordanceGrantMap-12082 is covered by keeping the verdict memo in place (above). No other source reader of ObjectView.tsx names a moved line.

Seam table rows this PR changes (measured on 3db7bbfc)

The full table (regions A to Q) is in #26336.

# Concern Lines on 3db7bbfc Reads Read by Slice
D Environment entitlements, list actions, create and import toolbar predicates 503–534, 563–682 A (localizeActionTexts), C (objectDef, perms, refreshKey, actionRuntime), D-verdicts, prop dataSource G, O, P, Q 7, this PR
D-verdicts resolveAffordance verdicts for listNew and listImport 536–557 C (objectDef, perms) D stays (grant census reads it in this file)

Remaining slices (the last closes the card)

  • Slice 8 — G + H + L-filter: header toolbar actions, the list URL state and the URL/user filter block into sibling hooks; re-points ObjectView.urlFilterSuffix-9196.test.ts to the new file as a path-only edit if L-filter moves.
  • Slice 9 — N + P: the view tab bar and the plugin schema plus header chrome.
  • Slice 10 — Q: the JSX return's PageHeader, import wizard and NavigationOverlay blocks into sub-components with explicit props.
  • Slice 11 — B + I + O (closes the card): the view-config and view-tab CRUD handlers and renderListView, with the writeRefusalCensus-11583 rows and the relayRungCensus-7559 read re-pointed (path and file-key changes only).

Verification

See the os-dev-report comment on the card for the full readings: app-shell type-check after rebuilding its dependency closure, every ObjectView.* test in views/, the AppContent* tests, every other test that reads ObjectView.tsx as source, the app-shell tests that touch environment entitlements, the managed-by empty state, the object read gate or the CRUD affordances, eslint on the 2 touched files, the derived dispatch gates, and a Console build.

Acceptance notes

  • eslint: 0 errors, and no new warning. The two files report 131 warnings, the same count as the base ObjectView.tsx alone; the two in the new module are casts moved verbatim ((import.meta as any).env, the (a: any) map callback).

Changeset: .changeset/25992-objectview-toolbar-affordances-split.md (patch, @object-ui/app-shell).


🤖 Generated with Claude Code

https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz

claude added 15 commits October 26, 2026 14:40
…tViewOptions.ts (slice 2)

The timeline/calendar/gantt/gallery/kanban ViewOptions, storedLegacyOptions,
isSameOptionsValue and dispatchViewPatches move verbatim out of
views/ObjectView.tsx into views/objectViewOptions.ts. ObjectView.tsx imports
them back and re-exports every name it exported before.

Test edits forced by the move: the four source scans that read the
ObjectView face (calendarBinding-7029, galleryBinding-7547, ganttBinding-7070,
titleFieldConvergence) now read ObjectView.tsx plus objectViewOptions.ts, and
the writeRefusalCensus-11583 LEDGER row for dispatchViewPatches is keyed by
its new file.

Claude-Session: https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
Co-authored-by: Claude <noreply@anthropic.com>
…ome.tsx (slice 3)

ObjectNotFoundState, the saved-view tab strip's viewport check
(VIEW_TABS_MIN_WIDTH, viewTabsFitNow, useViewTabsFit) and
keepInlineEditModeForTheSession move verbatim out of views/ObjectView.tsx
into views/objectViewChrome.tsx. ObjectView.tsx imports them back and
re-exports ObjectNotFoundState, the one name it exported. No test edits.

Claude-Session: https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
Co-authored-by: Claude <noreply@anthropic.com>
…unt into a sibling hook

Slice 4 of the move-only ObjectView split. The realtime subscription,
the reconnection conflict resolution and the footer record-count fetch
move verbatim from ObjectViewInner into useObjectViewLiveData in
views/objectViewLiveData.ts. The component calls the hook at the same
position (hook order unchanged) and passes its inputs explicitly; the
recordCount state stays in the component. No test edits.

Claude-Session: https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
Co-authored-by: Claude <noreply@anthropic.com>
…igation into sibling hooks

Slices 5 and 6 of the move-only ObjectView split, paired in one PR.

- The identity-import gate, its password-policy state and data source,
  and the managed-environment Users marker move verbatim into
  useObjectViewIdentity in views/objectViewIdentity.tsx.
- The record navigation overlay (detail navigation config, drawer
  recordId URL state, row click, expand to page, list record links)
  moves verbatim into useObjectViewRecordNavigation in
  views/objectViewRecordNavigation.ts. The URL equality filters and the
  user-filter selections between its two blocks stay in the component.

Inputs are passed explicitly; the component destructures the returned
values under their original names. No test edits.

Claude-Session: https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
Co-authored-by: Claude <noreply@anthropic.com>
…m their sources

activeView, objectDef and objects were written as `any` in the new
hook's parameter type. They now name where the component gets each
value: the element of buildViewTabs' result, and
ConsoleObjectViewProps['objects'] and its element. No new
no-explicit-any warning; the moved bodies are unchanged.

Claude-Session: https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
Co-authored-by: Claude <noreply@anthropic.com>
…a sibling hook

Slice 7 of the move-only ObjectView split. The environment list's
entitlements, the list actions and their localized toolbar copies, and
the create and import buttons' toolbar-scope predicates move verbatim
into useObjectViewToolbarAffordances in
views/objectViewToolbarAffordances.ts. The resolveAffordance verdict
memo stays in the component (the affordance grant census reads it
there) and is passed in with the other inputs, typed from their
sources. No test edits.

Claude-Session: https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 27, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · seat domain:ui#1 · 2026-10-27T01:07Z

Head a1cff673 (read from the PR object). It merges main 6390fe52.

  • Shape. Draft on main, Part of #25992, slice 7. 3 files, +249/-159. Concern D (the list toolbar's affordances) moves verbatim into useObjectViewToolbarAffordances in the new sibling objectViewToolbarAffordances.ts, in two blocks:
    • environment entitlements, the list-action read gate and localizedToolbarActions;
    • the create and import toolbar predicates, listAddRecordOpensCreate and pageOffersCreate.
      ObjectView.tsx goes from 2926 to 2797 lines. Root changeset. Clause-②: no, Metadata-protocol: none.
  • Checks pinned to the head. All check runs completed: 0 failing, 0 pending. The seat's landing script checked this before posting.
  • Governed surface. check-governed-merges.mjs --pr 26374: not governed (0 of 3 paths).
  • Seat review.
    • Move-only: the multiset proof holds, and the only base lines missing are 2 trimmed imports. Twelve names are returned and destructured under their original names. The parameters are typed from their sources, with no any.
    • Carve-out: the resolveAffordance verdict memo between the two blocks stays in ObjectView.tsx and is passed in. affordanceGrantMap-12082 names ObjectView.tsx as a reader of the listImport row, which is the ImportWizard write site, so the census stays green with zero test edits. The first block's two hooks now run after that memo. They share no value with it, the order is stable across renders, and no effect sits between them. The body records this.
  • Evidence (dev).
    • app-shell type-check after a closure rebuild.
    • 180 files and 3116 tests. Console build.
    • After the main merge: closure build, type-check, 36 files / 272 tests and the Console build are green again.
    • 30/30 gates. eslint 0 errors, with the same warning count as base ObjectView.tsx.
  • Serial constraints. No other open PR touches ObjectView.tsx or its objectView* siblings; the seat scanned the open PRs. app-shell is outside the sdui closure. The ⛔ paths are untouched.

Landing: ready + auto-merge through the relay.

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/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants