History

Expose V2 thread workflows on mobile

Julius Marminge committed 4 months ago

Commit beab58b1 parent 2fde64e16 files · +1024 −217Browse files

Showing the changes to apps/mobile/src/features/threads/ThreadQueueControl.tsx (1 of 16 files). Show all

Unified · Split

apps/mobile/src/features/threads/ThreadQueueControl.tsx+115−0
@@ -0,0 +1,115 @@
1import * as Haptics from "expo-haptics";
2import { SymbolView } from "expo-symbols";
3import { deriveThreadQueueWorkflowState } from "@t3tools/client-runtime/state/thread-workflows";
4import type { EnvironmentId, RunId, ThreadId } from "@t3tools/contracts";
5import { useMemo, useState } from "react";
6import { Pressable, ScrollView, View } from "react-native";
7
8import { AppText as Text } from "../../components/AppText";
9import { useThemeColor } from "../../lib/useThemeColor";
10import { threadEnvironment } from "../../state/threads";
11import { useAtomCommand } from "../../state/use-atom-command";
12import { useThreadProjection } from "../../state/use-thread-detail";
13
14export function ThreadQueueControl(props: {
15 readonly environmentId: EnvironmentId;
16 readonly threadId: ThreadId;
17}) {
18 const scoped = useThreadProjection(props);
19 const workflow = useMemo(
20 () => (scoped ? deriveThreadQueueWorkflowState(scoped.projection) : null),
21 [scoped],
22 );
23 const reorder = useAtomCommand(threadEnvironment.reorderQueuedRun, "reorder queued message");
24 const promote = useAtomCommand(threadEnvironment.promoteQueuedRun, "promote queued message");
25 const [busyRunId, setBusyRunId] = useState<RunId | null>(null);
26 const iconColor = useThemeColor("--color-icon-subtle");
27
28 if (!workflow || workflow.queuedRuns.length === 0) return null;
29
30 const move = async (runId: RunId, beforeRunId: RunId | null) => {
31 setBusyRunId(runId);
32 void Haptics.selectionAsync();
33 await reorder({
34 environmentId: props.environmentId,
35 input: { threadId: props.threadId, runId, beforeRunId },
36 });
37 setBusyRunId(null);
38 };
39
40 const steer = async (queuedRunId: RunId) => {
41 if (!workflow.activeRun || !workflow.canPromoteToSteer) return;
42 setBusyRunId(queuedRunId);
43 void Haptics.selectionAsync();
44 await promote({
45 environmentId: props.environmentId,
46 input: {
47 threadId: props.threadId,
48 queuedRunId,
49 targetRunId: workflow.activeRun.id,
50 },
51 });
52 setBusyRunId(null);
53 };
54
55 return (
56 <View className="mx-4 mb-3 overflow-hidden rounded-2xl border border-neutral-300/60 bg-card dark:border-white/[0.1]">
57 <View className="flex-row items-center gap-2 border-b border-neutral-300/50 px-3 py-2 dark:border-white/[0.08]">
58 <SymbolView name="list.number" size={13} tintColor={iconColor} type="monochrome" />
59 <Text className="font-t3-medium text-xs text-foreground">Queue</Text>
60 <Text className="ml-auto text-2xs tabular-nums text-foreground-muted">
61 {workflow.queuedRuns.length}
62 </Text>
63 </View>
64 <ScrollView style={{ maxHeight: 156 }} contentContainerStyle={{ paddingVertical: 4 }}>
65 {workflow.queuedRuns.map(({ run, text }, index) => (
66 <View key={run.id} className="min-h-11 flex-row items-center gap-1.5 px-2">
67 <Text className="w-5 text-right text-3xs tabular-nums text-foreground-muted">
68 {index + 1}
69 </Text>
70 <Text className="min-w-0 flex-1 text-xs text-foreground" numberOfLines={1}>
71 {text}
72 </Text>
73 <Pressable
74 accessibilityRole="button"
75 accessibilityLabel="Move queued message up"
76 disabled={busyRunId !== null || !workflow.canReorder || index === 0}
77 onPress={() => void move(run.id, workflow.queuedRuns[index - 1]?.run.id ?? null)}
78 className="h-9 w-9 items-center justify-center disabled:opacity-30"
79 >
80 <SymbolView name="arrow.up" size={13} tintColor={iconColor} type="monochrome" />
81 </Pressable>
82 <Pressable
83 accessibilityRole="button"
84 accessibilityLabel="Move queued message down"
85 disabled={
86 busyRunId !== null ||
87 !workflow.canReorder ||
88 index === workflow.queuedRuns.length - 1
89 }
90 onPress={() => void move(run.id, workflow.queuedRuns[index + 2]?.run.id ?? null)}
91 className="h-9 w-9 items-center justify-center disabled:opacity-30"
92 >
93 <SymbolView name="arrow.down" size={13} tintColor={iconColor} type="monochrome" />
94 </Pressable>
95 <Pressable
96 accessibilityRole="button"
97 accessibilityLabel="Promote queued message to steer"
98 disabled={busyRunId !== null || !workflow.canPromoteToSteer}
99 onPress={() => void steer(run.id)}
100 className="min-h-8 flex-row items-center gap-1 rounded-lg border border-neutral-300/60 px-2 disabled:opacity-30 dark:border-white/[0.1]"
101 >
102 <SymbolView
103 name="arrow.turn.left.up"
104 size={12}
105 tintColor={iconColor}
106 type="monochrome"
107 />
108 <Text className="font-t3-medium text-2xs text-foreground">Steer</Text>
109 </Pressable>
110 </View>
111 ))}
112 </ScrollView>
113 </View>
114 );
115}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t