1import { TextInput, View } from "react-native";
2
3import { AppText as Text } from "../../../components/AppText";
4import type { ComposerEditorSelection } from "../../../components/ComposerEditor";
5import {
6 ComposerDictationCancelAction,
7 ComposerDictationPrimaryAction,
8 ComposerDictationStartAction,
9 ComposerDictationStatus,
10 ComposerDictationToolbar,
11} from "../../voice-input/ComposerDictationControl";
12import type { useVoiceInputController } from "../../voice-input/useVoiceInputController";
13import { resolveVoiceComposerPresentation } from "../../voice-input/voiceInputPresentation";
14
15export function ScheduledTaskPromptField(props: {
16 readonly value: string;
17 readonly onChange: (value: string) => void;
18 readonly selection: ComposerEditorSelection;
19 readonly onChangeSelection: (selection: ComposerEditorSelection) => void;
20 readonly disabled: boolean;
21 readonly voiceInput: ReturnType<typeof useVoiceInputController>;
22}) {
23 const voice = props.voiceInput;
24 const presentation = resolveVoiceComposerPresentation(voice.state, voice.elapsedSeconds);
25 const showsDictation = presentation.statusLabel !== null;
26 const showsIdleTrigger = voice.isAvailable && !showsDictation;
27
28 return (
29 <View className="gap-2 border-t border-border-subtle px-4 py-3">
30 <Text className="text-sm text-foreground-muted">Prompt</Text>
31 <View className="relative">
32 <TextInput
33 accessibilityLabel="Prompt"
34 value={props.value}
35 onChangeText={props.onChange}
36 selection={props.selection}
37 onSelectionChange={({ nativeEvent }) => props.onChangeSelection(nativeEvent.selection)}
38 readOnly={props.disabled || voice.freezesEditor}
39 multiline
40 scrollEnabled
41 textAlignVertical="top"
42 placeholder="What should the agent do each time?"
43 placeholderTextColorClassName="accent-foreground-muted"
44 className="max-h-40 min-h-24 font-sans text-base text-foreground"
45 />
46 {showsIdleTrigger ? (
47 <View className="absolute right-0 bottom-0 rounded-full bg-card">
48 <ComposerDictationStartAction
49 state={voice.state}
50 isAvailable={voice.isAvailable}
51 disabled={props.disabled}
52 onStart={voice.start}
53 onCancel={voice.cancel}
54 />
55 </View>
56 ) : null}
57 </View>
58 {showsDictation ? (
59 <ComposerDictationToolbar showsDictation>
60 <View className="h-11 flex-row items-center">
61 <ComposerDictationCancelAction presentation={presentation} onCancel={voice.cancel} />
62 <ComposerDictationStatus
63 audioLevels={voice.audioLevels}
64 elapsedSeconds={voice.elapsedSeconds}
65 phase={voice.state.phase}
66 presentation={presentation}
67 onDismissError={voice.cancel}
68 />
69 <ComposerDictationPrimaryAction
70 state={voice.state}
71 presentation={presentation}
72 isAvailable={voice.isAvailable}
73 disabled={props.disabled}
74 onStart={voice.start}
75 onConfirm={voice.stop}
76 onCancel={voice.cancel}
77 />
78 </View>
79 </ComposerDictationToolbar>
80 ) : null}
81 </View>
82 );
83}