| author | |
| committer | |
| log | 4db50757c0b618293997a7f81bcfe30b68356969 |
| tree | 0d89eb0d9e7027ec427055260a3188d63da4c2c7 |
| parent | 270489b887420db3319898ab4046516e4c457711 |
| signature | Signed by PGP key B5690EEEBB952194 |
4 files changed, 40 insertions(+), 1 deletions(-)
apps/mobile/src/features/settings/SettingsRouteScreen.logic.test.ts created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | import { describe, expect, it } from "vite-plus/test"; | |
| 2 | ||
| 3 | import { resolveAgentAwarenessPlatformPresentation } from "./SettingsRouteScreen.logic"; | |
| 4 | ||
| 5 | describe("resolveAgentAwarenessPlatformPresentation", () => { | |
| 6 | it("explains that agent awareness settings are unavailable on Android", () => { | |
| 7 | expect(resolveAgentAwarenessPlatformPresentation("android")).toEqual({ | |
| 8 | supported: false, | |
| 9 | subtitle: "iOS only", | |
| 10 | }); | |
| 11 | }); | |
| 12 | ||
| 13 | it("leaves supported iOS settings unchanged", () => { | |
| 14 | expect(resolveAgentAwarenessPlatformPresentation("ios")).toEqual({ | |
| 15 | supported: true, | |
| 16 | subtitle: undefined, | |
| 17 | }); | |
| 18 | }); | |
| 19 | }); |
apps/mobile/src/features/settings/SettingsRouteScreen.logic.ts created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | export function resolveAgentAwarenessPlatformPresentation(platform: string): { | |
| 2 | readonly supported: boolean; | |
| 3 | readonly subtitle: string | undefined; | |
| 4 | } { | |
| 5 | return platform === "ios" | |
| 6 | ? { supported: true, subtitle: undefined } | |
| 7 | : { supported: false, subtitle: "iOS only" }; | |
| 8 | } |
apps/mobile/src/features/settings/SettingsRouteScreen.tsx+6| ... | ... | @@ -46,6 +46,7 @@ import { useSavedRemoteConnections } from "../../state/use-remote-environment-re |
| 46 | 46 | import { SettingsRow } from "./components/SettingsRow"; |
| 47 | 47 | import { SettingsSection } from "./components/SettingsSection"; |
| 48 | 48 | import { SettingsSwitchRow } from "./components/SettingsSwitchRow"; |
| 49 | import { resolveAgentAwarenessPlatformPresentation } from "./SettingsRouteScreen.logic"; | |
| 49 | 50 | |
| 50 | 51 | type NotificationStatus = "checking" | "enabled" | "disabled" | "unsupported"; |
| 51 | 52 | type LiveActivityStatus = "checking" | "enabled" | "disabled" | "signed-out" | "linking"; |
| ... | ... | @@ -144,6 +145,7 @@ function ConfiguredSettingsRouteScreen() { |
| 144 | 145 | const preferencesResult = useAtomValue(mobilePreferencesAtom); |
| 145 | 146 | const savePreferences = useAtomSet(updateMobilePreferencesAtom); |
| 146 | 147 | const agentAwarenessPushAvailable = supportsAgentAwarenessPush(); |
| 148 | const agentAwarenessPlatform = resolveAgentAwarenessPlatformPresentation(Platform.OS); | |
| 147 | 149 | const insets = useSafeAreaInsets(); |
| 148 | 150 | const navigation = useNavigation(); |
| 149 | 151 | const { getToken, isLoaded, isSignedIn } = useAuth({ treatPendingAsSignedOut: false }); |
| ... | ... | @@ -473,10 +475,12 @@ function ConfiguredSettingsRouteScreen() { |
| 473 | 475 | icon="bell.badge" |
| 474 | 476 | label="Device Notifications" |
| 475 | 477 | disabled={ |
| 478 | !agentAwarenessPlatform.supported || | |
| 476 | 479 | !agentAwarenessPushAvailable || |
| 477 | 480 | notificationStatus === "checking" || |
| 478 | 481 | notificationStatus === "unsupported" |
| 479 | 482 | } |
| 483 | subtitle={agentAwarenessPlatform.subtitle} | |
| 480 | 484 | // Only reads as on when this device is actually registered with the |
| 481 | 485 | // relay; otherwise notifications cannot be delivered regardless of |
| 482 | 486 | // the local iOS permission. |
| ... | ... | @@ -487,6 +491,7 @@ function ConfiguredSettingsRouteScreen() { |
| 487 | 491 | /> |
| 488 | 492 | <SettingsSwitchRow |
| 489 | 493 | disabled={ |
| 494 | !agentAwarenessPlatform.supported || | |
| 490 | 495 | !agentAwarenessPushAvailable || |
| 491 | 496 | !isLoaded || |
| 492 | 497 | liveActivityStatus === "checking" || |
| ... | ... | @@ -494,6 +499,7 @@ function ConfiguredSettingsRouteScreen() { |
| 494 | 499 | } |
| 495 | 500 | icon="bolt.circle" |
| 496 | 501 | label="Live Activity Updates" |
| 502 | subtitle={agentAwarenessPlatform.subtitle} | |
| 497 | 503 | // Same gate: a saved preference is meaningless until the device |
| 498 | 504 | // registration the relay needs to push updates has succeeded. |
| 499 | 505 | value={ |
apps/mobile/src/features/settings/components/SettingsSwitchRow.tsx+7-1| ... | ... | @@ -11,6 +11,7 @@ export function SettingsSwitchRow(props: { |
| 11 | 11 | readonly disabled?: boolean; |
| 12 | 12 | readonly icon: SymbolName; |
| 13 | 13 | readonly label: string; |
| 14 | readonly subtitle?: string; | |
| 14 | 15 | readonly value: boolean; |
| 15 | 16 | readonly onValueChange: (value: boolean) => void; |
| 16 | 17 | }) { |
| ... | ... | @@ -27,7 +28,12 @@ export function SettingsSwitchRow(props: { |
| 27 | 28 | } |
| 28 | 29 | > |
| 29 | 30 | <SymbolView name={props.icon} size={22} tintColor={icon} type="monochrome" weight="regular" /> |
| 30 | <Text className="flex-1 text-lg text-foreground">{props.label}</Text> | |
| 31 | <View className="min-w-0 flex-1"> | |
| 32 | <Text className="text-lg text-foreground">{props.label}</Text> | |
| 33 | {props.subtitle ? ( | |
| 34 | <Text className="text-sm text-foreground-muted">{props.subtitle}</Text> | |
| 35 | ) : null} | |
| 36 | </View> | |
| 31 | 37 | <Switch |
| 32 | 38 | disabled={props.disabled} |
| 33 | 39 | ios_backgroundColor={track} |