From c7fa1e96943f380a8893e89460d03a362285ab83 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 17 Sep 2026 20:28:27 -0700 Subject: [PATCH] fix(mobile): share settings action row defaults (#12369) --- .../mobile/src/components/MaterialListRow.tsx | 4 +- .../SettingsDiagnosticsRouteScreen.tsx | 22 ++------ .../SettingsClientStorageRouteScreen.tsx | 23 +++----- .../settings/components/SettingsActionRow.tsx | 56 +++++++++++++++++++ 4 files changed, 72 insertions(+), 33 deletions(-) create mode 100644 apps/mobile/src/features/settings/components/SettingsActionRow.tsx diff --git a/apps/mobile/src/components/MaterialListRow.tsx b/apps/mobile/src/components/MaterialListRow.tsx index 31d6f7a6ffd1f619de408ebe9c046431515c98be..539472e4bd960003913e8900916ada643eccee22 100644 --- a/apps/mobile/src/components/MaterialListRow.tsx +++ b/apps/mobile/src/components/MaterialListRow.tsx @@ -9,6 +9,7 @@ import { SymbolView } from "./AppSymbol"; /** Shared geometry for Material navigation and selection lists. Group rows in one card. */ export function MaterialListRow({ title, + titleClassName, subtitle, leading, trailing, @@ -16,6 +17,7 @@ export function MaterialListRow({ ...props }: Omit, "children"> & { readonly title: string; + readonly titleClassName?: string; readonly subtitle?: string | null; readonly leading?: ReactNode; readonly trailing?: ReactNode; @@ -38,7 +40,7 @@ export function MaterialListRow({ > {leading ? {leading} : null} - + {title} {subtitle ? ( diff --git a/apps/mobile/src/features/diagnostics/SettingsDiagnosticsRouteScreen.tsx b/apps/mobile/src/features/diagnostics/SettingsDiagnosticsRouteScreen.tsx index ff21a6c31a90c773f3b8b0af5f9d408921ed9b1e..3d4a79d85910d783f292ca9a3e8d329ba27b6f9d 100644 --- a/apps/mobile/src/features/diagnostics/SettingsDiagnosticsRouteScreen.tsx +++ b/apps/mobile/src/features/diagnostics/SettingsDiagnosticsRouteScreen.tsx @@ -2,12 +2,13 @@ import { ScreenScrollView as ScrollView } from "../../components/ScreenScrollVie import Constants from "expo-constants"; import * as Updates from "expo-updates"; import { useEffect, useState } from "react"; -import { ActivityIndicator, Platform, Pressable, View } from "react-native"; +import { ActivityIndicator, Platform, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { SymbolView } from "../../components/AppSymbol"; import { AppText as Text } from "../../components/AppText"; import { tryCopyTextWithHaptic } from "../../lib/copyTextWithHaptic"; +import { SettingsActionRow } from "../settings/components/SettingsActionRow"; import { SettingsScreen } from "../settings/components/SettingsScreen"; import { SettingsSection } from "../settings/components/SettingsSection"; import { @@ -108,23 +109,12 @@ export function SettingsDiagnosticsRouteScreen() { - void copyReport()} - className="flex-row items-center gap-4 p-4 disabled:opacity-40" - > - - - {copied ? "Copied" : "Copy crash report"} - - + /> Paste the report into a GitHub issue. It contains the app version, the JavaScript error diff --git a/apps/mobile/src/features/settings/SettingsClientStorageRouteScreen.tsx b/apps/mobile/src/features/settings/SettingsClientStorageRouteScreen.tsx index 5c36b16cac20c0284ce024adce31a2014dd5fb2c..0e8395b44db8b3b3520e769c6e5a42d06c80fdc8 100644 --- a/apps/mobile/src/features/settings/SettingsClientStorageRouteScreen.tsx +++ b/apps/mobile/src/features/settings/SettingsClientStorageRouteScreen.tsx @@ -16,6 +16,7 @@ import { } from "../../state/client-cache-state"; import { useServerConfigs } from "../../state/entities"; import { useSavedRemoteConnections } from "../../state/use-remote-environment-registry"; +import { SettingsActionRow } from "./components/SettingsActionRow"; import { SettingsSection } from "./components/SettingsSection"; import { SettingsScreen } from "./components/SettingsScreen"; @@ -139,24 +140,14 @@ export function SettingsClientStorageRouteScreen() { - - - - {summary ? `Clear ${formatBytes(summary.payloadBytes)}` : "Clear caches"} - - {isClearing ? : null} - + /> Clearing caches never removes environment connections, credentials, account data, or diff --git a/apps/mobile/src/features/settings/components/SettingsActionRow.tsx b/apps/mobile/src/features/settings/components/SettingsActionRow.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9cf58effe506ce27ce195f1fe7afd79e79d6f0e1 --- /dev/null +++ b/apps/mobile/src/features/settings/components/SettingsActionRow.tsx @@ -0,0 +1,56 @@ +import type { ComponentProps } from "react"; +import { ActivityIndicator, Platform, Pressable } from "react-native"; + +import { SymbolView } from "../../../components/AppSymbol"; +import { AppText as Text } from "../../../components/AppText"; +import { MaterialListRow } from "../../../components/MaterialListRow"; +import { cn } from "../../../lib/cn"; + +export function SettingsActionRow(props: { + readonly icon: ComponentProps["name"]; + readonly label: string; + readonly tone?: "default" | "danger"; + readonly disabled?: boolean; + readonly loading?: boolean; + readonly onPress: () => void; +}) { + const danger = props.tone === "danger"; + const textClassName = danger ? "tabular-nums text-danger-foreground" : "text-foreground"; + const iconColorClassName = danger ? "accent-danger-foreground" : "accent-icon"; + const icon = ( + + ); + const spinner = props.loading ? : null; + + if (Platform.OS === "android") { + return ( + + ); + } + + return ( + + {icon} + {props.label} + {spinner} + + ); +} -- 2.54.0