Skip to content

refactor(carplay): in-place template updates instead of setRootTemplate spam#3

Draft
jeffcrouse wants to merge 1 commit into
masterfrom
refactor/carplay-in-place-updates
Draft

refactor(carplay): in-place template updates instead of setRootTemplate spam#3
jeffcrouse wants to merge 1 commit into
masterfrom
refactor/carplay-in-place-updates

Conversation

@jeffcrouse
Copy link
Copy Markdown
Member

Background

Picks up the deferred refactor from 4f868a5 ("feat(carplay): land CarPlay scene with resilient browse-state sync"), which wired the end-to-end CarPlay scene and fixed the empty-tabs symptom. That commit explicitly deferred the Apple-API-conformance cleanup to give it a soak window.

What this changes

Before this PR, CarPlayDataBridge called RootTemplateBuilder.buildRootTemplate(...) on every sync arrival from the JS coordinator (3 rapid Promise.allSettled calls: favorites, library, playlists), producing a fresh CPTabBarTemplate + 3 fresh CPListTemplates each time, and calling controller.setRootTemplate(...) 3+ times in rapid succession. This worked in practice but violates Apple's recommended pattern and risks flicker, dropped updates, or losing the user's navigation state when they've drilled into a child template.

After this PR:

  • setRootTemplate is called exactly once — in attachInterfaceController — with a CPTabBarTemplate whose three child CPListTemplates are stored as bridge properties (favoritesTemplate, libraryTemplate, playlistsTemplate).
  • Each subsequent sync call (updateFavoritesupdateLibraryupdatePlaylists) rebuilds only the relevant items/sections and calls CPListTemplate.updateSections(_:) on the appropriate stored template. The tab bar and sibling templates are not touched.
  • On detachInterfaceController the stored templates and actions are cleared; a fresh hierarchy is built on the next attach.
  • clearState calls updateSections on all three templates (empty placeholder state) without touching the root.

Implementation details

  • Added RootTemplates struct to RootTemplateBuilder so buildRootTemplate returns the tab bar and the three child templates in one call.
  • Extracted makeFavoritesSections, makeLibrarySections, makePlaylistsSections as internal static helpers so the bridge can call them per-update without touching parent templates.
  • The Actions struct is built once in makeActions() at attach time; all closures capture [weak self] so they resolve to live bridge state at call time.
  • All [CarPlay] NSLog lines from 4f868a5 are preserved; the old setRoot favs=… log is updated to setRoot once favs=… to make it obvious in the simulator console that it fires only once per connect.

Testing

  • pnpm --filter @familiar/frontend test src/__tests__/CarPlayCoordinator.test.ts8/8 pass (JS coordinator contract is unchanged; no modifications to CarPlayCoordinator.ts).
  • pnpm --filter @familiar/ios exec tsc --noEmit — only the 2 pre-existing errors in TrackListBrowser.tsx and S3BackupSettings.tsx (both pre-date 4f868a5).

Simulator verification is the human's responsibility — this agent cannot run the iOS Simulator. @jeffcrouse please launch the CarPlay simulator from Xcode and confirm:

  1. All three tabs (Favorites, Library, Playlists) still populate after the JS coordinator syncs.
  2. Subsequent favorite/playlist updates reflect in the UI without flicker.
  3. Drilling into a Library bucket (Artists → artist → tracks) and then receiving a background sync does not pop you back to the root or blank the tab.
  4. The simulator console shows [CarPlay] setRoot once firing exactly once per CarPlay connect, followed by [CarPlay] updateSections … lines for each sync.

Generated by Claude Code

…te spam

Call setRootTemplate exactly once (on attachInterfaceController), storing
the three child CPListTemplates as bridge properties. Subsequent syncs from
the JS coordinator (updateFavorites/updateLibrary/updatePlaylists) now call
CPListTemplate.updateSections(_:) on the appropriate stored template rather
than rebuilding the full CPTabBarTemplate hierarchy and re-setting the root.

Adds RootTemplates struct and per-tab section-builder helpers to
RootTemplateBuilder so the bridge can rebuild only items/sections without
touching the parent templates. Actions are built once and capture [weak self].

Preserves all [CarPlay] NSLog instrumentation from 4f868a5.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants