fix(mobile): preserve Android Usage state across layout changes#24903
Problem
Crossing between compact and split Android workspace layouts switches Usage back to Limits and resets its filters and scroll position. This happens when folding or unfolding a device and when resizing a freeform window across the layout boundary: the two layouts render separate component trees, so changing layout destroys the current screen.
Change
Keep one workspace tab tree mounted in both layouts. Update layout-specific insets, background, navigation, and pull request content in place, so Usage retains its current page, date window, metric, environment filters, and scroll view.
Scope and approval
A focused fix for an obvious Android workspace state-loss bug, eligible under the small bug-fix exception. The change is limited to the Android workspace root; provider behavior, contracts, server operations, and connection modes require no changes. Existing usage documentation remains accurate.
Verification
- Added a regression test against the actual Android workspace root, with a stateful Usage leaf standing in for native content. Both starting layouts failed before the fix with Limits appearing after the first compact/split transition.
- Both cases now retain the selected Usage page, edited filters, scroll container identity, and scroll offset through repeated compact/split transitions. This verifies React subtree lifetime; it does not simulate native scroll layout.
vp run check:changedpassed formatting, lint, both knip passes, affected mobile/scripts typechecks, and both focused regression cases.- Rebased onto
1eb4071as24a9050.git range-diffconfirms the fix commit is unchanged, andvp run check:changedpassed again. Native captures below were taken before the rebase at2f24fc3. - Built and installed the matching Android development client (native fingerprint
715d920f6ef35b971b00ce6fcfedd0bbaea291bd) and verified on the Pixel 9 Pro Fold emulator: 1080×2424 cover and 2076×2152 inner displays, in the same green theme with synthetic usage history. - Before: folding and unfolding both reset Usage to Limits. After: both directions retain Usage, 7d, Tokens, and the selected Demo Usage environment. Opening the environment menu after unfolding confirmed that only Demo Usage remained checked.
- Scrolled the cover view, unfolded, and folded again. The returned content matched the original scrolled capture pixel-for-pixel across its 1080×1900 content region.
- The Android 15 emulator reported hinge changes without moving the app between displays, so it was excluded from fold/resize verification. The additional checks below use the working Android 17 foldable emulator. Web and desktop were not separately exercised; the source change is Android-specific.
| After unfolding | Before | After |
|---|---|---|
| Selected page and filters | Before: unfolding changes Usage to Limits | After: Usage, 7d, and Tokens remain selected |
Before recording · After recording · Retained environment filter
Scrolled cover view: before the round trip · after unfolding and folding.
Additional layout verification
The failure follows Android's compact/split boundary, rather than every relayout. The existing fix also handles freeform resizing; this expanded verification required no additional production changes.
| Transition | Result |
|---|---|
| Android freeform, 403×717 ↔ 811×801 dp | Original code resets Usage to Limits. The fix retains Usage, 7d, and Tokens in both directions. |
| Android portrait ↔ both landscape orientations | The fix retains Usage, 7d, and Tokens. A scrolled rotation round trip also returns identical content pixels in a 2152×1550 region. |
| iPhone Duo, 951×669 inner ↔ 466×678 cover | Usage, 7d, and Tokens remain selected on the unchanged iOS implementation. A separate scrolled fold round trip retains the visible content position. The CLI changes the display but its hinge-angle readback is unsupported, so the checks use actual viewport sizes and selected controls. |
| iPad fullscreen 1032×1376 → floating 375×524 | Usage, 7d, and Tokens remain selected on the unchanged iOS implementation. Rotating the floating window to landscape and back also retains them. |
| iPad floating 375×524 → fullscreen 1032×1376 | Usage, 7d, and Tokens remain selected. Computer Use expanded the same running app through the iPadOS green window control in Device Hub; no app relaunch or selection changes were needed. |
The iOS checks used matching native clients with fingerprint 552ed48c6dc6446fd6a057608ae67bffe81e7a3a. The tested iOS transitions did not reproduce the Android reset.
Android freeform: before recording · after recording · before narrow result · after narrow result.
Android rotation: landscape · scrolled content before and after the rotation round trip.
Duo: inner display · cover display · scrolled content before and after the fold round trip.
iPad: fullscreen · narrow window · landscape · expanded back to fullscreen.
Model: GPT-6.1 Sol | Harness: Codex in T3 Code
Checks
Approvability
Verdict: Approved at 2f24fc3
Macroscope's review found this PR approvable — This is a focused Android workspace bug fix that preserves the existing Usage subtree, filters, and scroll position across fold transitions while retaining layout-specific UI behavior. The added regression test is isolated to the React test configuration, with no production configuration or static-analysis overrides changed.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review.
External image Recent review info
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: main
- File: .coderabbit.config.ts
- Commit: 5b35402
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Advanced
- Run ID:
8b22b253-a973-470b-8dc3-e8dbd38df003
External image Commits
Reviewing files that changed from the base of the PR and between 5b35402623d7d1d88eaa472807272a6c2e78012a and 2f24fc36850c6ed869140e8a76b13b72b98365a0.
External image Files selected for processing: 3
apps/mobile/src/features/workspace/WorkspaceRootScreen.android.test.tsxapps/mobile/src/features/workspace/WorkspaceRootScreen.android.tsxapps/mobile/vite.config.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
Walkthrough
WorkspaceRootScreennow uses a shared render tree for split and non-split layouts. The screen adjusts its background, insets, clearance, tab content, and navigation by layout. An Android test checks that tab, filter, and scroll state persist through repeated split-view changes.Changes: Android workspace layout
Layer / File(s) Summary Shared layout and state preservation
apps/mobile/src/features/workspace/WorkspaceRootScreen.android.tsx,apps/mobile/src/features/workspace/WorkspaceRootScreen.android.test.tsx,apps/mobile/vite.config.tsThe screen selects layout, pull-request content, and navigation based on split-view state. The Android test checks that tab selection, filters, scroll container identity, and scroll position persist through repeated layout changes. The test is added to the React test configuration. Priority: External image Normal
Estimated code review effort: 2 (Simple) | ~15 minutes
Change: Bug fix
Suggested labels:
bugfix,📱 Native Change,size:SSuggested reviewers:
juliusmarminge
Merge Risk: External image Minimal · up to 2f24f
The layout change appears ready to merge after normal checks. The remaining native scroll-layout uncertainty does not establish a failure.
Pre-merge checks: Passed 4
Check name Status Explanation Linked Issues check Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request. Title check Passed The title "fix(mobile): preserve Android Usage state across layout changes" matches the main change. The PR keeps one workspace tab tree mounted across compact and split Android layouts, so Usage keep… Description check Passed The description follows the template's Problem, Change, Scope and approval, and Verification sections, and it is specific about the reproduction and results. The Problem section explains that switchin… Full details: Title check
Explanation
The title "fix(mobile): preserve Android Usage state across layout changes" matches the main change. The PR keeps one workspace tab tree mounted across compact and split Android layouts, so Usage keeps its page, filters, and scroll position. The title is specific, follows conventional commit form, and names the platform and the affected screen state.
Full details: Description check
Explanation
The description follows the template's Problem, Change, Scope and approval, and Verification sections, and it is specific about the reproduction and results. The Problem section explains that switching between compact and split Android layouts resets Usage to Limits and loses filters and scroll position, and it names the cause (separate component trees). The Change section explains the single mounted tab tree. The Scope section invokes a small bug-fix exception for an obvious Android state-loss bug, and it says the change is limited to the Android workspace root. The Verification section gives a regression test with before/after results, the check command outcomes, emulator fold testing with before/after evidence, and additional freeform, rotation, and iPad/Duo checks. It also states what was not verified (Android 15 emulator, iOS/web/desktop not exercised, the test does not simulate native scroll layout). Minor gaps: the Scope section does not link a triaged issue or maintainer approval, and it justifies the change as a small-bug-fix exception without a prior issue reference. The template asks for that justification explicitly, so it is addressed, though a reviewer may want an issue link or approval comment to confirm eligibility. The model and harness line is present at the end.
Finishing Touches
🧪 Generate unit tests (beta)
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
Added 1 commit
- fix(mobile): preserve Usage state when folding Android devices24a9050