Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c672c36
feat(mobile): plan mode (legacy) toggle with cross-client sync
Aug 14, 2026
0b1f719
fix(mobile): address review-bot findings
Aug 14, 2026
c04006b
fix(mobile): residual review findings from stacked PR triage
Aug 15, 2026
5068725
fix(mobile): address follow-up review findings
Aug 15, 2026
67df07d
fix(web): address review finding on synced settings hook
Aug 15, 2026
a28abf5
fix(mobile): bounded preference retry and stream compat
Aug 15, 2026
cef7f85
fix(mobile): retry exhausted preference reconciliation on next trigger
Aug 15, 2026
f842dd1
fix(mobile): guard stale settles in preference sync
Aug 15, 2026
54ca4bf
fix(web): keep adoption guard on inactive settles
Aug 15, 2026
bd13cef
refactor(mobile): simplify synced preference machinery
Aug 15, 2026
c37046e
fix(mobile): deterministic multi-env settle and read-only fallback
Aug 15, 2026
73f17e5
fix(mobile): per-field last-write-wins for synced preferences
Aug 15, 2026
ee1eec9
fix(mobile): monotonic write stamps
Aug 15, 2026
8786028
refactor(mobile): remove review-round slop
Aug 15, 2026
f187a21
fix(mobile): address review findings
Aug 15, 2026
e7ceaca
fix(mobile): preference write coherence and hydration gating
Aug 15, 2026
b9c3507
fix(mobile): stable reconciliation readiness under reconnects
Aug 15, 2026
4e90cc8
fix(mobile): gating coverage and share-transfer race
Aug 15, 2026
65b10cd
fix(mobile): settle reconciliation readiness semantics and secondary …
Aug 15, 2026
74c6466
fix(mobile): deterministic equal-stamp preference tiebreak
Aug 15, 2026
2a06432
fix(mobile): consistent hydration gate and read-only reconcile
Aug 15, 2026
33efe9c
fix(mobile): stamp preservation and retry budget semantics
Aug 15, 2026
4cf411d
fix(mobile): value-aware reconciliation watermark
Aug 15, 2026
f2de8bd
refactor(mobile): apply anti-slop lint pass
Aug 15, 2026
c717694
fix(sync): refresh Plan Mode preferences against main
amanthanvi Aug 20, 2026
a73aafe
fix(sync): make Plan Mode writes durable
amanthanvi Aug 20, 2026
f80b8a5
fix(sync): preserve reconciled preference state
amanthanvi Aug 20, 2026
5a02ceb
fix(web): wait for primary preference hydration
amanthanvi Aug 20, 2026
e8f7a72
fix(mobile): retain failed synced preferences
amanthanvi Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/mobile/src/Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import { NATIVE_LIQUID_GLASS_SUPPORTED } from "./native/native-glass";
import { nativeHeaderScrollEdgeEffects } from "./native/StackHeader";
import { FORM_SHEET_PRESENTATION_OPTIONS } from "./native/sheet-surface";
import { useThreadOutboxDrain } from "./state/use-thread-outbox-drain";
import { useSyncedClientPreferences } from "./state/synced-client-preferences";

const HEADER_SCROLL_EDGE_EFFECTS = nativeHeaderScrollEdgeEffects(Platform.OS, Platform.Version);

Expand Down Expand Up @@ -358,6 +359,11 @@ function ThreadOutboxDrainWorker() {
return null;
}

function SyncedClientPreferencesWorker() {
useSyncedClientPreferences();
return null;
}

function RootStackLayout(props: {
readonly children: React.ReactNode;
readonly state: NavigationState;
Expand Down Expand Up @@ -394,6 +400,7 @@ function RootStackLayout(props: {
return (
<HardwareKeyboardCommandProvider pathname={pathname}>
<ThreadOutboxDrainWorker />
<SyncedClientPreferencesWorker />
<ShowcaseCaptureCoordinator pathname={pathname} />
<ExistingThreadSettingsRouteProvider>
<AdaptiveWorkspaceLayout pathname={workspacePathname}>
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/src/components/AppSymbol.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const ANDROID_ICON_BY_SF_SYMBOL: Partial<Record<SFSymbol, Icon>> = {
"folder.badge.plus": IconFolderPlus,
"folder.fill": IconFolder,
gearshape: IconSettings,
hammer: IconHammer,
"info.circle": IconInfoCircle,
link: IconLink,
"line.3.horizontal.decrease.circle": IconFilter,
Expand Down
32 changes: 16 additions & 16 deletions apps/mobile/src/features/settings/SettingsRouteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { WorkspaceSidebarToolbar } from "../layout/workspace-sidebar-toolbar";
import { runtime } from "../../lib/runtime";
import { useThemeColor } from "../../lib/useThemeColor";
import { mobilePreferencesAtom, updateMobilePreferencesAtom } from "../../state/preferences";
import { useLegacyPlanModeEnabled } from "../threads/use-legacy-plan-mode-enabled";
import { useThreadListV2Enabled } from "../threads/use-thread-list-v2-enabled";
import {
type AppUpdateCheckState,
Expand All @@ -43,6 +44,7 @@ import {
runAppUpdateCheck,
} from "../updates/app-updates";
import { useSavedRemoteConnections } from "../../state/use-remote-environment-registry";
import { useUpdatePlanModePreference } from "../../state/synced-client-preferences";
import { SettingsRow } from "./components/SettingsRow";
import { SettingsSection } from "./components/SettingsSection";
import { SettingsSwitchRow } from "./components/SettingsSwitchRow";
Expand Down Expand Up @@ -548,37 +550,35 @@ function GeneralSettingsSection() {
);
}

/**
* Device-local legacy toggles. Mobile has no client-settings sync, so this is
* the counterpart of web's Settings → General → Legacy features backed by
* mobile preferences.
*/
function LegacySettingsSection() {
const savePreferences = useAtomSet(updateMobilePreferencesAtom);
const preferences = useAtomValue(mobilePreferencesAtom);
const updatePlanModePreference = useUpdatePlanModePreference();
const planModeEnabled = useLegacyPlanModeEnabled();
const threadListV2Enabled = useThreadListV2Enabled();
const planModeEnabled =
AsyncResult.isSuccess(preferences) && preferences.value.planModeEnabled === true;

return (
<View className="gap-3">
<SettingsSection title="Legacy">
<SettingsSwitchRow
icon="hammer"
label="Plan Mode (Legacy)"
value={planModeEnabled}
onValueChange={updatePlanModePreference}
/>
<SettingsSwitchRow
icon="sidebar.left"
label="Legacy Thread List"
value={!threadListV2Enabled}
onValueChange={(value) => savePreferences({ legacyThreadListEnabled: value })}
/>
<SettingsSwitchRow
icon="hammer"
label="Plan Mode"
value={planModeEnabled}
onValueChange={(value) => savePreferences({ planModeEnabled: value })}
/>
</SettingsSection>
<Text className="px-2 text-sm text-foreground-muted">
Opt into retired interfaces kept for compatibility. Plan Mode restores the Build/Plan
control; otherwise every task runs in Build mode.
Opt into retired interfaces kept for compatibility. Plan mode restores the Build/Plan
control and the /plan and /default commands; while off, every task uses default mode.
</Text>
<Text className="px-2 text-sm text-foreground-muted">
Brings back the original grouped thread list. The default list is flat, in creation order:
active work renders as cards; settled threads collapse to compact rows.
</Text>
</View>
);
Expand Down
Loading
Loading