feat(mobile): one sheet for model and thread settings - #5625
Conversation
Replaces the two nested native context menus in the composer with a single trigger pill and one bottom sheet: provider-grouped model list (logos, folds for non-primary providers, legacy behind a toggle), the selected model's options, runtime mode, and plan mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Formatting fixes plus a scrollable pinned-settings region so a model with many option descriptors can't push runtime/plan controls past the sheet's max height. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Needs human review This PR introduces a new settings sheet component with substantial new UI logic (~800+ lines), complex keyboard/focus coordination, and staged state management. The scope of new feature code warrants human review. Additionally, there is an unresolved finding about missing error handling for keyboard dismissal that could leave the sheet stuck. You can customize Macroscope's approvability policy. Learn more. |
Legacy models reset to hidden on every open behind a top-right show/hide pill, and the plan mode toggle is gone: threads build by default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Blur-during-settings-sheet told the parent the composer collapsed while it still rendered expanded, shrinking the feed inset underneath. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sheet is now just the model list with a Save button: reasoning, context window, and runtime each fold behind a compact disclosure row that opens an in-sheet submenu. Ultracode/ultrathink pseudo-efforts are no longer offered on mobile, and existing threads only list their own harness's models. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 0c9236e
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… staging Submenus open in a small panel on top of the sheet instead of replacing its content, so the sheet stops resizing while drilling in and out. The settings rows now stay editable while a model is staged: they show the staged model's options and Save applies model plus options in one write (the draft flow previously clobbered a staged model when options followed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Legacy models never force-show (a selected legacy model is exempted from the filter individually), the keyboard only returns after the sheet if it was up beforehand, settings rows render as a stable union across primary harnesses with unsupported rows disabled instead of vanishing, and a project's implicit last-used default never resolves to a legacy model (explicit picks still stick). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Any dismissal of the thread settings sheet (backdrop, grabber, or a tap that lands just outside a control like the legacy pill) closed the sheet and refocused the composer, popping the keyboard unexpectedly. Dismissals now close quietly; only the explicit Save/Done button brings the keyboard back. The legacy pill also gets hitSlop so near-misses land on it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a056b34. Configure here.
| return; | ||
| } | ||
| setPhase("visible"); | ||
| }); |
There was a problem hiding this comment.
Sheet stuck after dismiss failure
High Severity
open only moves to visible inside KeyboardController.dismiss().then, with no rejection path. Elsewhere in mobile (ThreadDetailScreen) dismiss failures are handled with .catch. If dismiss rejects here, phase stays opening, isActiveRef stays true, the modal never appears, and later open calls no-op, so thread settings stay unavailable and the composer can remain expanded until remount.
Reviewed by Cursor Bugbot for commit a056b34. Configure here.
## What's Changed * fix(desktop): zoom shortcuts no longer die when the preview browser has focus by @t3dotgg in pingdotgg/t3code#5691 * feat(mobile): one sheet for model and thread settings by @t3dotgg in pingdotgg/t3code#5625 * feat(usage): usage page reading provider transcripts across environments by @t3dotgg in pingdotgg/t3code#5684 **Full Changelog**: pingdotgg/t3code@v0.0.33-nightly.20260808.1031...v0.0.33-nightly.20260808.1033 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.33-nightly.20260808.1033
…224) * fix(desktop): zoom shortcuts no longer die when the preview browser has focus (pingdotgg#5691) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(mobile): one sheet for model and thread settings (pingdotgg#5625) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(usage): usage page reading provider transcripts across environments (pingdotgg#5684) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(desktop): zoom shortcuts no longer die when the preview browser has focus (pingdotgg#5691) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(mobile): one sheet for model and thread settings (pingdotgg#5625) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat(usage): usage page reading provider transcripts across environments (pingdotgg#5684) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Theo Browne <me@t3.gg> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: aaditagrawal <aaditagrawal@users.noreply.github.com>
Adopts the three upstream commits after #381: a cross-environment usage page reading provider transcripts (pingdotgg#5684), its chart fix (pingdotgg#5697), and one mobile sheet for model and thread settings (pingdotgg#5625). Resolutions: - server.ts / ws.ts / client-runtime state: upstream's UsageService and its usageSummary atom family are additive next to the fork's diagnostics services (HostResourceProbe, ProcessResourceMonitor, TraceDiagnostics, BackgroundPolicy) and hostResourceSnapshot family — unioned. - ThreadComposer: pingdotgg#5625 folds the model picker and provider options into a single settings sheet, replacing the fork's ControlPillMenu. The sheet is adopted, and the fork's usage signal rides on it: the trigger keeps ProviderUsageIcon with the live marker rather than upstream's plain ProviderIcon, so quota state stays visible at a glance. The fork-only collapsed-composer pill (upstream has none) now opens the same sheet instead of the retired menu. Adversarial review caught that retiring the model menu also orphaned the fork's numeric usage note: the marker survived on the trigger icon but the quota percentage the menu rows carried had no home. It now hangs off the trigger label, so both halves of the fork's usage signal survive the consolidation. The plain ProviderIcon import went with upstream's replaced icon. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
apps/mobile/src/features/threads/composerSendLabel.ts is a logic mirror and was not on the mirrors table. It does not merely duplicate upstream logic -- it replaced four upstream lines in ThreadComposer.tsx with a call, which is the more dangerous shape: a future upstream edit to those three conditions lands nowhere, because the lines that held them are gone. Nothing conflicts and nothing fails. Re-verified against the follow-up merge-base. pingdotgg#5625 rewrote ThreadComposer.tsx end to end (-124/+57) and left the ternary's conditions alone, so the helper is still byte-equivalent to what it replaced.
The 2026-08-08 sync ran in two passes. This is the second: four more upstream commits (usage page pingdotgg#5684 + chart fix pingdotgg#5697, mobile settings sheet pingdotgg#5625, desktop zoom-shortcut fix pingdotgg#5691), merge-base a20923c. Only two rows moved on the file-list half. ThreadComposer.tsx went +26/-4 to +27/-4 because pingdotgg#5625 rewrote the file around the fork's edit and the resolution re-attaches the line-break button to upstream's new single settings trigger. pnpm-lock.yaml went +196/-143 to +317/-737, which is PR #63's repair showing up rather than new churn. That second number is the reason the lockfile note grew a paragraph. The first pass resolved all three lock conflicts with --ours and ran pnpm install --lockfile-only, which preserves any existing pin that still satisfies the semver range instead of floating to the newest -- so seeding from upstream's lock silently discarded the security sweep and reopened 21 Dependabot alerts. The overrides: block survived byte-identical and did not save it. Seed from the fork's pre-sync lock. Churn and risk are regenerated in the same commit, so both halves of the ledger agree on one merge-base. server.ts churn 32 to 33.
apps/mobile/src/features/threads/composerSendLabel.ts is a logic mirror and was not on the mirrors table. It does not merely duplicate upstream logic -- it replaced four upstream lines in ThreadComposer.tsx with a call, which is the more dangerous shape: a future upstream edit to those three conditions lands nowhere, because the lines that held them are gone. Nothing conflicts and nothing fails. Re-verified against the follow-up merge-base. pingdotgg#5625 rewrote ThreadComposer.tsx end to end (-124/+57) and left the ternary's conditions alone, so the helper is still byte-equivalent to what it replaced.
## What's Changed * fix(mobile): reconnects no longer shift the thread list by @t3dotgg in pingdotgg/t3code#5372 * feat(web): drag pinned threads into your own order by @t3dotgg in pingdotgg/t3code#5581 * chore(ci): vouch StiensWout by @t3-code[bot] in pingdotgg/t3code#5637 * feat(desktop): remember recently used sites in the Browser panel by @chrisdeeming in pingdotgg/t3code#5270 * chore: vouch chrisdeeming by @t3-code[bot] in pingdotgg/t3code#5641 * feat(web): make sidebar artwork theme-aware by @maria-rcks in pingdotgg/t3code#5636 * fix(web): reconnect the composer seam for remote non-Git projects by @caezium in pingdotgg/t3code#5633 * fix(web): show Stop button while input is pending by @ipanasenko in pingdotgg/t3code#5554 * feat(web): fold plan mode and token-by-token output into Legacy features by @t3dotgg in pingdotgg/t3code#5664 * feat: sidebar v2 is now the default sidebar by @t3dotgg in pingdotgg/t3code#5672 * fix(server): stop PR status lookups amplifying GitHub rate limits by @t3dotgg in pingdotgg/t3code#5673 * fix(web): delay transient reconnect warnings by @t3-code[bot] in pingdotgg/t3code#5670 * fix(web): inherit terminal size in simple typography by @chrisdeeming in pingdotgg/t3code#5628 * fix(server): stop the reaper from silently killing live background subagents by @t3dotgg in pingdotgg/t3code#5677 * fix(desktop): zoom shortcuts no longer die when the preview browser has focus by @t3dotgg in pingdotgg/t3code#5691 * feat(mobile): one sheet for model and thread settings by @t3dotgg in pingdotgg/t3code#5625 * feat(usage): usage page reading provider transcripts across environments by @t3dotgg in pingdotgg/t3code#5684 * fix(web): usage chart no longer makes Claude look like the bigger spender by @t3dotgg in pingdotgg/t3code#5697 * fix(web): persist diff view mode by @leorivastech in pingdotgg/t3code#5731 * feat(web): show how many subagents are running at a glance by @t3dotgg in pingdotgg/t3code#5745 * fix(web): add missing cursor-pointer styling to dropdowns and interactive buttons by @naMqe-h in pingdotgg/t3code#5716 * fix(server): stop Claude resume handshakes from completing turns that never ran by @gfsaaser24 in pingdotgg/t3code#5710 * chore: vouch gfsaaser24 by @t3dotgg in pingdotgg/t3code#5761 * chore: vouch saphid by @t3dotgg in pingdotgg/t3code#5763 * fix(server): stop Codex threads with queued follow-ups by @t3dotgg in pingdotgg/t3code#5762 * fix(web): usage page loses the cost quality panel, gains a back button by @t3dotgg in pingdotgg/t3code#5756 * feat(server): agents can now open the images you paste into chat by @t3dotgg in pingdotgg/t3code#5757 * fix(web): pinned reorder no longer reshuffles while writes land by @t3dotgg in pingdotgg/t3code#5767 * feat(web): overhaul project settings into a real settings page by @t3dotgg in pingdotgg/t3code#5768 * fix(web): usage totals no longer jump while devices report in by @t3dotgg in pingdotgg/t3code#5772 * fix(server): settle no longer leaves monitors and dev servers running by @t3dotgg in pingdotgg/t3code#5774 * feat: pick worktree or current checkout per project by @t3dotgg in pingdotgg/t3code#5766 * fix(web): sidebar rows show the branch again, not a truncated plan step by @t3dotgg in pingdotgg/t3code#5776 * feat(server): vp run migrate-dev-db seeds worktree dev dbs with real data by @t3dotgg in pingdotgg/t3code#5773 * feat(web): keep unsent drafts one click away in the sidebar by @t3dotgg in pingdotgg/t3code#5777 * feat(web): project icons can be chosen manually by @t3dotgg in pingdotgg/t3code#5775 * fix(server): one greedy agent process no longer takes down the whole server by @t3dotgg in pingdotgg/t3code#5788 * ci: label-gated hosted-web preview deploys by @t3dotgg in pingdotgg/t3code#5465 * Add cross-platform mobile usage dashboard by @juliusmarminge in pingdotgg/t3code#5743 * fix(web): preserve desktop route during Clerk auth by @wobsoriano in pingdotgg/t3code#5770 * fix(web): match create theme and import theme buttons to the standard outline style by @UtkarshUsername in pingdotgg/t3code#5860 * fix(server): favicon resolution no longer pins the event loop by @murenovich in pingdotgg/t3code#5538 * fix(shared): bound the file-link label so bracket runs stop rescanning by @tsouth89 in pingdotgg/t3code#5782 * fix(web): thread title button no longer eats the drag area by @nathangerday in pingdotgg/t3code#5857 * fix(web): unify usage page chrome by @t3-code[bot] in pingdotgg/t3code#5823 * fix(shell): add ~/.local/bin to the Windows CLI resolver so native-installed providers are found by @arhxam in pingdotgg/t3code#5074 * fix(web): match settings search shortcut styling to command palette's by @UtkarshUsername in pingdotgg/t3code#5841 * fix(mobile): long-pressing a thread row no longer navigates into the thread by @juliusmarminge in pingdotgg/t3code#5901 * fix(server): usage no longer double-counts forked Codex sessions by @t3dotgg in pingdotgg/t3code#5887 * fix(server): sandbox user-provided SVGs by @t3dotgg in pingdotgg/t3code#5916 * fix(web): match usage titlebar text styling by @t3-code[bot] in pingdotgg/t3code#5897 * Move project settings to contextual project routes by @juliusmarminge in pingdotgg/t3code#5923 * Retain thread sidebar data when navigating to /settings so back navigation is instant by @juliusmarminge in pingdotgg/t3code#5930 * Automate production mobile EAS releases by @juliusmarminge in pingdotgg/t3code#5609 * Add settings and usage breadcrumbs by @juliusmarminge in pingdotgg/t3code#5929 * fix(web): correct model picker trigger padding by @Chrono-byte in pingdotgg/t3code#5935 * fix(web): show worktree icon in sidebar v2 by @tris203 in pingdotgg/t3code#5909 * fix(web): enable restore defaults after theme mix changes by @Lucenx9 in pingdotgg/t3code#5928 * fix(web): trait menu closes after you pick a level by @t3dotgg in pingdotgg/t3code#5879 * fix(web): align project name with headline by @carterwsmith in pingdotgg/t3code#5864 * fix(web): update pills use readable theme foregrounds by @chrisdeeming in pingdotgg/t3code#5938 * fix(web): use themed confirmation dialogs by @StiensWout in pingdotgg/t3code#5624 * fix(web): use import/export-appropriate icons for theme buttons by @UtkarshUsername in pingdotgg/t3code#5964 * fix(mobile): detect PowerShell cmdlet errors in work log rows by @myacoub91 in pingdotgg/t3code#5726 * fix(mobile): stop Android user bubbles with code blocks from overlapping by @Brechard in pingdotgg/t3code#5659 * fix(mobile): parse EAS fingerprint JSON by @juliusmarminge in pingdotgg/t3code#5991 ## New Contributors * @chrisdeeming made their first contribution in pingdotgg/t3code#5270 * @wobsoriano made their first contribution in pingdotgg/t3code#5770 * @murenovich made their first contribution in pingdotgg/t3code#5538 * @tsouth89 made their first contribution in pingdotgg/t3code#5782 * @nathangerday made their first contribution in pingdotgg/t3code#5857 * @carterwsmith made their first contribution in pingdotgg/t3code#5864 * @myacoub91 made their first contribution in pingdotgg/t3code#5726 **Full Changelog**: pingdotgg/t3code@v0.0.32...v0.0.33 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.33
The 2026-08-08 sync ran in two passes. This is the second: four more upstream commits (usage page pingdotgg#5684 + chart fix pingdotgg#5697, mobile settings sheet pingdotgg#5625, desktop zoom-shortcut fix pingdotgg#5691), merge-base a20923c. Only two rows moved on the file-list half. ThreadComposer.tsx went +26/-4 to +27/-4 because pingdotgg#5625 rewrote the file around the fork's edit and the resolution re-attaches the line-break button to upstream's new single settings trigger. pnpm-lock.yaml went +196/-143 to +317/-737, which is PR #63's repair showing up rather than new churn. That second number is the reason the lockfile note grew a paragraph. The first pass resolved all three lock conflicts with --ours and ran pnpm install --lockfile-only, which preserves any existing pin that still satisfies the semver range instead of floating to the newest -- so seeding from upstream's lock silently discarded the security sweep and reopened 21 Dependabot alerts. The overrides: block survived byte-identical and did not save it. Seed from the fork's pre-sync lock. Churn and risk are regenerated in the same commit, so both halves of the ledger agree on one merge-base. server.ts churn 32 to 33.
apps/mobile/src/features/threads/composerSendLabel.ts is a logic mirror and was not on the mirrors table. It does not merely duplicate upstream logic -- it replaced four upstream lines in ThreadComposer.tsx with a call, which is the more dangerous shape: a future upstream edit to those three conditions lands nowhere, because the lines that held them are gone. Nothing conflicts and nothing fails. Re-verified against the follow-up merge-base. pingdotgg#5625 rewrote ThreadComposer.tsx end to end (-124/+57) and left the ternary's conditions alone, so the helper is still byte-equivalent to what it replaced.


Changing the model on mobile meant drilling through nested native context menus: provider submenu, then model, with effort and runtime hiding in a second menu. No search, no overview, and every provider doubled its menu length with a "legacy models" submenu.
Now the composer has one pill that shows the whole thread setup ("Claude Fable 5 · Max · 1M · Auto") and opens a single bottom sheet:
Verified end to end on the iOS Simulator and on-device: model staging and save (with staged option edits carried through), folds, legacy pill, submenu apply, runtime changes, summary pill updates, light and dark.
Built by Claude Fable 5 running in Claude Code.
Note
Consolidate model and thread settings into a single sheet in the mobile composer
NewTaskDraftScreenandThreadComposerwith a single 'Thread settings' toolbar trigger that opens a unifiedThreadSettingsSheetmodal.threadSettingsSummaryLabelutility composes a compact summary string (model, options, runtime mode) displayed on the trigger pill.useThreadSettingsSheetPresentationcoordinates keyboard dismissal on open and restores editor focus only when the sheet is closed via Save, not on dismiss.resolveDefaultableModelSelectionprevents implicit defaults from resolving to legacy models;applyProviderOptionSelectionreplaces menu-event-string parsing with typed, validated selection updates.Macroscope summarized a056b34.
Note
Medium Risk
Touches core composer model/runtime selection and draft default resolution; staging and keyboard/focus timing add UX edge cases but changes are localized to mobile thread UI.
Overview
Replaces nested native model/configuration menus in the new-task draft and thread composer with one toolbar pill (summary like
Model · Max · Auto) that opens aThreadSettingsSheetmodal.The sheet adds a scrollable, provider-grouped model list (primary harnesses expanded, large catalogs foldable, legacy behind a toggle), staged model picks applied on Save/Done, and disclosure submenus for provider options and runtime. Open threads only see models from their current harness; new tasks still get all providers. Plan/interaction mode is no longer in the sheet—only reflected in the summary when already in plan mode (
/planunchanged).Presentation plumbing:
useThreadSettingsSheetPresentationdismisses the custom composer keyboard before showing the modal, keeps Android/iOS composer expanded while the sheet is open, and restores focus only after Save, not backdrop dismiss.Selection defaults:
resolveDefaultableModelSelectionstops implicit project last-used defaults from landing on legacy models; draft picks stay explicit.setSelectedModelKeycan apply model + options in one write when saving a staged change.Cleanup: Removes
buildModelMenuActionsand menu-event provider option helpers in favor of direct selection APIs and tests for staging behavior.Reviewed by Cursor Bugbot for commit a056b34. Bugbot is set up for automated code reviews on this repo. Configure here.