1import { ScreenScrollView as ScrollView } from "../../components/ScreenScrollView";
2import { useAtomSet, useAtomValue } from "@effect/atom-react";
3import { useNavigation } from "@react-navigation/native";
4import { AsyncResult } from "effect/reactivity";
5import { Platform, View } from "react-native";
6import { useSafeAreaInsets } from "react-native-safe-area-context";
7
8import { AndroidScreenHeader } from "../../components/AndroidScreenHeader";
9import { AppText as Text } from "../../components/AppText";
10import { NativeStackScreenOptions } from "../../native/StackHeader";
11import { DEFAULT_FOLLOW_UP_BEHAVIOR, type FollowUpBehavior } from "../../lib/followUpBehavior";
12import { mobilePreferencesAtom, updateMobilePreferencesAtom } from "../../state/preferences";
13import { SettingsChoiceRow } from "./components/SettingsChoiceRow";
14import { SettingsSection } from "./components/SettingsSection";
15
16const FOLLOW_UP_OPTIONS: ReadonlyArray<{
17 readonly behavior: FollowUpBehavior;
18 readonly label: string;
19 readonly description: string;
20}> = [
21 {
22 behavior: "queue",
23 label: "Queue",
24 description: "Your message waits and runs after the current turn finishes.",
25 },
26 {
27 behavior: "steer",
28 label: "Steer",
29 description: "Your message reaches the agent right away, changing what it is working on.",
30 },
31];
32
33export function SettingsFollowUpRouteScreen() {
34 const navigation = useNavigation();
35 const insets = useSafeAreaInsets();
36 const preferencesResult = useAtomValue(mobilePreferencesAtom);
37 const savePreferences = useAtomSet(updateMobilePreferencesAtom);
38 const preferencesReady = AsyncResult.isSuccess(preferencesResult) && !preferencesResult.waiting;
39 const selectedBehavior = AsyncResult.isSuccess(preferencesResult)
40 ? (preferencesResult.value.followUpBehavior ?? DEFAULT_FOLLOW_UP_BEHAVIOR)
41 : null;
42
43 return (
44 <View collapsable={false} className="flex-1 bg-sheet">
45 {Platform.OS === "android" ? (
46 <>
47 <NativeStackScreenOptions options={{ headerShown: false }} />
48 <AndroidScreenHeader title="Follow-ups" onBack={() => navigation.goBack()} />
49 </>
50 ) : null}
51 <ScrollView
52 contentInsetAdjustmentBehavior="automatic"
53 showsVerticalScrollIndicator={false}
54 className="flex-1"
55 contentContainerClassName="gap-3 px-5 pt-4"
56 contentContainerStyle={{ paddingBottom: Math.max(insets.bottom, 18) + 18 }}
57 >
58 <SettingsSection title="While the agent is running">
59 {FOLLOW_UP_OPTIONS.map((option, index) => (
60 <SettingsChoiceRow
61 key={option.behavior}
62 label={option.label}
63 description={option.description}
64 selected={selectedBehavior === option.behavior}
65 separated={index > 0}
66 disabled={!preferencesReady}
67 onPress={() => savePreferences({ followUpBehavior: option.behavior })}
68 />
69 ))}
70 </SettingsSection>
71 <Text className="px-2 text-sm text-foreground-muted">
72 Long-press the send button to use the other option for a single message. With a hardware
73 keyboard, hold Command while sending.
74 </Text>
75 </ScrollView>
76 </View>
77 );
78}