From 04b3e666d6d517b026522de76fe83ae6dc40d163 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 17 Sep 2026 19:21:12 -0700 Subject: [PATCH] refactor(mobile): share settings choice row defaults --- .../settings/SettingsFollowUpRouteScreen.tsx | 38 +++----------- .../settings/SettingsKeyboardRouteScreen.tsx | 38 +++----------- .../SettingsProjectGroupingRouteScreen.tsx | 38 +++----------- .../SettingsServerControlsRouteScreen.tsx | 52 ++----------------- .../settings/components/SettingsChoiceRow.tsx | 41 +++++++++++++++ 5 files changed, 69 insertions(+), 138 deletions(-) create mode 100644 apps/mobile/src/features/settings/components/SettingsChoiceRow.tsx diff --git a/apps/mobile/src/features/settings/SettingsFollowUpRouteScreen.tsx b/apps/mobile/src/features/settings/SettingsFollowUpRouteScreen.tsx index 9f801c872c96..aa12849c1f39 100644 --- a/apps/mobile/src/features/settings/SettingsFollowUpRouteScreen.tsx +++ b/apps/mobile/src/features/settings/SettingsFollowUpRouteScreen.tsx @@ -1,15 +1,15 @@ import { useAtomSet, useAtomValue } from "@effect/atom-react"; import { useNavigation } from "@react-navigation/native"; import { AsyncResult } from "effect/unstable/reactivity"; -import { Platform, Pressable, ScrollView, View } from "react-native"; +import { Platform, ScrollView, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { AndroidScreenHeader } from "../../components/AndroidScreenHeader"; import { AppText as Text } from "../../components/AppText"; -import { SymbolView } from "../../components/AppSymbol"; import { NativeStackScreenOptions } from "../../native/StackHeader"; import { DEFAULT_FOLLOW_UP_BEHAVIOR, type FollowUpBehavior } from "../../lib/followUpBehavior"; import { mobilePreferencesAtom, updateMobilePreferencesAtom } from "../../state/preferences"; +import { SettingsChoiceRow } from "./components/SettingsChoiceRow"; import { SettingsSection } from "./components/SettingsSection"; const FOLLOW_UP_OPTIONS: ReadonlyArray<{ @@ -56,37 +56,15 @@ export function SettingsFollowUpRouteScreen() { > {FOLLOW_UP_OPTIONS.map((option, index) => ( - 0} disabled={!preferencesReady} onPress={() => savePreferences({ followUpBehavior: option.behavior })} - className={ - index === 0 - ? "flex-row items-center gap-4 p-4" - : "flex-row items-center gap-4 border-t border-border-subtle p-4" - } - > - - {option.label} - - {option.description} - - - {selectedBehavior === option.behavior ? ( - - ) : null} - + /> ))} diff --git a/apps/mobile/src/features/settings/SettingsKeyboardRouteScreen.tsx b/apps/mobile/src/features/settings/SettingsKeyboardRouteScreen.tsx index abd6ac22266d..f0cb34ce9d7e 100644 --- a/apps/mobile/src/features/settings/SettingsKeyboardRouteScreen.tsx +++ b/apps/mobile/src/features/settings/SettingsKeyboardRouteScreen.tsx @@ -1,18 +1,18 @@ import { useAtomSet, useAtomValue } from "@effect/atom-react"; import { useNavigation } from "@react-navigation/native"; import { AsyncResult } from "effect/unstable/reactivity"; -import { Platform, Pressable, ScrollView, View } from "react-native"; +import { Platform, ScrollView, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { AndroidScreenHeader } from "../../components/AndroidScreenHeader"; import { AppText as Text } from "../../components/AppText"; -import { SymbolView } from "../../components/AppSymbol"; import { NativeStackScreenOptions } from "../../native/StackHeader"; import { DEFAULT_COMPOSER_ENTER_BEHAVIOR, type ComposerEnterBehavior, } from "../../lib/composerEnterBehavior"; import { mobilePreferencesAtom, updateMobilePreferencesAtom } from "../../state/preferences"; +import { SettingsChoiceRow } from "./components/SettingsChoiceRow"; import { SettingsSection } from "./components/SettingsSection"; const ENTER_BEHAVIOR_OPTIONS: ReadonlyArray<{ @@ -59,37 +59,15 @@ export function SettingsKeyboardRouteScreen() { > {ENTER_BEHAVIOR_OPTIONS.map((option, index) => ( - 0} disabled={!preferencesReady} onPress={() => savePreferences({ composerEnterBehavior: option.behavior })} - className={ - index === 0 - ? "flex-row items-center gap-4 p-4" - : "flex-row items-center gap-4 border-t border-border-subtle p-4" - } - > - - {option.label} - - {option.description} - - - {selectedBehavior === option.behavior ? ( - - ) : null} - + /> ))} diff --git a/apps/mobile/src/features/settings/SettingsProjectGroupingRouteScreen.tsx b/apps/mobile/src/features/settings/SettingsProjectGroupingRouteScreen.tsx index fb17ed64edc9..bb343e0e255f 100644 --- a/apps/mobile/src/features/settings/SettingsProjectGroupingRouteScreen.tsx +++ b/apps/mobile/src/features/settings/SettingsProjectGroupingRouteScreen.tsx @@ -2,17 +2,15 @@ import { ScreenScrollView as ScrollView } from "../../components/ScreenScrollVie import { useAtomSet, useAtomValue } from "@effect/atom-react"; import type { SidebarProjectGroupingMode } from "@t3tools/contracts"; import { AsyncResult } from "effect/unstable/reactivity"; -import { Pressable, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; -import { AppText as Text } from "../../components/AppText"; -import { SymbolView } from "../../components/AppSymbol"; import { SettingsScreen } from "./components/SettingsScreen"; import { mobileProjectGroupingModePatch, resolveMobileProjectGroupingSettings, } from "../../state/project-grouping"; import { mobilePreferencesAtom, updateMobilePreferencesAtom } from "../../state/preferences"; +import { SettingsChoiceRow } from "./components/SettingsChoiceRow"; import { SettingsSection } from "./components/SettingsSection"; const GROUPING_OPTIONS: ReadonlyArray<{ @@ -57,37 +55,15 @@ export function SettingsProjectGroupingRouteScreen() { > {GROUPING_OPTIONS.map((option, index) => ( - 0} disabled={!preferencesReady} onPress={() => savePreferences(mobileProjectGroupingModePatch(option.mode))} - className={ - index === 0 - ? "flex-row items-center gap-4 p-4" - : "flex-row items-center gap-4 border-t border-border-subtle p-4" - } - > - - {option.label} - - {option.description} - - - {selectedMode === option.mode ? ( - - ) : null} - + /> ))} diff --git a/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx b/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx index e9333426387f..58c45e465611 100644 --- a/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx +++ b/apps/mobile/src/features/settings/SettingsServerControlsRouteScreen.tsx @@ -10,7 +10,7 @@ import { type ProjectScopedServerSettingKey, } from "@t3tools/contracts"; import { useRef, useState, type ComponentProps } from "react"; -import { Platform, Pressable, View } from "react-native"; +import { Pressable, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { RUNTIME_MODE_CHOICES } from "../threads/thread-settings-options"; @@ -21,6 +21,7 @@ import { AndroidSettingsEnvironmentFilter, SettingsEnvironmentFilterHeader, } from "./components/SettingsEnvironmentFilterHeader"; +import { SettingsChoiceRow } from "./components/SettingsChoiceRow"; import { SettingsSection } from "./components/SettingsSection"; import { SettingsSwitchRow } from "./components/SettingsSwitchRow"; import { SettingsProjectOverridesSection } from "./components/SettingsProjectOverridesSection"; @@ -219,7 +220,7 @@ function ServerSettingsDetail(props: { readonly page: SettingsPage }) { } > {WORKSPACE_CHOICES.map((choice, index) => ( - {RUNTIME_MODE_CHOICES.map((choice, index) => ( - {STREAMING_CHOICES.map((choice, index) => ( - void; -}) { - return ( - - - - {props.label} - - {props.description} - - {props.selected ? ( - - ) : null} - - ); -} - function MixedValuesLabel(props: { readonly projectSelected: boolean }) { return ( void; +}) { + return ( + + + {props.label} + {props.description} + + {props.selected ? ( + + ) : null} + + ); +}