Skip to content

Split LayoutStore by responsibility#933

Closed
robinebers wants to merge 2 commits into
codex/normalize-layout-persistencefrom
codex/split-layout-store
Closed

Split LayoutStore by responsibility#933
robinebers wants to merge 2 commits into
codex/normalize-layout-persistencefrom
codex/split-layout-store

Conversation

@robinebers

@robinebers robinebers commented Jul 9, 2026

Copy link
Copy Markdown
Owner

TL;DR

Splits the 889-line LayoutStore into focused grouping, ordering, pinning, presentation, and model files without changing behavior. This PR is stacked on #926 so reviewers see only the responsibility split.

What was happening

  • One observable store file mixed persisted layout mutation with dashboard grouping, Customize projections, pin policy, navigation presentation, and small view models.
  • The file substantially exceeded the repository's ~500-line convention and made unrelated behavior harder to locate.
  • These responsibilities already had clear seams but remained physically interleaved.

What this changes

  • Keeps the observable store and persisted mutation core in LayoutStore.swift.
  • Moves read-only dashboard and Customize projections into LayoutStore+Grouping.
  • Moves ordering helpers, pin policy, and transient presentation state into focused extensions.
  • Moves the small projection/notice value types into LayoutStoreModels.
  • Keeps every resulting source file at or below 500 lines with direct extensions rather than a wrapper or delegation layer.

Heads-up

  • Stacked on Preserve and normalize saved layout identifiers #926 (codex/normalize-layout-persistence); do not merge this before its base PR.
  • Cross-file Swift extensions require a small set of read-only backing references and helpers to be module-internal. Provider expansion storage and persistence remain write-constrained behind the validated mutator; the executable target exposes no public API, and no caller contract changes.
  • PR Remove unreachable UI scaffolding and test-only APIs #924 removes code this PR moves. Whichever lands second needs one rebase; keep Remove unreachable UI scaffolding and test-only APIs #924's removals (availableToAdd, the global pin count, and unused projection fields) in the new focused files. The resolved tree is verified.
  • This is organization-only: no runtime behavior, persisted format, documentation, copy, or visual output changes.

Tests


Note

Low Risk
Pure file split with moved code and internal visibility tweaks; tests and PR description assert no runtime or persistence changes.

Overview
Refactors LayoutStore into smaller files so persisted mutations stay in LayoutStore.swift and read-only projections, helpers, and UI-facing state move into dedicated extensions and LayoutStoreModels.swift.

New files carry the moved logic: LayoutStore+Grouping (dashboard/Customize projections, spend-capable providers, orderedProviders), LayoutStore+Ordering (metricOrder, drag-reorder and merge helpers), LayoutStore+Pins (pin caps, denial reasons, pinnedGroups), and LayoutStore+Presentation (popover navigation forwarding, transient notice surfaces, cancelDrag). ProviderGroup, ProviderMetrics, ProviderRow, and customize notice types now live in LayoutStoreModels.swift.

To let extensions share state without a wrapper layer, navigation, pinNotice/shareNotice/customizeNotice, registry, and isProviderEnabled are let and module-internal instead of private. setProviderExpanded is grouped with other persistence helpers near the bottom of the core file. No intended behavior, persistence format, or caller contract changes—organization only.

Reviewed by Cursor Bugbot for commit 0670a0a. Bugbot is set up for automated code reviews on this repo. Configure here.

@robinebers robinebers added the gate-passed Passed the automated PR gatekeeper checks (gatekeeper skips it on later runs) label Jul 10, 2026 — with Cursor
@robinebers robinebers force-pushed the codex/split-layout-store branch from 9b28463 to 0670a0a Compare July 10, 2026 01:19
@robinebers

Copy link
Copy Markdown
Owner Author

Superseded by #952. The replacement keeps only the mechanical LayoutStore responsibility split, is stacked on the compact dead-code PR #950 instead of the rejected layout-normalization stack, and changes no persistence or behavior. It produces exactly three files at 491/345/60 lines; the normalized implementation hash is unchanged, 73 focused tests and 960 XCTest cases plus 3 Swift Testing cases pass, the signed app launches, and the replacement has zero review threads with all available checks green. I am closing this harder-to-review stacked version; its branch and history remain available.

@robinebers robinebers closed this Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gate-passed Passed the automated PR gatekeeper checks (gatekeeper skips it on later runs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant