Repository navigation
fix(mobile): center Android sheets and fit book-mode sheets in the left pane - #18492
Conversation
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — This change introduces a custom Android navigation/presentation layer and restructures workspace rendering so bottom sheets can cover the entire workspace, alongside a native screen dependency update. Because it affects existing navigation, mounting, layout, and dismissal behavior across Android, the runtime impact warrants human review. Notes:
You can add or adjust custom eligibility rules. Learn more. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Route projection and tests apps/mobile/src/native/workspace-stack-projection.ts, apps/mobile/src/native/workspace-stack-projection.test.ts |
projectStackPresentation splits routes at the first overlay. Tests cover review-sheet routes, Back navigation, grouped sheet pages, and cold-linked detail history. |
Presentation context and column renderer apps/mobile/src/features/layout/workspace-presentation-context.tsx, apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx |
The adaptive layout reads the presentation-host context. It provides its column renderer through context when hosted and renders the columns directly otherwise. |
Android navigator integration apps/mobile/src/features/layout/createWorkspaceStackNavigator.android.tsx, apps/mobile/package.json |
The Android navigator renders workspace routes in the columns and overlays above the base descriptor. The react-native-screens tarball changes from t3.45 to t3.46. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant AdaptiveWorkspaceLayoutContent
participant WorkspaceStackNavigator
participant WorkspaceStackView
participant projectStackPresentation
participant renderColumns
AdaptiveWorkspaceLayoutContent->>WorkspaceStackNavigator: provide renderColumns through context when hosted
WorkspaceStackNavigator->>WorkspaceStackView: render navigation state
WorkspaceStackView->>projectStackPresentation: split routes at first overlay
projectStackPresentation-->>WorkspaceStackView: return workspace routes and overlays
WorkspaceStackView->>renderColumns: render workspace routes
WorkspaceStackView->>WorkspaceStackView: place overlays above the base descriptor
Suggested reviewers: juliusmarminge
Merge Risk: 
Minimal · up to 7005d
-
No actionable merge-blocking risk is established; native runtime checks remain useful follow-up validation.
Security architecture risk: 
Low · up to e2066
-
The change is confined to Android navigation and sheet presentation. The inspected code preserves existing route identities and dismissal controls, with no demonstrated expansion of access or privileges. Some rapid-transition and nested-dismissal behavior remains unverified on Android.
Retained concerns
No architecture-level concerns identified.Security review details
-
Security Blast Radius
- inferred — The supported exposure is shared Android presentation behavior: workspace-wide routed overlays and Android form sheets using either patched native implementation. A regression could therefore affect multiple screens, but the inspected changes do not grant new service, tenant, credential, or data-store authority.
Trust Boundaries and Controls
- observed — The synthetic workspace route is a rendering container, not a replacement identity for overlay actions. Production dismissal uses the real descriptor route key and current owning router key; Android legacy dismissal emits a count of one.
Resilience and Maintainability Implications
- observed — Tests cover helper-level identity and ordering, ordinary back navigation, grouped dismissal, and cold-linked history. These tests do not render the new Android presentation envelope, so they do not prove native grouped-dismissal, interruption, or rapid-repeat behavior.
-
Pre-merge checks: 
4
-
Full details: Title check
-
Explanation
The title "fix(mobile): center Android sheets and fit book-mode sheets in the left pane" follows conventional commit form and names the two main changes: centering Android routed sheets and fitting sheets in the left pane in book mode. The objectives describe centering sheets across the workspace, and the description adds book-mode fitting, so the title matches the changeset. It is slightly long at 76 characters, but it is specific and not vague.
Full details: Description check
-
Explanation
The description covers the problem (routed sheets confined to the detail pane on unfolded Android), the change (presenting sheets over the whole workspace, centered sizing, book-mode fitting to the left pane), and extensive verification (device captures, native test counts, emulator checks, and explicit unverified items). It also links the scope context to PR
#18492and related comments. The template's 'Scope and approval' section is not explicitly filled in: it does not state a linked triaged bug issue or maintainer approval, and it only references a prior comparison comment. The description also mixes in a lot of branch, commit, and dependency detail (merge hashes, a tag, a fork source link) that the template does not ask for. Overall the description is mostly complete, but the scope and approval section needs a clear link to the triaged issue or maintainer approval.Resolution
Consider adding an explicit link to the triaged bug issue or the maintainer approval comment in the 'Scope and approval' section. Trim the merge and fork-tag details if they are not needed for review.
-
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.
5020e62 to
e206621
Compare
|
Note Written by @PixPMusic, thank you for putting the sheet host around the whole workspace and preserving the original route descriptors. I kept that implementation and your commit, then merged current main without rebasing. The change is now five mobile source/test files. I removed the native width patch, its Kotlin tests and dependency/lockfile changes: the backdrop defect needs a workspace-sized presentation host, while a new 640dp width policy is a separate design decision. Native sheet sizing now stays at its existing defaults. Main's rail overlay, compact Settings navigation, safe areas, settled content widths and inspector behavior are retained. I also simplified the renderer and tightened its return type. Passed on Unverified: actual Android presentation, full-workspace tap interception, compact/wide sizing, keyboard, Back/dismiss and resizing. This VM has no attached Android device, and the device tool reports "Agent device access is turned off for this environment." Chrome cannot exercise native ScreenStacks, so I have no current-main/current-head screenshots or interaction video. The older evidence in the description predates this reduced implementation and does not verify this head. Please run those native checks before merging. Two independent GPT-6.1-Sol reviews of this exact head found no actionable code findings. Both leave native interaction verification as the remaining blocker. |
|
Picking up the Android validation pass from Maria’s latest head. I’m going to merge current main into this branch, preserve the reduced workspace presentation-host implementation, and run native Android checks on the unfolded inner display and folded cover screen. I’ll check full-workspace backdrop/tap interception, compact and wide sizing, keyboard behavior, Back/dismissal, and fold/resizing transitions, then upload fresh screenshots and interaction evidence here with a follow-up validation comment. The existing native sheet width defaults will stay intact; this pass is intended to get the remaining native validation done for the merge window. |
…rent-main-validation
|
First current-main validation pass, before the requested sizing follow-up: merged Native Android 17 foldable, inner 2076×2152 and cover 1080×2424, using synthetic demo data:
Backdrop interaction recording · Same thread after backdrop dismissal |
|
Second native validation pass on Routed Android sheets now match the standalone FormSheet/photo-library presentation Alex requested: bottom-anchored, centered across the whole workspace, and limited by Material’s existing 640dp maximum width. Compact windows use the available width. The native change is published at c49845fd in the Screens source fork, packaged as Passed on the rebuilt Android 17 client (
The flat Duo image below is a visual comparison, not a full Apple regression matrix. The packaged iOS, C++ and library JS payloads are byte-identical to Remaining validation gap: the emulator did not display an on-screen IME when fields were focused, so keyboard lift/keyboard-first Back remain unverified. Text editing, draft retention, ordinary Back and dismissal were checked. Physical devices and landscape were not tested.
Backdrop interaction video · Branches · Cover screen with draft · Same draft after unfolding · Verification details |
|
Follow-up on The navigator marks actual form-sheet routes so their shared Android header draws the grip in its existing top padding, using embedded header spacing without a camera inset or a second handle row. Standalone FormSheets retain their own native grabber and reset that route context to avoid duplicates. Commit now uses the existing Native Android 17 checks on this head: Commit and Branches captured on unfolded inner (2076×2152) and folded cover (1080×2424) displays. Centered/wide and compact sizing remain correct; dragging down from the grip dismisses the native sheet. Header cancel, Android Back/reopen, file-selection toggle/restore and draft preservation across unfolding passed. No Apple regression matrix repeated. The shared Commit wrapper returns its children unchanged on iOS; the new header and route-context behavior is Android-only. Earlier IME/physical-device/landscape validation gaps remain as documented.
Commit cover screen · Branches inner · Branches cover · Drag from grip to dismiss |
…rent-main-validation # Conflicts: # apps/mobile/src/components/ui/Sheet.android.tsx # apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx
|
Merged current main ( Confirmed on the Duo: with the book hinge active, native Commit presents in the left half. Android now follows that rule for both routed sheets and standalone FormSheets. The entire frame, grip and React content fit within the left pane; the sheet no longer just moves left while remaining too wide. Unfolding restores the centered Material width. The backdrop still intercepts touches across the full workspace. Fresh native Android validation passed: flat → book → flat, opening already bent, selection preservation, Commit draft/file-selection preservation across cover and unfolding, right-side backdrop dismissal, header dismissal, and the merged One UI preference.
Fold/unfold video with selection preserved · One Duo comparison · Cover · One UI · Verification details. Synthetic fixtures only. No new full iPhone/iPad regression matrix; Duo is the placement reference. Runtime landscape and keyboard/IME behavior are not newly verified. PR description updated with the current implementation and evidence. Model: GPT-6.1 Sol (high reasoning) | Harness: Codex |
|
Follow-up from Alex’s physical Pixel foldable test on The recording shows Branches & worktrees centered when flat, resizing fully into the left pane with the portrait book hinge active, and returning to the centered layout when unfolded. This is the T3 Code Dev APK with embedded JS, running without Metro and with OTA updates disabled. Physical Pixel recording — flat/book transitions (MP4) Device name obscured for the public recording; the sheet behavior is unchanged. |
## What's Changed * fix(mobile): center Android sheets and fit book-mode sheets in the left pane by @PixPMusic in pingdotgg/t3code#18492 * fix(mobile): keep the collapsed Android rail square by @PixPMusic in pingdotgg/t3code#26039 * fix(web): closing the last Browser tab hides the right panel again by @juliusmarminge in pingdotgg/t3code#26058 * refactor(web): pull requests Cmd+F focuses the topbar search directly by @juliusmarminge in pingdotgg/t3code#26045 * refactor(web): install draft model reconciliation at app start by @juliusmarminge in pingdotgg/t3code#26046 * perf(mobile): project favicons mount their image in one commit by @juliusmarminge in pingdotgg/t3code#26047 * refactor(web): the upload queue alone records finished file uploads on drafts by @juliusmarminge in pingdotgg/t3code#26050 * feat(mobile): Usage uses the width on iPad and unfolded phones by @juliusmarminge in pingdotgg/t3code#26061 * fix(gitcafe): PR panel follows renumbered pull requests by @juliusmarminge in pingdotgg/t3code#26079 * chore(infra): bump Alchemy to 2.0.0-beta.84 by @juliusmarminge in pingdotgg/t3code#26057 * refactor(mobile): stop writing the resolved project filter back from an effect by @juliusmarminge in pingdotgg/t3code#26049 * fix(mobile): a pairing link fills the open Add environment form instead of stacking another by @juliusmarminge in pingdotgg/t3code#26052 * fix(mobile): snooze menu times advance with the clock by @juliusmarminge in pingdotgg/t3code#26043 * fix(clients): prompt links find projects cloned from git.cafe by @juliusmarminge in pingdotgg/t3code#26042 * fix(server): retry Codex capacity failures with empty input by @Yash-Singh1 in pingdotgg/t3code#25611 * fix(server): recover handoffs when target context is exhausted by @Yash-Singh1 in pingdotgg/t3code#25610 * fix(web): chips drop their pill and stay readable on every theme by @flamboh in pingdotgg/t3code#25066 * fix(mobile): switching pull request tabs no longer jumps the page by @flamboh in pingdotgg/t3code#26064 * feat(mobile): report crashes to Axiom with symbolicated stacks by @gabrielelpidio in pingdotgg/t3code#19093 * fix(web): chip palette test follows the single design by @juliusmarminge in pingdotgg/t3code#26131 * feat(server): /mcp narrows a client's modes from T3-Mode-Limit by @juliusmarminge in pingdotgg/t3code#16653 * feat(server): t3_thread_launch takes clientRequestId by @juliusmarminge in pingdotgg/t3code#16654 * feat(server): link to another environment by @juliusmarminge in pingdotgg/t3code#16655 * feat(server): agents use linked environments through any T3 tool by @juliusmarminge in pingdotgg/t3code#16684 * feat(server): work a linked environment starts stays within its link by @juliusmarminge in pingdotgg/t3code#16695 * feat(web,mobile): linked environments in Connections by @juliusmarminge in pingdotgg/t3code#16698 * feat(server): delegate_task to a linked environment by @juliusmarminge in pingdotgg/t3code#16719 * feat(server,web,mobile): an agent sets up a link to another environment by @juliusmarminge in pingdotgg/t3code#17129 * feat(server,web,mobile): @-mention a machine, and linked environments become a Labs beta by @juliusmarminge in pingdotgg/t3code#17130 * fix(mobile): dragging a microphone or environment route now saves its new place by @juliusmarminge in pingdotgg/t3code#26096 * feat(web): channel artwork choice on Latest, plus nightly or dev art on any channel by @maria-rcks in pingdotgg/t3code#26138 * feat(mobile): browse ZIP attachments with the shared archive reader by @Bil0000 in pingdotgg/t3code#19463 * fix(server): Claude --settings launch args merge with T3's settings instead of being dropped by @t3dotgg in pingdotgg/t3code#22864 * feat(server,web): see and stop the dev servers a thread started by @t3dotgg in pingdotgg/t3code#22542 * fix(web): composer no longer jumps when a second line is added by @maria-rcks in pingdotgg/t3code#26155 * feat(web,mobile): queued messages show who sent them by @juliusmarminge in pingdotgg/t3code#26159 * fix(preview): agent and browser panel show the same page after a late desktop attach by @t3dotgg in pingdotgg/t3code#22877 * fix(web): pairing, connect, error, and Clerk sign-in surfaces match the app's dialog style by @maria-rcks in pingdotgg/t3code#25281 * fix(server): parallel worktree launches no longer fail on .git/config lock by @juliusmarminge in pingdotgg/t3code#25700 * fix(task-cache): the hook test waits for every flusher it starts by @juliusmarminge in pingdotgg/t3code#26148 * chore(lint): every React effect states its reason at the call site by @juliusmarminge in pingdotgg/t3code#26161 * test(server): the link-card retry test names a new MCP credential by @juliusmarminge in pingdotgg/t3code#26143 * perf(web): stop measuring table cells while replies stream by @t3dotgg in pingdotgg/t3code#26152 * feat(desktop): add a remote server by clicking its t3code://pair link by @t3dotgg in pingdotgg/t3code#24111 * fix(server): agent questions stay answerable after a server restart by @SunkenInTime in pingdotgg/t3code#19229 * chore(lint): the effect lint error walks the alternatives before the suppression by @juliusmarminge in pingdotgg/t3code#26181 * fix(web): settings avatar no longer hugs the modal corner by @t3dotgg in pingdotgg/t3code#26180 * fix(mobile): shared file names can no longer write outside the Android cache by @juliusmarminge in pingdotgg/t3code#26175 * fix(server): repository lookups no longer send GitHub tokens to arbitrary hosts by @juliusmarminge in pingdotgg/t3code#26176 * fix(github): long period runs no longer freeze reference autolinking by @juliusmarminge in pingdotgg/t3code#26177 * fix(mobile): Android diff ellipsis no longer measures text quadratically by @juliusmarminge in pingdotgg/t3code#26174 * fix(server): Codex works again after its app-server is killed by @t3dotgg in pingdotgg/t3code#26188 **Full Changelog**: pingdotgg/t3code@v0.1.4-nightly.20261027.3783...v0.1.4-nightly.20261027.3796 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.4-nightly.20261027.3796








On unfolded Android, routed sheets are confined to the detail pane, leaving the rail and list outside their backdrop. Present them over the whole workspace and use Material’s 640dp maximum width, centered and bottom-anchored. Compact and cover screens fill their available width.
With an active vertical hinge in portrait book mode, both routed sheets and standalone FormSheets now fit inside the physical left pane, matching the Duo’s native presentation. Folding updates the sheet frame and React content together; unfolding restores centered sizing without losing form state. The backdrop continues to cover the whole workspace. Grips and rounded inner headers are preserved.
Merged main
dc84b0962e, resolving conflicts with #18547 and the Samsung/One UI navigation changes while retaining Maria’s workspace presentation host. Current head:f8e85a257e. Android native changes are published as Screens5.0.0-t3.48: source, tag. Its iOS/C++/JS payloads are unchanged from the previous archive.Validation
Native Android 17 foldable: both sheet implementations fit within the left 1038px of the 2076px portrait display. Flat/book transitions, opening already bent, restored centered width, cover sizing, selection/draft preservation, full-workspace backdrop dismissal, header dismissal and the One UI preference passed. One Duo Commit capture confirms the left-side reference. Synthetic demo fixtures only.
vp run check:changedpassed, including 27 focused tests; four native placement tests passed. Rebuilt and exercised the native Android client. Landscape placement is unit-tested; no new runtime landscape or full iPhone/iPad matrix is claimed. Keyboard lift/keyboard-first Back remain unverified because the emulator did not show an on-screen IME.Fold/unfold video · Cover · One UI · Native Android photo-library reference · Verification details
Original main/PR comparison and validation.
Model: GPT-6.1 Sol (high reasoning) | Harness: Codex