Keep iOS Mac avatar color slots stable during Mac switches

Merged
AZ
3mo ago
+220-26

Summary

  • Fixes a one-frame color flash on iOS: switching the active Mac briefly shows every workspace/computer row in the wrong avatar color before snapping to the correct one.
  • Root cause: MobileWorkspaceAggregation.machineColorIndex ranked each Mac's color slot by alphabetical position among whatever keys currently existed in the live workspacesByMac dictionary. During a switch, dropStalePreviousForeground synchronously drops the old foreground Mac's key before the new Mac's siblings are re-added asynchronously, so the dictionary briefly holds exactly one key — collapsing that Mac's rank to slot 0 ([Color.blue, Color.cyan]), regardless of its real assigned color.
  • Fix: color slots are now assigned once per Mac, additively, and stick for the lifetime of the shell instance (MobileShellComposite.stableMacColorSlots), instead of being recomputed from the live key set on every recompute. MobileWorkspaceAggregation.machineColorIndex is now a pure (existingAssignments, adding) -> updatedAssignments function immune to live key-set churn.

Test plan

  • swift test in Packages/iOS/CmuxMobileShellModel — 95/95 passing, including a new regression test that reproduces the switch-churn pattern (mutating the live key set while asserting existing Macs' indices never change).
  • Two-commit red/green: d924896 adds the failing regression test only, c35d9dfe adds the fix.
  • Dogfood on a real two-Mac + iPhone setup (the actual repro requires two genuinely distinct paired Macs, which isn't reproducible in this environment — see PR discussion).

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


[!NOTE]
Low Risk
In-memory UI color mapping only; bounded resets on sign-out/team switch with dedicated tests. No auth, networking, or data persistence changes.

Overview
Fixes a one-frame avatar color flash when switching the active Mac on iOS. Per-Mac color slots are no longer derived from alphabetical rank among whatever keys are currently in workspacesByMac on each recompute (which briefly collapses to a single key mid-switch).

MobileShellComposite now keeps stableMacColorSlots for the shell lifetime: updateStableMacColorSlots() runs before workspace derivation, machineColorIndex exposes that map, and derivedWorkspaces takes the precomputed index instead of recomputing from the live key set. Sign-out clears all slots; team switch prunes to the foreground Mac only so old-team Macs do not leak into numbering while the foreground color stays stable.

MobileWorkspaceAggregation.machineColorIndex is now additive—(existingAssignments, adding) preserves prior slots and assigns new Macs deterministically. Regression tests cover switch churn, sign-out, and team-switch boundaries.

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


Summary by cubic

Fixes the one-frame avatar color flash on iOS when switching Macs by assigning stable per-Mac color slots for the shell lifetime, and resets those slots on sign-out/team switches to prevent color leakage.

  • Bug Fixes
    • Added stableMacColorSlots in MobileShellComposite and update it before deriving UI state.
    • Replaced alphabetical indexing with MobileWorkspaceAggregation.machineColorIndex(existingAssignments:adding:); skips empty/anonymous IDs.
    • Passed the precomputed machineColorIndex into derivedWorkspaces to keep previews consistent during switch churn.
    • Reset stableMacColorSlots on sign-out and on team switch; keep only the foreground Mac’s slot across a team switch to avoid a color flash.
    • Moved slot update/reset helpers to MobileShellComposite+MacSwitchState.swift and split color-slot reset tests into MobileShellCompositeColorSlotResetTests.swift to stay within CI’s file-length budget; no behavior change.

Summary by CodeRabbit

  • Bug Fixes

    • Mac color assignments now remain consistent as workspaces update, preventing colors from shifting unexpectedly.
    • Color assignments are correctly reset when signing out and appropriately retained or removed when switching teams.
  • Tests

    • Added coverage for color stability across workspace updates, account changes, and team switches.