@adminide-stack/yantra-mobile 12.0.120-alpha.1 → 12.0.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/NavigationHeader/HeaderTasksButton.js +130 -17
- package/lib/components/NavigationHeader/HeaderTasksButton.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +10 -8
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +8 -1
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/buildJob.js +92 -0
- package/lib/features/webbuilder/buildJob.js.map +1 -0
- package/lib/features/webbuilder/workflow.js +22 -26
- package/lib/features/webbuilder/workflow.js.map +1 -1
- package/lib/hooks/useCdecliChannel.js +5 -3
- package/lib/hooks/useCdecliChannel.js.map +1 -1
- package/lib/hooks/useChatStream.js +2 -2
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/useSurfaceJobs.js +49 -0
- package/lib/hooks/useSurfaceJobs.js.map +1 -0
- package/lib/screens/WebBuilderNative/index.js +13 -2
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +120 -21
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderJobs.js +66 -0
- package/lib/screens/WebBuilderNative/useWebBuilderJobs.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback}from'react';import {ScrollView,StyleSheet,Text,View,Pressable,ActivityIndicator}from'react-native';import {useFocusEffect}from'@react-navigation/native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {MAX_CONCURRENT_TASKS}from'../../config/constants.js';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useGatewayContext}from'../../contexts/GatewayContext.js';import {useAgentSessionState}from'../../hooks/useAgentSessionState.js';import {agentSessionManager}from'../../services/agentSessionManager.js';import {mobileTokens}from'../../theme/mobileTokens.js';import {HeaderSheet}from'./HeaderSheet.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';const STATUS_LABEL = {
|
|
1
|
+
import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useEffect,useCallback}from'react';import {Linking,ScrollView,StyleSheet,Text,View,Pressable,ActivityIndicator}from'react-native';import {useFocusEffect,useNavigation}from'@react-navigation/native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {isJobRunning,jobStateLabel,jobDetailLine,slugLabel}from'common';import {MAX_CONCURRENT_TASKS}from'../../config/constants.js';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useGatewayContext}from'../../contexts/GatewayContext.js';import {WEBBUILDER_JOB_SURFACE}from'../../features/webbuilder/buildJob.js';import {useAgentSessionState}from'../../hooks/useAgentSessionState.js';import {useSurfaceJobs}from'../../hooks/useSurfaceJobs.js';import {agentSessionManager}from'../../services/agentSessionManager.js';import {mobileTokens}from'../../theme/mobileTokens.js';import {HeaderSheet}from'./HeaderSheet.js';import {HeaderToolbarButton}from'./HeaderToolbarButton.js';const STATUS_LABEL = {
|
|
2
2
|
idle: "Idle",
|
|
3
3
|
connecting: "Connecting",
|
|
4
4
|
running: "Running",
|
|
@@ -6,6 +6,23 @@ import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback}f
|
|
|
6
6
|
failed: "Failed",
|
|
7
7
|
aborted: "Aborted"
|
|
8
8
|
};
|
|
9
|
+
const STATUS_GLYPH = {
|
|
10
|
+
completed: {
|
|
11
|
+
name: "check-circle-outline",
|
|
12
|
+
light: "#16a34a",
|
|
13
|
+
dark: "#4ade80"
|
|
14
|
+
},
|
|
15
|
+
failed: {
|
|
16
|
+
name: "alert-circle-outline",
|
|
17
|
+
light: "#dc2626",
|
|
18
|
+
dark: "#f87171"
|
|
19
|
+
},
|
|
20
|
+
aborted: {
|
|
21
|
+
name: "close-circle-outline",
|
|
22
|
+
light: "#ea580c",
|
|
23
|
+
dark: "#fb923c"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
9
26
|
function StatusGlyph({
|
|
10
27
|
status,
|
|
11
28
|
isDark
|
|
@@ -13,9 +30,17 @@ function StatusGlyph({
|
|
|
13
30
|
if (status === "running" || status === "connecting") {
|
|
14
31
|
return /* @__PURE__ */ jsx(ActivityIndicator, { size: 14, color: isDark ? "#60a5fa" : "#2563eb" });
|
|
15
32
|
}
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
const glyph = STATUS_GLYPH[status];
|
|
34
|
+
if (!glyph) {
|
|
35
|
+
const muted = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
36
|
+
return /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "circle-outline", size: 16, color: muted });
|
|
37
|
+
}
|
|
38
|
+
return /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: glyph.name, size: 16, color: isDark ? glyph.dark : glyph.light });
|
|
39
|
+
}
|
|
40
|
+
function previewOf(task) {
|
|
41
|
+
const last = task.messages[task.messages.length - 1];
|
|
42
|
+
if (!last) return "No messages yet";
|
|
43
|
+
return last.content.length > 60 ? `${last.content.slice(0, 60)}\u2026` : last.content;
|
|
19
44
|
}
|
|
20
45
|
function TaskRow({
|
|
21
46
|
task,
|
|
@@ -26,8 +51,7 @@ function TaskRow({
|
|
|
26
51
|
}) {
|
|
27
52
|
const foreground = isDark ? "#e2e8f0" : mobileTokens.color.text;
|
|
28
53
|
const muted = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
29
|
-
const
|
|
30
|
-
const preview = last ? last.content.length > 60 ? `${last.content.slice(0, 60)}\u2026` : last.content : "No messages yet";
|
|
54
|
+
const preview = previewOf(task);
|
|
31
55
|
const skillLabel = task.skillTemplateName || task.skillTemplate;
|
|
32
56
|
return /* @__PURE__ */ jsxs(Pressable, { onPress: onSelect, style: ({
|
|
33
57
|
pressed
|
|
@@ -53,11 +77,76 @@ function TaskRow({
|
|
|
53
77
|
/* @__PURE__ */ jsx(Pressable, { onPress: onRemove, hitSlop: 8, accessibilityLabel: "Remove task", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "trash-can-outline", size: 16, color: muted }) })
|
|
54
78
|
] });
|
|
55
79
|
}
|
|
80
|
+
function JobRow({
|
|
81
|
+
job,
|
|
82
|
+
now,
|
|
83
|
+
isDark,
|
|
84
|
+
onOpen,
|
|
85
|
+
onDismiss
|
|
86
|
+
}) {
|
|
87
|
+
const foreground = isDark ? "#e2e8f0" : mobileTokens.color.text;
|
|
88
|
+
const muted = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
89
|
+
const stateLabel = jobStateLabel(job, now);
|
|
90
|
+
const detail = jobDetailLine(job);
|
|
91
|
+
return /* @__PURE__ */ jsxs(Pressable, { onPress: onOpen != null ? onOpen : void 0, disabled: !onOpen, accessibilityRole: "button", accessibilityLabel: `${job.title}, ${stateLabel}`, style: ({
|
|
92
|
+
pressed
|
|
93
|
+
}) => [styles.row, pressed && styles.pressed], children: [
|
|
94
|
+
job.state === "running" ? /* @__PURE__ */ jsx(ActivityIndicator, { size: 14, color: isDark ? "#60a5fa" : "#2563eb" }) : /* @__PURE__ */ jsx(StatusGlyph, { status: job.state === "succeeded" ? "completed" : "failed", isDark }),
|
|
95
|
+
/* @__PURE__ */ jsxs(View, { style: styles.rowBody, children: [
|
|
96
|
+
/* @__PURE__ */ jsxs(View, { style: styles.titleRow, children: [
|
|
97
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, {
|
|
98
|
+
color: foreground
|
|
99
|
+
}], numberOfLines: 1, children: job.title }),
|
|
100
|
+
/* @__PURE__ */ jsx(View, { style: [styles.skillChip, isDark && styles.skillChipDark], children: /* @__PURE__ */ jsx(Text, { style: [styles.skillChipText, {
|
|
101
|
+
color: muted
|
|
102
|
+
}], numberOfLines: 1, children: slugLabel(job.slug) }) })
|
|
103
|
+
] }),
|
|
104
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.rowMeta, {
|
|
105
|
+
color: muted
|
|
106
|
+
}], numberOfLines: 2, children: detail ? `${stateLabel} \xB7 ${detail}` : stateLabel })
|
|
107
|
+
] }),
|
|
108
|
+
job.state === "running" ? null : /* @__PURE__ */ jsx(Pressable, { onPress: onDismiss, hitSlop: 8, accessibilityLabel: "Remove task", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "trash-can-outline", size: 16, color: muted }) })
|
|
109
|
+
] });
|
|
110
|
+
}
|
|
111
|
+
function webBuilderChannel(job) {
|
|
112
|
+
var _a;
|
|
113
|
+
const channelId = (_a = job.handle) == null ? void 0 : _a.channelId;
|
|
114
|
+
return job.slug === WEBBUILDER_JOB_SURFACE && typeof channelId === "string" && channelId ? channelId : null;
|
|
115
|
+
}
|
|
56
116
|
function TasksSheet({
|
|
57
117
|
isDark,
|
|
58
|
-
onClose
|
|
118
|
+
onClose,
|
|
119
|
+
jobs,
|
|
120
|
+
runningJobs,
|
|
121
|
+
onDismissJob
|
|
59
122
|
}) {
|
|
60
123
|
const session = useAgentSessionState();
|
|
124
|
+
const navigation = useNavigation();
|
|
125
|
+
const [now, setNow] = useState(() => Date.now());
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!jobs.some(isJobRunning)) return void 0;
|
|
128
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
129
|
+
return () => clearInterval(timer);
|
|
130
|
+
}, [jobs]);
|
|
131
|
+
const openJob = useCallback((job) => {
|
|
132
|
+
const channelId = webBuilderChannel(job);
|
|
133
|
+
if (channelId) {
|
|
134
|
+
return () => {
|
|
135
|
+
onClose();
|
|
136
|
+
navigation.navigate("MainStack.WebBuilderNative", {
|
|
137
|
+
openChannelId: channelId
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const {
|
|
142
|
+
pageUrl
|
|
143
|
+
} = job;
|
|
144
|
+
if (!pageUrl) return null;
|
|
145
|
+
return () => {
|
|
146
|
+
onClose();
|
|
147
|
+
Linking.openURL(pageUrl).catch(() => void 0);
|
|
148
|
+
};
|
|
149
|
+
}, [navigation, onClose]);
|
|
61
150
|
const {
|
|
62
151
|
selectedGateway
|
|
63
152
|
} = useGatewayContext();
|
|
@@ -72,30 +161,47 @@ function TasksSheet({
|
|
|
72
161
|
title: "General Assistant"
|
|
73
162
|
});
|
|
74
163
|
}, [canCreate]);
|
|
75
|
-
return /* @__PURE__ */ jsx(HeaderSheet, { visible: true, title: "Tasks", subtitle: `${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`, isDark, onClose, headerRight: /* @__PURE__ */ jsxs(View, { style: styles.headerRight, children: [
|
|
164
|
+
return /* @__PURE__ */ jsx(HeaderSheet, { visible: true, title: "Tasks", subtitle: jobs.length ? `${runningJobs} running \xB7 ${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots` : `${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`, isDark, onClose, headerRight: /* @__PURE__ */ jsxs(View, { style: styles.headerRight, children: [
|
|
76
165
|
/* @__PURE__ */ jsx(View, { style: [styles.gwDot, {
|
|
77
166
|
backgroundColor: connected ? "#22c55e" : "#94a3b8"
|
|
78
167
|
}] }),
|
|
79
168
|
/* @__PURE__ */ jsx(Pressable, { onPress: handleNew, disabled: !canCreate, accessibilityLabel: "Start new task", style: ({
|
|
80
169
|
pressed
|
|
81
170
|
}) => [styles.newBtn, pressed && styles.pressed, !canCreate && styles.disabled], children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "plus", size: 16, color: mobileTokens.color.primary }) })
|
|
82
|
-
] }), children: /* @__PURE__ */
|
|
171
|
+
] }), children: /* @__PURE__ */ jsxs(ScrollView, { style: {
|
|
83
172
|
flex: 1
|
|
84
|
-
}, contentContainerStyle: styles.list, keyboardShouldPersistTaps: "handled", children:
|
|
85
|
-
|
|
86
|
-
|
|
173
|
+
}, contentContainerStyle: styles.list, keyboardShouldPersistTaps: "handled", children: [
|
|
174
|
+
jobs.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
175
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.sectionLabel, {
|
|
176
|
+
color: muted
|
|
177
|
+
}], children: "Jobs" }),
|
|
178
|
+
jobs.map((job) => /* @__PURE__ */ jsx(JobRow, { job, now, isDark, onOpen: openJob(job), onDismiss: () => onDismissJob(job.id) }, job.id)),
|
|
179
|
+
session.tasks.length > 0 ? /* @__PURE__ */ jsx(Text, { style: [styles.sectionLabel, {
|
|
180
|
+
color: muted
|
|
181
|
+
}], children: "Sessions" }) : null
|
|
182
|
+
] }) : null,
|
|
183
|
+
session.tasks.map((task) => /* @__PURE__ */ jsx(TaskRow, { task, isActive: session.activeTaskId === task.id, isDark, onSelect: () => agentSessionManager.setActiveTask(task.id), onRemove: () => agentSessionManager.removeTask(task.id) }, task.id)),
|
|
184
|
+
session.tasks.length === 0 && jobs.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles.empty, {
|
|
185
|
+
color: muted
|
|
186
|
+
}], children: connected ? "No tasks yet. Create one to get started." : "Connect Yantra to create tasks." }) : null
|
|
187
|
+
] }) });
|
|
87
188
|
}
|
|
88
189
|
function HeaderTasksButton({
|
|
89
190
|
isDark
|
|
90
191
|
}) {
|
|
91
192
|
const session = useAgentSessionState();
|
|
92
193
|
const [open, setOpen] = useState(false);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
194
|
+
const surfaceJobs = useSurfaceJobs(open);
|
|
195
|
+
const {
|
|
196
|
+
refresh: refreshJobs
|
|
197
|
+
} = surfaceJobs;
|
|
198
|
+
useEffect(() => {
|
|
199
|
+
if (open) refreshJobs();
|
|
200
|
+
}, [open, refreshJobs]);
|
|
201
|
+
useFocusEffect(useCallback(() => () => setOpen(false), []));
|
|
96
202
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
97
|
-
/* @__PURE__ */ jsx(HeaderToolbarButton, { icon: "pulse", label: "Tasks", badge: session.tasks.length, active: open, onPress: () => setOpen(true), accessibilityLabel: "Tasks", isDark }),
|
|
98
|
-
open ? /* @__PURE__ */ jsx(TasksSheet, { isDark, onClose: () => setOpen(false) }) : null
|
|
203
|
+
/* @__PURE__ */ jsx(HeaderToolbarButton, { icon: "pulse", label: "Tasks", badge: session.tasks.length + surfaceJobs.runningCount, active: open, onPress: () => setOpen(true), accessibilityLabel: "Tasks", isDark }),
|
|
204
|
+
open ? /* @__PURE__ */ jsx(TasksSheet, { isDark, onClose: () => setOpen(false), jobs: surfaceJobs.jobs, runningJobs: surfaceJobs.runningCount, onDismissJob: surfaceJobs.dismiss }) : null
|
|
99
205
|
] });
|
|
100
206
|
}
|
|
101
207
|
const styles = StyleSheet.create({
|
|
@@ -161,6 +267,13 @@ const styles = StyleSheet.create({
|
|
|
161
267
|
rowMeta: {
|
|
162
268
|
fontSize: 12
|
|
163
269
|
},
|
|
270
|
+
sectionLabel: {
|
|
271
|
+
fontSize: 11,
|
|
272
|
+
fontWeight: "700",
|
|
273
|
+
letterSpacing: 0.4,
|
|
274
|
+
textTransform: "uppercase",
|
|
275
|
+
marginTop: 4
|
|
276
|
+
},
|
|
164
277
|
empty: {
|
|
165
278
|
fontSize: 14,
|
|
166
279
|
lineHeight: 20,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderTasksButton.js","sources":["../../../src/components/NavigationHeader/HeaderTasksButton.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { useFocusEffect } from '@react-navigation/native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { MAX_CONCURRENT_TASKS } from '../../config/constants';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useGatewayContext } from '../../contexts/GatewayContext';\nimport { useAgentSessionState } from '../../hooks/useAgentSessionState';\nimport { agentSessionManager, type AgentTask, type TaskStatus } from '../../services/agentSessionManager';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { HeaderSheet } from './HeaderSheet';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ntype Props = {\n isDark: boolean;\n};\n\nconst STATUS_LABEL: Record<TaskStatus, string> = {\n idle: 'Idle',\n connecting: 'Connecting',\n running: 'Running',\n completed: 'Completed',\n failed: 'Failed',\n aborted: 'Aborted',\n};\n\nfunction StatusGlyph({ status, isDark }: { status: TaskStatus; isDark: boolean }) {\n if (status === 'running' || status === 'connecting') {\n return <ActivityIndicator size={14} color={isDark ? '#60a5fa' : '#2563eb'} />;\n }\n const name =\n status === 'completed'\n ? 'check-circle-outline'\n : status === 'failed'\n ? 'alert-circle-outline'\n : status === 'aborted'\n ? 'close-circle-outline'\n : 'circle-outline';\n const color =\n status === 'completed'\n ? isDark\n ? '#4ade80'\n : '#16a34a'\n : status === 'failed'\n ? isDark\n ? '#f87171'\n : '#dc2626'\n : status === 'aborted'\n ? isDark\n ? '#fb923c'\n : '#ea580c'\n : isDark\n ? '#94a3b8'\n : mobileTokens.color.textMuted;\n return <MaterialCommunityIcons name={name} size={16} color={color} />;\n}\n\nfunction TaskRow({\n task,\n isActive,\n isDark,\n onSelect,\n onRemove,\n}: {\n task: AgentTask;\n isActive: boolean;\n isDark: boolean;\n onSelect: () => void;\n onRemove: () => void;\n}) {\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const last = task.messages[task.messages.length - 1];\n const preview = last\n ? last.content.length > 60\n ? `${last.content.slice(0, 60)}…`\n : last.content\n : 'No messages yet';\n const skillLabel = task.skillTemplateName || task.skillTemplate;\n\n return (\n <Pressable\n onPress={onSelect}\n style={({ pressed }) => [\n styles.row,\n isActive && styles.rowActive,\n isDark && isActive && styles.rowActiveDark,\n pressed && styles.pressed,\n ]}\n >\n <StatusGlyph status={task.status} isDark={isDark} />\n <View style={styles.rowBody}>\n <View style={styles.titleRow}>\n <Text style={[styles.rowTitle, { color: foreground }]} numberOfLines={1}>\n {task.title}\n </Text>\n {skillLabel ? (\n <View style={[styles.skillChip, isDark && styles.skillChipDark]}>\n <Text style={[styles.skillChipText, { color: muted }]} numberOfLines={1}>\n {skillLabel}\n </Text>\n </View>\n ) : null}\n </View>\n <Text style={[styles.rowMeta, { color: muted }]} numberOfLines={1}>\n {STATUS_LABEL[task.status]} · {preview}\n </Text>\n </View>\n <Pressable onPress={onRemove} hitSlop={8} accessibilityLabel=\"Remove task\">\n <MaterialCommunityIcons name=\"trash-can-outline\" size={16} color={muted} />\n </Pressable>\n </Pressable>\n );\n}\n\nfunction TasksSheet({ isDark, onClose }: { isDark: boolean; onClose: () => void }) {\n const session = useAgentSessionState();\n const { selectedGateway } = useGatewayContext();\n const cdecli = useCdecliConnection();\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const cdecliSelected = selectedGateway?.channelType === 'cdecli-serve';\n const connected = cdecliSelected ? cdecli.channelConnected : session.gatewayConnected;\n const canCreate = session.tasks.length < MAX_CONCURRENT_TASKS && (cdecliSelected || session.gatewayConnected);\n\n const handleNew = useCallback(() => {\n if (!canCreate) return;\n agentSessionManager.createTask({ title: 'General Assistant' });\n }, [canCreate]);\n\n return (\n <HeaderSheet\n visible\n title=\"Tasks\"\n subtitle={`${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`}\n isDark={isDark}\n onClose={onClose}\n headerRight={\n <View style={styles.headerRight}>\n <View style={[styles.gwDot, { backgroundColor: connected ? '#22c55e' : '#94a3b8' }]} />\n <Pressable\n onPress={handleNew}\n disabled={!canCreate}\n accessibilityLabel=\"Start new task\"\n style={({ pressed }) => [\n styles.newBtn,\n pressed && styles.pressed,\n !canCreate && styles.disabled,\n ]}\n >\n <MaterialCommunityIcons name=\"plus\" size={16} color={mobileTokens.color.primary} />\n </Pressable>\n </View>\n }\n >\n <ScrollView style={{ flex: 1 }} contentContainerStyle={styles.list} keyboardShouldPersistTaps=\"handled\">\n {session.tasks.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>\n {connected ? 'No tasks yet. Create one to get started.' : 'Connect Yantra to create tasks.'}\n </Text>\n ) : (\n session.tasks.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n isActive={session.activeTaskId === task.id}\n isDark={isDark}\n onSelect={() => agentSessionManager.setActiveTask(task.id)}\n onRemove={() => agentSessionManager.removeTask(task.id)}\n />\n ))\n )}\n </ScrollView>\n </HeaderSheet>\n );\n}\n\nexport function HeaderTasksButton({ isDark }: Props) {\n const session = useAgentSessionState();\n const [open, setOpen] = useState(false);\n\n useFocusEffect(\n useCallback(() => {\n return () => setOpen(false);\n }, []),\n );\n\n return (\n <>\n <HeaderToolbarButton\n icon=\"pulse\"\n label=\"Tasks\"\n badge={session.tasks.length}\n active={open}\n onPress={() => setOpen(true)}\n accessibilityLabel=\"Tasks\"\n isDark={isDark}\n />\n {open ? <TasksSheet isDark={isDark} onClose={() => setOpen(false)} /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n list: {\n paddingHorizontal: 16,\n paddingBottom: 12,\n gap: 8,\n },\n row: {\n flexDirection: 'row',\n alignItems: 'flex-start',\n gap: 10,\n borderRadius: 12,\n borderWidth: 1,\n borderColor: 'transparent',\n paddingHorizontal: 12,\n paddingVertical: 10,\n backgroundColor: mobileTokens.color.surfaceMuted,\n },\n rowActive: {\n borderColor: mobileTokens.color.primaryBorder,\n backgroundColor: mobileTokens.color.primarySoft,\n },\n rowActiveDark: {\n backgroundColor: 'rgba(79,70,229,0.18)',\n },\n pressed: {\n opacity: 0.7,\n },\n disabled: {\n opacity: 0.4,\n },\n titleRow: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n minWidth: 0,\n },\n skillChip: {\n maxWidth: 96,\n borderRadius: 6,\n paddingHorizontal: 6,\n paddingVertical: 2,\n backgroundColor: mobileTokens.color.surface,\n },\n skillChipDark: {\n backgroundColor: '#0f172a',\n },\n skillChipText: {\n fontSize: 10,\n fontWeight: '600',\n },\n rowBody: {\n flex: 1,\n minWidth: 0,\n gap: 2,\n },\n rowTitle: {\n flexShrink: 1,\n fontSize: 14,\n fontWeight: '600',\n },\n rowMeta: {\n fontSize: 12,\n },\n empty: {\n fontSize: 14,\n lineHeight: 20,\n paddingVertical: 20,\n textAlign: 'center',\n },\n headerRight: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n },\n gwDot: {\n width: 6,\n height: 6,\n borderRadius: 3,\n },\n newBtn: {\n width: 32,\n height: 32,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 10,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HeaderTasksButton.js","sources":["../../../src/components/NavigationHeader/HeaderTasksButton.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport { ActivityIndicator, Linking, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { useFocusEffect, useNavigation, type NavigationProp, type ParamListBase } from '@react-navigation/native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { isJobRunning, jobDetailLine, jobStateLabel, slugLabel, type CentralJob } from 'common';\nimport { MAX_CONCURRENT_TASKS } from '../../config/constants';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useGatewayContext } from '../../contexts/GatewayContext';\nimport { WEBBUILDER_JOB_SURFACE } from '../../features/webbuilder/buildJob';\nimport { useAgentSessionState } from '../../hooks/useAgentSessionState';\nimport { useSurfaceJobs } from '../../hooks/useSurfaceJobs';\nimport { agentSessionManager, type AgentTask, type TaskStatus } from '../../services/agentSessionManager';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport { HeaderSheet } from './HeaderSheet';\nimport { HeaderToolbarButton } from './HeaderToolbarButton';\n\ntype Props = {\n isDark: boolean;\n};\n\nconst STATUS_LABEL: Record<TaskStatus, string> = {\n idle: 'Idle',\n connecting: 'Connecting',\n running: 'Running',\n completed: 'Completed',\n failed: 'Failed',\n aborted: 'Aborted',\n};\n\ntype IconName = React.ComponentProps<typeof MaterialCommunityIcons>['name'];\n\n/** The glyph and its light/dark tone for a finished status; anything else is a plain circle. */\nconst STATUS_GLYPH: Partial<Record<TaskStatus, { name: IconName; light: string; dark: string }>> = {\n completed: { name: 'check-circle-outline', light: '#16a34a', dark: '#4ade80' },\n failed: { name: 'alert-circle-outline', light: '#dc2626', dark: '#f87171' },\n aborted: { name: 'close-circle-outline', light: '#ea580c', dark: '#fb923c' },\n};\n\nfunction StatusGlyph({ status, isDark }: { status: TaskStatus; isDark: boolean }) {\n if (status === 'running' || status === 'connecting') {\n return <ActivityIndicator size={14} color={isDark ? '#60a5fa' : '#2563eb'} />;\n }\n const glyph = STATUS_GLYPH[status];\n if (!glyph) {\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n return <MaterialCommunityIcons name=\"circle-outline\" size={16} color={muted} />;\n }\n return <MaterialCommunityIcons name={glyph.name} size={16} color={isDark ? glyph.dark : glyph.light} />;\n}\n\n/** The last message, cut to a line. */\nfunction previewOf(task: AgentTask): string {\n const last = task.messages[task.messages.length - 1];\n if (!last) return 'No messages yet';\n return last.content.length > 60 ? `${last.content.slice(0, 60)}…` : last.content;\n}\n\nfunction TaskRow({\n task,\n isActive,\n isDark,\n onSelect,\n onRemove,\n}: {\n task: AgentTask;\n isActive: boolean;\n isDark: boolean;\n onSelect: () => void;\n onRemove: () => void;\n}) {\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const preview = previewOf(task);\n const skillLabel = task.skillTemplateName || task.skillTemplate;\n\n return (\n <Pressable\n onPress={onSelect}\n style={({ pressed }) => [\n styles.row,\n isActive && styles.rowActive,\n isDark && isActive && styles.rowActiveDark,\n pressed && styles.pressed,\n ]}\n >\n <StatusGlyph status={task.status} isDark={isDark} />\n <View style={styles.rowBody}>\n <View style={styles.titleRow}>\n <Text style={[styles.rowTitle, { color: foreground }]} numberOfLines={1}>\n {task.title}\n </Text>\n {skillLabel ? (\n <View style={[styles.skillChip, isDark && styles.skillChipDark]}>\n <Text style={[styles.skillChipText, { color: muted }]} numberOfLines={1}>\n {skillLabel}\n </Text>\n </View>\n ) : null}\n </View>\n <Text style={[styles.rowMeta, { color: muted }]} numberOfLines={1}>\n {STATUS_LABEL[task.status]} · {preview}\n </Text>\n </View>\n <Pressable onPress={onRemove} hitSlop={8} accessibilityLabel=\"Remove task\">\n <MaterialCommunityIcons name=\"trash-can-outline\" size={16} color={muted} />\n </Pressable>\n </Pressable>\n );\n}\n\n/** A long-running job (a Web Builder build, a canvas video, ...) from the server's record. */\nfunction JobRow({\n job,\n now,\n isDark,\n onOpen,\n onDismiss,\n}: {\n job: CentralJob;\n now: number;\n isDark: boolean;\n onOpen: (() => void) | null;\n onDismiss: () => void;\n}) {\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const stateLabel = jobStateLabel(job, now);\n const detail = jobDetailLine(job);\n\n return (\n <Pressable\n onPress={onOpen ?? undefined}\n disabled={!onOpen}\n accessibilityRole=\"button\"\n accessibilityLabel={`${job.title}, ${stateLabel}`}\n style={({ pressed }) => [styles.row, pressed && styles.pressed]}\n >\n {job.state === 'running' ? (\n <ActivityIndicator size={14} color={isDark ? '#60a5fa' : '#2563eb'} />\n ) : (\n <StatusGlyph status={job.state === 'succeeded' ? 'completed' : 'failed'} isDark={isDark} />\n )}\n <View style={styles.rowBody}>\n <View style={styles.titleRow}>\n <Text style={[styles.rowTitle, { color: foreground }]} numberOfLines={1}>\n {job.title}\n </Text>\n <View style={[styles.skillChip, isDark && styles.skillChipDark]}>\n <Text style={[styles.skillChipText, { color: muted }]} numberOfLines={1}>\n {slugLabel(job.slug)}\n </Text>\n </View>\n </View>\n <Text style={[styles.rowMeta, { color: muted }]} numberOfLines={2}>\n {detail ? `${stateLabel} · ${detail}` : stateLabel}\n </Text>\n </View>\n {job.state === 'running' ? null : (\n <Pressable onPress={onDismiss} hitSlop={8} accessibilityLabel=\"Remove task\">\n <MaterialCommunityIcons name=\"trash-can-outline\" size={16} color={muted} />\n </Pressable>\n )}\n </Pressable>\n );\n}\n\n/** The chat a Web Builder job built in, which its screen reopens. */\nfunction webBuilderChannel(job: CentralJob): string | null {\n const channelId = job.handle?.channelId;\n return job.slug === WEBBUILDER_JOB_SURFACE && typeof channelId === 'string' && channelId ? channelId : null;\n}\n\nfunction TasksSheet({\n isDark,\n onClose,\n jobs,\n runningJobs,\n onDismissJob,\n}: {\n isDark: boolean;\n onClose: () => void;\n jobs: CentralJob[];\n runningJobs: number;\n onDismissJob: (id: string) => void;\n}) {\n const session = useAgentSessionState();\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n // Running jobs show the time they have worked, so the clock ticks while one runs.\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n if (!jobs.some(isJobRunning)) return undefined;\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, [jobs]);\n const openJob = useCallback(\n (job: CentralJob): (() => void) | null => {\n const channelId = webBuilderChannel(job);\n if (channelId) {\n return () => {\n onClose();\n navigation.navigate('MainStack.WebBuilderNative', { openChannelId: channelId });\n };\n }\n const { pageUrl } = job;\n if (!pageUrl) return null;\n return () => {\n onClose();\n Linking.openURL(pageUrl).catch(() => undefined);\n };\n },\n [navigation, onClose],\n );\n const { selectedGateway } = useGatewayContext();\n const cdecli = useCdecliConnection();\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const cdecliSelected = selectedGateway?.channelType === 'cdecli-serve';\n const connected = cdecliSelected ? cdecli.channelConnected : session.gatewayConnected;\n const canCreate = session.tasks.length < MAX_CONCURRENT_TASKS && (cdecliSelected || session.gatewayConnected);\n\n const handleNew = useCallback(() => {\n if (!canCreate) return;\n agentSessionManager.createTask({ title: 'General Assistant' });\n }, [canCreate]);\n\n return (\n <HeaderSheet\n visible\n title=\"Tasks\"\n subtitle={\n jobs.length\n ? `${runningJobs} running · ${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`\n : `${session.tasks.length} of ${MAX_CONCURRENT_TASKS} slots`\n }\n isDark={isDark}\n onClose={onClose}\n headerRight={\n <View style={styles.headerRight}>\n <View style={[styles.gwDot, { backgroundColor: connected ? '#22c55e' : '#94a3b8' }]} />\n <Pressable\n onPress={handleNew}\n disabled={!canCreate}\n accessibilityLabel=\"Start new task\"\n style={({ pressed }) => [\n styles.newBtn,\n pressed && styles.pressed,\n !canCreate && styles.disabled,\n ]}\n >\n <MaterialCommunityIcons name=\"plus\" size={16} color={mobileTokens.color.primary} />\n </Pressable>\n </View>\n }\n >\n <ScrollView style={{ flex: 1 }} contentContainerStyle={styles.list} keyboardShouldPersistTaps=\"handled\">\n {jobs.length > 0 ? (\n <>\n <Text style={[styles.sectionLabel, { color: muted }]}>Jobs</Text>\n {jobs.map((job) => (\n <JobRow\n key={job.id}\n job={job}\n now={now}\n isDark={isDark}\n onOpen={openJob(job)}\n onDismiss={() => onDismissJob(job.id)}\n />\n ))}\n {session.tasks.length > 0 ? (\n <Text style={[styles.sectionLabel, { color: muted }]}>Sessions</Text>\n ) : null}\n </>\n ) : null}\n {session.tasks.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n isActive={session.activeTaskId === task.id}\n isDark={isDark}\n onSelect={() => agentSessionManager.setActiveTask(task.id)}\n onRemove={() => agentSessionManager.removeTask(task.id)}\n />\n ))}\n {session.tasks.length === 0 && jobs.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>\n {connected ? 'No tasks yet. Create one to get started.' : 'Connect Yantra to create tasks.'}\n </Text>\n ) : null}\n </ScrollView>\n </HeaderSheet>\n );\n}\n\nexport function HeaderTasksButton({ isDark }: Props) {\n const session = useAgentSessionState();\n const [open, setOpen] = useState(false);\n const surfaceJobs = useSurfaceJobs(open);\n const { refresh: refreshJobs } = surfaceJobs;\n // Opening the sheet reads the jobs again rather than showing the last poll.\n useEffect(() => {\n if (open) refreshJobs();\n }, [open, refreshJobs]);\n\n useFocusEffect(useCallback(() => () => setOpen(false), []));\n\n return (\n <>\n <HeaderToolbarButton\n icon=\"pulse\"\n label=\"Tasks\"\n badge={session.tasks.length + surfaceJobs.runningCount}\n active={open}\n onPress={() => setOpen(true)}\n accessibilityLabel=\"Tasks\"\n isDark={isDark}\n />\n {open ? (\n <TasksSheet\n isDark={isDark}\n onClose={() => setOpen(false)}\n jobs={surfaceJobs.jobs}\n runningJobs={surfaceJobs.runningCount}\n onDismissJob={surfaceJobs.dismiss}\n />\n ) : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n list: {\n paddingHorizontal: 16,\n paddingBottom: 12,\n gap: 8,\n },\n row: {\n flexDirection: 'row',\n alignItems: 'flex-start',\n gap: 10,\n borderRadius: 12,\n borderWidth: 1,\n borderColor: 'transparent',\n paddingHorizontal: 12,\n paddingVertical: 10,\n backgroundColor: mobileTokens.color.surfaceMuted,\n },\n rowActive: {\n borderColor: mobileTokens.color.primaryBorder,\n backgroundColor: mobileTokens.color.primarySoft,\n },\n rowActiveDark: {\n backgroundColor: 'rgba(79,70,229,0.18)',\n },\n pressed: {\n opacity: 0.7,\n },\n disabled: {\n opacity: 0.4,\n },\n titleRow: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n minWidth: 0,\n },\n skillChip: {\n maxWidth: 96,\n borderRadius: 6,\n paddingHorizontal: 6,\n paddingVertical: 2,\n backgroundColor: mobileTokens.color.surface,\n },\n skillChipDark: {\n backgroundColor: '#0f172a',\n },\n skillChipText: {\n fontSize: 10,\n fontWeight: '600',\n },\n rowBody: {\n flex: 1,\n minWidth: 0,\n gap: 2,\n },\n rowTitle: {\n flexShrink: 1,\n fontSize: 14,\n fontWeight: '600',\n },\n rowMeta: {\n fontSize: 12,\n },\n sectionLabel: {\n fontSize: 11,\n fontWeight: '700',\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n marginTop: 4,\n },\n empty: {\n fontSize: 14,\n lineHeight: 20,\n paddingVertical: 20,\n textAlign: 'center',\n },\n headerRight: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n },\n gwDot: {\n width: 6,\n height: 6,\n borderRadius: 3,\n },\n newBtn: {\n width: 32,\n height: 32,\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 10,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {useMemo,useState,useCallback,useRef,useEffect}from'react';import {StyleSheet,Keyboard,BackHandler,View,Text,Share,Platform,ActionSheetIOS,Alert,Linking}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {GestureHandlerRootView}from'react-native-gesture-handler';import {useSafeInsets}from'../canvas/withRemoteSafeArea.js';import {useAppTheme}from'../../theme/AppThemeProvider.js';import {Tap,DIM}from'../inbox/components/Tap.js';import {isBareSeed,studioTurnText,brandBriefBlock,siteScoreTurn}from'./studioCatalog.js';import {useBrandKit}from'./brandKitStorage.js';import {parseToolActivity}from'../chat/toolActivity.js';import {wakePreviewPrompt}from'./webbuilderPrompts.js';import {webbuilderTheme}from'./webbuilderTheme.js';import {BrandKitSheet}from'./components/BrandKitSheet.js';import {CodeView}from'./components/CodeView.js';import {ProjectChat}from'./components/ProjectChat.js';import {PreviewScreen}from'./components/PreviewScreen.js';import {PublishSheet}from'./components/PublishSheet.js';import {BOTTOM_TABS_SPACE,BottomTabs}from'./components/BottomTabs.js';import {SiteScoreSheet}from'./components/SiteScoreSheet.js';import {ProjectsScreen}from'./components/ProjectsScreen.js';import {TemplatesSheet}from'./components/TemplatesSheet.js';import {StudioHome}from'./components/StudioHome.js';import {VersionsSheet}from'./components/VersionsSheet.js';import {IconButton,Toast}from'./components/ui.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {useMemo,useState,useCallback,useRef,useEffect}from'react';import {StyleSheet,Keyboard,BackHandler,View,Text,Share,Platform,ActionSheetIOS,Alert,Linking}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {GestureHandlerRootView}from'react-native-gesture-handler';import {useSafeInsets}from'../canvas/withRemoteSafeArea.js';import {useAppTheme}from'../../theme/AppThemeProvider.js';import {Tap,DIM}from'../inbox/components/Tap.js';import {isBareSeed,studioTurnText,brandBriefBlock,siteScoreTurn}from'./studioCatalog.js';import {titleFromPrompt}from'./buildFragments.js';import {useBrandKit}from'./brandKitStorage.js';import {parseToolActivity}from'../chat/toolActivity.js';import {wakePreviewPrompt}from'./webbuilderPrompts.js';import {webbuilderTheme}from'./webbuilderTheme.js';import {BrandKitSheet}from'./components/BrandKitSheet.js';import {CodeView}from'./components/CodeView.js';import {ProjectChat}from'./components/ProjectChat.js';import {PreviewScreen}from'./components/PreviewScreen.js';import {PublishSheet}from'./components/PublishSheet.js';import {BOTTOM_TABS_SPACE,BottomTabs}from'./components/BottomTabs.js';import {SiteScoreSheet}from'./components/SiteScoreSheet.js';import {ProjectsScreen}from'./components/ProjectsScreen.js';import {TemplatesSheet}from'./components/TemplatesSheet.js';import {StudioHome}from'./components/StudioHome.js';import {VersionsSheet}from'./components/VersionsSheet.js';import {IconButton,Toast}from'./components/ui.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
3
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
4
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -44,7 +44,7 @@ function WebBuilderExperience({
|
|
|
44
44
|
onResumePreview,
|
|
45
45
|
initialAgentSeed = null
|
|
46
46
|
}) {
|
|
47
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
47
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
48
48
|
const appTheme = useAppTheme();
|
|
49
49
|
const isDark = hostIsDark != null ? hostIsDark : appTheme.isDark;
|
|
50
50
|
const theme = useMemo(() => webbuilderTheme(isDark), [isDark]);
|
|
@@ -103,7 +103,9 @@ function WebBuilderExperience({
|
|
|
103
103
|
var _a2;
|
|
104
104
|
return selectedKey ? (_a2 = builds.find((b) => b.key === selectedKey)) != null ? _a2 : latest : latest;
|
|
105
105
|
}, [builds, selectedKey, latest]);
|
|
106
|
-
const
|
|
106
|
+
const firstAsk = (_b = hostChat == null ? void 0 : hostChat.messages.find((m) => m.role === "user")) == null ? void 0 : _b.content;
|
|
107
|
+
const askTitle = useMemo(() => titleFromPrompt(firstAsk), [firstAsk]);
|
|
108
|
+
const siteTitle = (project == null ? void 0 : project.title) || (build == null ? void 0 : build.title) || askTitle || null;
|
|
107
109
|
const [previewNonce, setPreviewNonce] = useState(0);
|
|
108
110
|
const seenBuildAt = useRef({
|
|
109
111
|
key: null,
|
|
@@ -207,7 +209,7 @@ function WebBuilderExperience({
|
|
|
207
209
|
});
|
|
208
210
|
return () => sub.remove();
|
|
209
211
|
}, [back]);
|
|
210
|
-
const live = (
|
|
212
|
+
const live = (_d = (_c = build == null ? void 0 : build.liveUrl) != null ? _c : project == null ? void 0 : project.liveUrl) != null ? _d : null;
|
|
211
213
|
let statusText = "New";
|
|
212
214
|
let statusTone = theme.muted;
|
|
213
215
|
if (building || (hostChat == null ? void 0 : hostChat.busy)) {
|
|
@@ -318,12 +320,12 @@ function WebBuilderExperience({
|
|
|
318
320
|
] })
|
|
319
321
|
] })
|
|
320
322
|
] }),
|
|
321
|
-
mode === "chat" ? /* @__PURE__ */ jsx(ProjectChat, { messages: (
|
|
322
|
-
mode === "preview" ? /* @__PURE__ */ jsx(PreviewScreen, { build, building, loading: buildsLoading, previewNonce, onReload: () => setPreviewNonce((n) => n + 1), onHome: () => setPreviewNonce((n) => n + 1), onWake: wakePreview, waking: waking || Boolean(hostChat == null ? void 0 : hostChat.busy), steps: liveSteps, onPublish: () => setPublishOpen(true), publishLabel, error: (
|
|
323
|
+
mode === "chat" ? /* @__PURE__ */ jsx(ProjectChat, { messages: (_e = hostChat == null ? void 0 : hostChat.messages) != null ? _e : [], streaming: (_f = hostChat == null ? void 0 : hostChat.streaming) != null ? _f : null, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), error: (_g = hostChat == null ? void 0 : hostChat.error) != null ? _g : null, connected: Boolean(hostChat == null ? void 0 : hostChat.connected), building, build, siteTitle: siteTitle || "Your site", onSend: (text) => sendToAgent(text), onOpenPreview: () => setMode("preview"), onPublish: () => setPublishOpen(true), onPreviewAsleep: wakePreview, theme, bottomInset: insets.bottom }) : null,
|
|
324
|
+
mode === "preview" ? /* @__PURE__ */ jsx(PreviewScreen, { build, building, loading: buildsLoading, previewNonce, onReload: () => setPreviewNonce((n) => n + 1), onHome: () => setPreviewNonce((n) => n + 1), onWake: wakePreview, waking: waking || Boolean(hostChat == null ? void 0 : hostChat.busy), steps: liveSteps, onPublish: () => setPublishOpen(true), publishLabel, error: (_h = hostChat == null ? void 0 : hostChat.error) != null ? _h : null, theme, bottomInset: insets.bottom }) : null,
|
|
323
325
|
mode === "code" ? /* @__PURE__ */ jsx(View, { style: [styles.fill, {
|
|
324
326
|
backgroundColor: theme.card,
|
|
325
327
|
paddingBottom: insets.bottom
|
|
326
|
-
}], children: /* @__PURE__ */ jsx(CodeView, { files: (
|
|
328
|
+
}], children: /* @__PURE__ */ jsx(CodeView, { files: (_i = build == null ? void 0 : build.files) != null ? _i : null, theme, onAsk: openChat }) }) : null
|
|
327
329
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
328
330
|
homeTab === "create" ? /* @__PURE__ */ jsx(View, { style: [styles.header, styles.headerBare, {
|
|
329
331
|
paddingTop: insets.top + 4,
|
|
@@ -332,7 +334,7 @@ function WebBuilderExperience({
|
|
|
332
334
|
/* @__PURE__ */ jsx(View, { style: styles.fill, children: homeTab === "create" ? /* @__PURE__ */ jsx(StudioHome, { draft, onDraft: setDraft, template, onClearTemplate: () => setTemplate(null), onBrowseTemplates: () => setTemplatesOpen(true), brand, onBrand: () => setBrandOpen(true), onSiteScore: () => setScoreOpen(true), onStart: startSite, connecting: startBlocked, startNotice, theme, bottomInset: BOTTOM_TABS_SPACE + insets.bottom }) : /* @__PURE__ */ jsx(ProjectsScreen, { projects, loading: projectsLoading, error: projectsError, hasMore: projectsHasMore, onRefresh: onRefreshProjects, onLoadMore: onLoadMoreProjects, onOpen: (p) => onOpenProject(p.channelId), onNewProject: () => setHomeTab("create"), topInset: insets.top + 12, bottomInset: BOTTOM_TABS_SPACE + insets.bottom, theme }) }),
|
|
333
335
|
/* @__PURE__ */ jsx(BottomTabs, { tab: homeTab, onTab: setHomeTab, theme, bottomInset: insets.bottom })
|
|
334
336
|
] }),
|
|
335
|
-
/* @__PURE__ */ jsx(TemplatesSheet, { visible: templatesOpen, onClose: () => setTemplatesOpen(false), templates, loading: templatesLoading, error: templatesError, onReload: onReloadTemplates, selectedId: (
|
|
337
|
+
/* @__PURE__ */ jsx(TemplatesSheet, { visible: templatesOpen, onClose: () => setTemplatesOpen(false), templates, loading: templatesLoading, error: templatesError, onReload: onReloadTemplates, selectedId: (_j = template == null ? void 0 : template.id) != null ? _j : null, onPick: pickTemplate, theme }),
|
|
336
338
|
/* @__PURE__ */ jsx(SiteScoreSheet, { visible: scoreOpen, onClose: () => setScoreOpen(false), blocked: startBlocked, onCheck: (url) => {
|
|
337
339
|
setScoreOpen(false);
|
|
338
340
|
onStartProject({
|