@adminide-stack/yantra-mobile 12.0.125-alpha.0 → 12.0.125
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/features/canvas/AudioEditorExperience.js +207 -109
- package/lib/features/canvas/AudioEditorExperience.js.map +1 -1
- package/lib/features/canvas/CanvasAgentChatPane.js +87 -72
- package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
- package/lib/features/canvas/CanvasBoardsGrid.js +494 -387
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasChatResultCard.js +78 -59
- package/lib/features/canvas/CanvasChatResultCard.js.map +1 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js +126 -84
- package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +108 -126
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/CanvasGeneratePanel.js +178 -166
- package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
- package/lib/features/canvas/CanvasLibrarySheet.js +119 -123
- package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -1
- package/lib/features/canvas/CanvasLooksPanel.js +113 -89
- package/lib/features/canvas/CanvasLooksPanel.js.map +1 -1
- package/lib/features/canvas/CanvasModelPicker.js +79 -79
- package/lib/features/canvas/CanvasModelPicker.js.map +1 -1
- package/lib/features/canvas/CanvasTasksPanel.js +193 -128
- package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
- package/lib/features/canvas/CanvasTemplatesPanel.js +106 -94
- package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -1
- package/lib/features/canvas/CanvasToolDock.js +195 -127
- package/lib/features/canvas/CanvasToolDock.js.map +1 -1
- package/lib/features/canvas/FrameExtractorExperience.js +163 -100
- package/lib/features/canvas/FrameExtractorExperience.js.map +1 -1
- package/lib/features/canvas/GeneratorReferenceSlots.js +132 -69
- package/lib/features/canvas/GeneratorReferenceSlots.js.map +1 -1
- package/lib/features/canvas/ImageEditorExperience.js +278 -209
- package/lib/features/canvas/ImageEditorExperience.js.map +1 -1
- package/lib/features/canvas/InfluencerStudioExperience.js +167 -125
- package/lib/features/canvas/InfluencerStudioExperience.js.map +1 -1
- package/lib/features/canvas/MoodboardExperience.js +102 -85
- package/lib/features/canvas/MoodboardExperience.js.map +1 -1
- package/lib/features/canvas/NativeCanvasViewer.js +203 -192
- package/lib/features/canvas/NativeCanvasViewer.js.map +1 -1
- package/lib/features/canvas/PromoContextFields.js +125 -92
- package/lib/features/canvas/PromoContextFields.js.map +1 -1
- package/lib/features/canvas/SetStudioExperience.js +225 -143
- package/lib/features/canvas/SetStudioExperience.js.map +1 -1
- package/lib/features/canvas/VideoClipsExperience.js +126 -92
- package/lib/features/canvas/VideoClipsExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditExperience.js +154 -142
- package/lib/features/canvas/VideoEditExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditorExperience.js +551 -492
- package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
- package/lib/features/canvas/VideoGeneratorExperience.js +284 -131
- package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
- package/lib/features/canvas/canvasTasks.js +7 -3
- package/lib/features/canvas/canvasTasks.js.map +1 -1
- package/lib/features/canvas/canvasTheme.js +265 -0
- package/lib/features/canvas/canvasTheme.js.map +1 -0
- package/lib/features/canvas/canvasUi.js +381 -0
- package/lib/features/canvas/canvasUi.js.map +1 -0
- package/lib/features/canvas/recorder/CameraRecorderExperience.js +109 -52
- package/lib/features/canvas/recorder/CameraRecorderExperience.js.map +1 -1
- package/lib/features/canvas/serverTasks.js +1 -1
- package/lib/features/canvas/serverTasks.js.map +1 -1
- package/lib/features/canvas/set/SetViewportWebView.js +1 -1
- package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +8 -7
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js.map +1 -1
- package/lib/features/canvas/videoEditor/ExportTaskCard.js +44 -41
- package/lib/features/canvas/videoEditor/ExportTaskCard.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +50 -45
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportTask.js +3 -2
- package/lib/features/canvas/videoEditor/exportTask.js.map +1 -1
- package/lib/features/canvas/videoEditor/formWidgets.js +116 -64
- package/lib/features/canvas/videoEditor/formWidgets.js.map +1 -1
- package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js +77 -63
- package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js.map +1 -1
- package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js +95 -79
- package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js.map +1 -1
- package/lib/features/design/DesignEditorExperience.js +241 -160
- package/lib/features/design/DesignEditorExperience.js.map +1 -1
- package/lib/features/design/DesignExperience.js +300 -143
- package/lib/features/design/DesignExperience.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +3 -2
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/components/PublishSheet.js +1 -1
- package/lib/features/webbuilder/components/PublishSheet.js.map +1 -1
- package/lib/features/webbuilder/webbuilderPrompts.js +2 -5
- package/lib/features/webbuilder/webbuilderPrompts.js.map +1 -1
- package/lib/screens/WebBuilderNative/sandboxProxyApi.js +120 -0
- package/lib/screens/WebBuilderNative/sandboxProxyApi.js.map +1 -0
- package/lib/screens/WebBuilderNative/useRestoredSandboxes.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +26 -4
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/lib/screens/WebBuilderNative/webbuilderTransport.js +110 -7
- package/lib/screens/WebBuilderNative/webbuilderTransport.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsxs,jsx}from'react/jsx-runtime';import {useState,useEffect}from'react';import {
|
|
1
|
+
import {jsxs,jsx}from'react/jsx-runtime';import {useState,useEffect,useMemo}from'react';import {View,Text,ActivityIndicator,StyleSheet}from'react-native';import {getCanvasTask,subscribeCanvasTasks}from'../canvasTasks.js';import {friendlyMediaError}from'./mediaActions.js';import {renderProgressPct,renderTimeLeft}from'./renderTimeline.js';import {useCanvasTheme,themedStyles}from'../canvasTheme.js';import {Pressable,pressedStyle,RADIUS,SPACE,TYPE}from'../canvasUi.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -57,17 +57,21 @@ function ExportTaskCard({
|
|
|
57
57
|
onBackground
|
|
58
58
|
}) {
|
|
59
59
|
var _a;
|
|
60
|
+
const theme = useCanvasTheme();
|
|
61
|
+
const styles = useMemo(() => makeStyles(theme), [theme]);
|
|
60
62
|
if (!task) return null;
|
|
61
63
|
if (task.state === "failed") {
|
|
62
64
|
return /* @__PURE__ */ jsxs(View, { style: styles.card, testID: "export-task-card", children: [
|
|
63
65
|
/* @__PURE__ */ jsx(Text, { style: styles.error, children: "Export failed" }),
|
|
64
66
|
/* @__PURE__ */ jsx(Text, { style: styles.stage, numberOfLines: 5, children: friendlyMediaError(new Error(task.error || "The render failed"), "video export") }),
|
|
65
|
-
/* @__PURE__ */ jsx(Pressable, { onPress: onDismiss, style:
|
|
67
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: onDismiss, style: ({
|
|
68
|
+
pressed
|
|
69
|
+
}) => [styles.button, pressedStyle(pressed)], accessibilityRole: "button", children: /* @__PURE__ */ jsx(Text, { style: styles.buttonLabel, children: "Dismiss" }) })
|
|
66
70
|
] });
|
|
67
71
|
}
|
|
68
72
|
const lines = exportCardLines(task);
|
|
69
73
|
return /* @__PURE__ */ jsxs(View, { style: styles.card, testID: "export-task-card", children: [
|
|
70
|
-
/* @__PURE__ */ jsx(ActivityIndicator, { color:
|
|
74
|
+
/* @__PURE__ */ jsx(ActivityIndicator, { color: theme.edInk }),
|
|
71
75
|
/* @__PURE__ */ jsx(Text, { style: styles.stage, numberOfLines: 2, children: lines.stage }),
|
|
72
76
|
lines.pct !== void 0 ? /* @__PURE__ */ jsx(View, { style: styles.bar, children: /* @__PURE__ */ jsx(View, { style: [styles.barFill, {
|
|
73
77
|
width: `${lines.pct}%`
|
|
@@ -75,60 +79,59 @@ function ExportTaskCard({
|
|
|
75
79
|
lines.timeLeft ? /* @__PURE__ */ jsx(Text, { style: styles.meta, children: lines.timeLeft }) : null,
|
|
76
80
|
task.notice ? /* @__PURE__ */ jsx(Text, { style: styles.notice, children: task.notice }) : null,
|
|
77
81
|
((_a = task.warnings) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(Text, { style: styles.meta, numberOfLines: 3, children: task.warnings[0] }) : null,
|
|
78
|
-
task.state === "running" && !task.local ? /* @__PURE__ */ jsx(Pressable, { onPress: onBackground, style:
|
|
82
|
+
task.state === "running" && !task.local ? /* @__PURE__ */ jsx(Pressable, { onPress: onBackground, style: ({
|
|
83
|
+
pressed
|
|
84
|
+
}) => [styles.button, pressedStyle(pressed)], accessibilityRole: "button", children: /* @__PURE__ */ jsx(Text, { style: styles.buttonLabel, children: "Keep rendering in background" }) }) : null
|
|
79
85
|
] });
|
|
80
86
|
}
|
|
81
|
-
const
|
|
87
|
+
const makeStyles = themedStyles((theme) => StyleSheet.create({
|
|
82
88
|
card: {
|
|
83
89
|
minWidth: 240,
|
|
84
90
|
maxWidth: 320,
|
|
85
|
-
padding:
|
|
86
|
-
borderRadius:
|
|
87
|
-
backgroundColor:
|
|
91
|
+
padding: SPACE.xl,
|
|
92
|
+
borderRadius: RADIUS.xl,
|
|
93
|
+
backgroundColor: theme.edPanel,
|
|
88
94
|
alignItems: "center",
|
|
89
|
-
gap:
|
|
95
|
+
gap: SPACE.md
|
|
90
96
|
},
|
|
91
|
-
stage: {
|
|
92
|
-
|
|
97
|
+
stage: __spreadProps(__spreadValues({}, TYPE.label), {
|
|
98
|
+
fontWeight: "500",
|
|
93
99
|
fontSize: 14,
|
|
100
|
+
color: theme.edInk,
|
|
94
101
|
textAlign: "center"
|
|
95
|
-
},
|
|
96
|
-
meta: {
|
|
97
|
-
color:
|
|
98
|
-
fontSize: 12,
|
|
102
|
+
}),
|
|
103
|
+
meta: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
104
|
+
color: theme.edInk2,
|
|
99
105
|
textAlign: "center"
|
|
100
|
-
},
|
|
101
|
-
notice: {
|
|
102
|
-
color:
|
|
103
|
-
fontSize: 12,
|
|
106
|
+
}),
|
|
107
|
+
notice: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
108
|
+
color: theme.edWarn,
|
|
104
109
|
textAlign: "center"
|
|
105
|
-
},
|
|
106
|
-
error: {
|
|
107
|
-
color:
|
|
108
|
-
|
|
109
|
-
fontWeight: "700"
|
|
110
|
-
},
|
|
110
|
+
}),
|
|
111
|
+
error: __spreadProps(__spreadValues({}, TYPE.title), {
|
|
112
|
+
color: theme.edDanger
|
|
113
|
+
}),
|
|
111
114
|
bar: {
|
|
112
115
|
alignSelf: "stretch",
|
|
113
|
-
height:
|
|
114
|
-
borderRadius:
|
|
115
|
-
backgroundColor:
|
|
116
|
+
height: 6,
|
|
117
|
+
borderRadius: RADIUS.pill,
|
|
118
|
+
backgroundColor: theme.edRaisedHi,
|
|
116
119
|
overflow: "hidden"
|
|
117
120
|
},
|
|
118
121
|
barFill: {
|
|
119
|
-
height:
|
|
120
|
-
|
|
122
|
+
height: 6,
|
|
123
|
+
borderRadius: RADIUS.pill,
|
|
124
|
+
backgroundColor: theme.edAccent
|
|
121
125
|
},
|
|
122
126
|
button: {
|
|
123
|
-
marginTop:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
marginTop: SPACE.xs,
|
|
128
|
+
minHeight: 40,
|
|
129
|
+
justifyContent: "center",
|
|
130
|
+
paddingHorizontal: SPACE.lg,
|
|
131
|
+
borderRadius: RADIUS.pill,
|
|
132
|
+
backgroundColor: theme.edRaised
|
|
128
133
|
},
|
|
129
|
-
buttonLabel: {
|
|
130
|
-
color:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
});export{ExportTaskCard,exportCardLines,useCanvasTask};//# sourceMappingURL=ExportTaskCard.js.map
|
|
134
|
+
buttonLabel: __spreadProps(__spreadValues({}, TYPE.label), {
|
|
135
|
+
color: theme.edInk
|
|
136
|
+
})
|
|
137
|
+
}));export{ExportTaskCard,exportCardLines,useCanvasTask};//# sourceMappingURL=ExportTaskCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExportTaskCard.js","sources":["../../../../src/features/canvas/videoEditor/ExportTaskCard.tsx"],"sourcesContent":["/**\n * The editor's export progress card for a durable export task: step, the\n * connector's projected time left, its time-limit notice, compile warnings,\n * and a \"keep in background\" exit (the render carries on in More → Tasks).\n */\nimport React, { useEffect, useState } from 'react';\nimport { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native';\nimport { getCanvasTask, subscribeCanvasTasks, type CanvasTask } from '../canvasTasks';\nimport { friendlyMediaError } from './mediaActions';\nimport { renderProgressPct, renderTimeLeft } from './renderTimeline';\n\n/** Live view of one canvas task (re-renders on every store change + a 15s clock for the time left). */\nexport function useCanvasTask(id: string | null): CanvasTask | undefined {\n const [task, setTask] = useState<CanvasTask | undefined>(() => (id ? getCanvasTask(id) : undefined));\n const [, setTick] = useState(0);\n useEffect(() => {\n if (!id) {\n setTask(undefined);\n return undefined;\n }\n setTask(getCanvasTask(id));\n const unsub = subscribeCanvasTasks(() => setTask(getCanvasTask(id)));\n const clock = setInterval(() => setTick((n) => n + 1), 15_000);\n return () => {\n unsub();\n clearInterval(clock);\n };\n }, [id]);\n return task;\n}\n\n/** Card copy for a task, pure (tested). */\nexport function exportCardLines(\n task: CanvasTask,\n now = Date.now(),\n): { stage: string; timeLeft?: string; pct?: number } {\n const stage = task.lastLine || 'Rendering…';\n const projected = task.render?.projectedMs;\n if (task.state !== 'running' || !task.startedAt || task.local) return { stage };\n const elapsed = Math.max(0, now - task.startedAt);\n return {\n stage,\n ...(projected ? { timeLeft: renderTimeLeft(projected, elapsed) } : {}),\n pct: Math.round(renderProgressPct(task.step, projected, elapsed)),\n };\n}\n\nexport function ExportTaskCard({\n task,\n onDismiss,\n onBackground,\n}: {\n task: CanvasTask | undefined;\n onDismiss: () => void;\n /** Leave the render running and get back to the canvas. */\n onBackground: () => void;\n}) {\n if (!task) return null;\n if (task.state === 'failed') {\n return (\n <View style={styles.card} testID=\"export-task-card\">\n <Text style={styles.error}>Export failed</Text>\n <Text style={styles.stage} numberOfLines={5}>\n {friendlyMediaError(new Error(task.error || 'The render failed'), 'video export')}\n </Text>\n <Pressable onPress={onDismiss} style={styles.button} accessibilityRole=\"button\">\n <Text style={styles.buttonLabel}>Dismiss</Text>\n </Pressable>\n </View>\n );\n }\n const lines = exportCardLines(task);\n return (\n <View style={styles.card} testID=\"export-task-card\">\n <ActivityIndicator color=\"#F7F7FA\" />\n <Text style={styles.stage} numberOfLines={2}>\n {lines.stage}\n </Text>\n {lines.pct !== undefined ? (\n <View style={styles.bar}>\n <View style={[styles.barFill, { width: `${lines.pct}%` }]} />\n </View>\n ) : null}\n {lines.timeLeft ? <Text style={styles.meta}>{lines.timeLeft}</Text> : null}\n {task.notice ? <Text style={styles.notice}>{task.notice}</Text> : null}\n {task.warnings?.length ? (\n <Text style={styles.meta} numberOfLines={3}>\n {task.warnings[0]}\n </Text>\n ) : null}\n {task.state === 'running' && !task.local ? (\n <Pressable onPress={onBackground} style={styles.button} accessibilityRole=\"button\">\n <Text style={styles.buttonLabel}>Keep rendering in background</Text>\n </Pressable>\n ) : null}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n card: {\n minWidth: 240,\n maxWidth: 320,\n padding: 20,\n borderRadius: 16,\n backgroundColor: '#1B1B21',\n alignItems: 'center',\n gap: 10,\n },\n stage: { color: '#F7F7FA', fontSize: 14, textAlign: 'center' },\n meta: { color: '#A1A1AA', fontSize: 12, textAlign: 'center' },\n notice: { color: '#FBBF24', fontSize: 12, textAlign: 'center' },\n error: { color: '#F87171', fontSize: 15, fontWeight: '700' },\n bar: { alignSelf: 'stretch', height: 4, borderRadius: 2, backgroundColor: '#2A2A33', overflow: 'hidden' },\n barFill: { height: 4, backgroundColor: '#8B5CF6' },\n button: { marginTop: 4, paddingHorizontal: 14, paddingVertical: 8, borderRadius: 10, backgroundColor: '#2A2A33' },\n buttonLabel: { color: '#F7F7FA', fontSize: 13, fontWeight: '600' },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ExportTaskCard.js","sources":["../../../../src/features/canvas/videoEditor/ExportTaskCard.tsx"],"sourcesContent":["/**\n * The editor's export progress card for a durable export task: step, the\n * connector's projected time left, its time-limit notice, compile warnings,\n * and a \"keep in background\" exit (the render carries on in More → Tasks).\n */\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { ActivityIndicator, StyleSheet, Text, View } from 'react-native';\nimport { getCanvasTask, subscribeCanvasTasks, type CanvasTask } from '../canvasTasks';\nimport { friendlyMediaError } from './mediaActions';\nimport { renderProgressPct, renderTimeLeft } from './renderTimeline';\nimport { useCanvasTheme, themedStyles, type CanvasPalette } from '../canvasTheme';\nimport { Pressable, RADIUS, SPACE, TYPE, pressedStyle } from '../canvasUi';\n\n/** Live view of one canvas task (re-renders on every store change + a 15s clock for the time left). */\nexport function useCanvasTask(id: string | null): CanvasTask | undefined {\n const [task, setTask] = useState<CanvasTask | undefined>(() => (id ? getCanvasTask(id) : undefined));\n const [, setTick] = useState(0);\n useEffect(() => {\n if (!id) {\n setTask(undefined);\n return undefined;\n }\n setTask(getCanvasTask(id));\n const unsub = subscribeCanvasTasks(() => setTask(getCanvasTask(id)));\n const clock = setInterval(() => setTick((n) => n + 1), 15_000);\n return () => {\n unsub();\n clearInterval(clock);\n };\n }, [id]);\n return task;\n}\n\n/** Card copy for a task, pure (tested). */\nexport function exportCardLines(\n task: CanvasTask,\n now = Date.now(),\n): { stage: string; timeLeft?: string; pct?: number } {\n const stage = task.lastLine || 'Rendering…';\n const projected = task.render?.projectedMs;\n if (task.state !== 'running' || !task.startedAt || task.local) return { stage };\n const elapsed = Math.max(0, now - task.startedAt);\n return {\n stage,\n ...(projected ? { timeLeft: renderTimeLeft(projected, elapsed) } : {}),\n pct: Math.round(renderProgressPct(task.step, projected, elapsed)),\n };\n}\n\nexport function ExportTaskCard({\n task,\n onDismiss,\n onBackground,\n}: {\n task: CanvasTask | undefined;\n onDismiss: () => void;\n /** Leave the render running and get back to the canvas. */\n onBackground: () => void;\n}) {\n const theme = useCanvasTheme();\n const styles = useMemo(() => makeStyles(theme), [theme]);\n if (!task) return null;\n if (task.state === 'failed') {\n return (\n <View style={styles.card} testID=\"export-task-card\">\n <Text style={styles.error}>Export failed</Text>\n <Text style={styles.stage} numberOfLines={5}>\n {friendlyMediaError(new Error(task.error || 'The render failed'), 'video export')}\n </Text>\n <Pressable\n onPress={onDismiss}\n style={({ pressed }) => [styles.button, pressedStyle(pressed)]}\n accessibilityRole=\"button\"\n >\n <Text style={styles.buttonLabel}>Dismiss</Text>\n </Pressable>\n </View>\n );\n }\n const lines = exportCardLines(task);\n return (\n <View style={styles.card} testID=\"export-task-card\">\n <ActivityIndicator color={theme.edInk} />\n <Text style={styles.stage} numberOfLines={2}>\n {lines.stage}\n </Text>\n {lines.pct !== undefined ? (\n <View style={styles.bar}>\n <View style={[styles.barFill, { width: `${lines.pct}%` }]} />\n </View>\n ) : null}\n {lines.timeLeft ? <Text style={styles.meta}>{lines.timeLeft}</Text> : null}\n {task.notice ? <Text style={styles.notice}>{task.notice}</Text> : null}\n {task.warnings?.length ? (\n <Text style={styles.meta} numberOfLines={3}>\n {task.warnings[0]}\n </Text>\n ) : null}\n {task.state === 'running' && !task.local ? (\n <Pressable\n onPress={onBackground}\n style={({ pressed }) => [styles.button, pressedStyle(pressed)]}\n accessibilityRole=\"button\"\n >\n <Text style={styles.buttonLabel}>Keep rendering in background</Text>\n </Pressable>\n ) : null}\n </View>\n );\n}\n\nconst makeStyles = themedStyles((theme: CanvasPalette) =>\n StyleSheet.create({\n card: {\n minWidth: 240,\n maxWidth: 320,\n padding: SPACE.xl,\n borderRadius: RADIUS.xl,\n backgroundColor: theme.edPanel,\n alignItems: 'center',\n gap: SPACE.md,\n },\n stage: { ...TYPE.label, fontWeight: '500', fontSize: 14, color: theme.edInk, textAlign: 'center' },\n meta: { ...TYPE.caption, color: theme.edInk2, textAlign: 'center' },\n notice: { ...TYPE.caption, color: theme.edWarn, textAlign: 'center' },\n error: { ...TYPE.title, color: theme.edDanger },\n bar: {\n alignSelf: 'stretch',\n height: 6,\n borderRadius: RADIUS.pill,\n backgroundColor: theme.edRaisedHi,\n overflow: 'hidden',\n },\n barFill: { height: 6, borderRadius: RADIUS.pill, backgroundColor: theme.edAccent },\n button: {\n marginTop: SPACE.xs,\n minHeight: 40,\n justifyContent: 'center',\n paddingHorizontal: SPACE.lg,\n borderRadius: RADIUS.pill,\n backgroundColor: theme.edRaised,\n },\n buttonLabel: { ...TYPE.label, color: theme.edInk },\n }),\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {jsxs,jsx}from'react/jsx-runtime';import {useRef,useState}from'react';import {
|
|
1
|
+
import {jsxs,jsx}from'react/jsx-runtime';import {useMemo,useRef,useState}from'react';import {View,Text,ScrollView,TextInput,ActivityIndicator,StyleSheet}from'react-native';import {deriveAgentEndpoint}from'../remoteMediaClient.js';import {reflowSceneChildren}from'../sceneLayers.js';import {runCutAgentTurn}from'./agentLoop.js';import {linksIn,intakeLinks,fetchLinkViaAgent}from'./attachments.js';import {useCanvasTheme,themedStyles}from'../../canvasTheme.js';import {Pressable,pressedStyle,RADIUS,SPACE,TYPE}from'../../canvasUi.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +16,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
16
|
}
|
|
15
17
|
return a;
|
|
16
18
|
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
17
20
|
function AgentCutPane({
|
|
18
21
|
timeline,
|
|
19
22
|
setTimeline,
|
|
@@ -24,6 +27,8 @@ function AgentCutPane({
|
|
|
24
27
|
onAddMedia,
|
|
25
28
|
onFilm
|
|
26
29
|
}) {
|
|
30
|
+
const theme = useCanvasTheme();
|
|
31
|
+
const styles = useMemo(() => makeStyles(theme), [theme]);
|
|
27
32
|
const timelineRef = useRef(timeline);
|
|
28
33
|
timelineRef.current = timeline;
|
|
29
34
|
const [prompt, setPrompt] = useState("Keep the strongest 3 clips and put the hero shot first");
|
|
@@ -94,65 +99,65 @@ function AgentCutPane({
|
|
|
94
99
|
return /* @__PURE__ */ jsxs(View, { style: styles.root, children: [
|
|
95
100
|
/* @__PURE__ */ jsx(Text, { style: styles.title, children: "AI cut" }),
|
|
96
101
|
/* @__PURE__ */ jsx(Text, { style: styles.fine, children: "Describe the cut. The agent can inspect, trim, reorder and remove clips, add scenes to film and titles, and take in pasted links to pictures or videos." }),
|
|
97
|
-
/* @__PURE__ */ jsx(ScrollView, { style: styles.log, contentContainerStyle: {
|
|
98
|
-
paddingBottom: 8
|
|
99
|
-
}, children: log.map((line, i) => /* @__PURE__ */ jsx(Text, { style: styles.logLine, children: line }, `${i}-${line.slice(0, 12)}`)) }),
|
|
102
|
+
/* @__PURE__ */ jsx(ScrollView, { style: styles.log, contentContainerStyle: styles.logInner, children: log.map((line, i) => /* @__PURE__ */ jsx(Text, { style: styles.logLine, children: line }, `${i}-${line.slice(0, 12)}`)) }),
|
|
100
103
|
status ? /* @__PURE__ */ jsx(Text, { style: styles.status, children: status }) : null,
|
|
101
|
-
/* @__PURE__ */ jsx(TextInput, { value: prompt, onChangeText: setPrompt, style: styles.input, multiline: true, placeholderTextColor:
|
|
102
|
-
/* @__PURE__ */ jsx(Pressable, { onPress: () => void run(), disabled: busy, style:
|
|
104
|
+
/* @__PURE__ */ jsx(TextInput, { value: prompt, onChangeText: setPrompt, style: styles.input, multiline: true, placeholderTextColor: theme.edInk3, placeholder: "e.g. Drop the last clip and tighten the open" }),
|
|
105
|
+
/* @__PURE__ */ jsx(Pressable, { onPress: () => void run(), disabled: busy, style: ({
|
|
106
|
+
pressed
|
|
107
|
+
}) => [styles.cta, busy && styles.ctaOff, pressedStyle(pressed)], children: busy ? /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.edOnInk }) : /* @__PURE__ */ jsx(Text, { style: styles.ctaLabel, children: "Run cut" }) })
|
|
103
108
|
] });
|
|
104
109
|
}
|
|
105
|
-
const
|
|
110
|
+
const makeStyles = themedStyles((theme) => StyleSheet.create({
|
|
106
111
|
root: {
|
|
107
|
-
padding:
|
|
108
|
-
gap:
|
|
109
|
-
},
|
|
110
|
-
title: {
|
|
111
|
-
fontSize: 14,
|
|
112
|
-
fontWeight: "700",
|
|
113
|
-
color: "#0f172a"
|
|
114
|
-
},
|
|
115
|
-
fine: {
|
|
116
|
-
fontSize: 12,
|
|
117
|
-
color: "#64748b",
|
|
118
|
-
lineHeight: 16
|
|
112
|
+
padding: SPACE.lg,
|
|
113
|
+
gap: SPACE.sm
|
|
119
114
|
},
|
|
115
|
+
title: __spreadProps(__spreadValues({}, TYPE.title), {
|
|
116
|
+
color: theme.edInk
|
|
117
|
+
}),
|
|
118
|
+
fine: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
119
|
+
fontWeight: "400",
|
|
120
|
+
color: theme.edInk3
|
|
121
|
+
}),
|
|
120
122
|
log: {
|
|
121
123
|
maxHeight: 140,
|
|
122
|
-
backgroundColor:
|
|
123
|
-
borderRadius:
|
|
124
|
-
padding:
|
|
124
|
+
backgroundColor: theme.edRaised,
|
|
125
|
+
borderRadius: RADIUS.md,
|
|
126
|
+
padding: SPACE.md
|
|
125
127
|
},
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
color: "#334155",
|
|
129
|
-
marginBottom: 4
|
|
130
|
-
},
|
|
131
|
-
status: {
|
|
132
|
-
fontSize: 12,
|
|
133
|
-
color: "#7c3aed"
|
|
128
|
+
logInner: {
|
|
129
|
+
paddingBottom: SPACE.sm
|
|
134
130
|
},
|
|
131
|
+
logLine: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
132
|
+
fontWeight: "400",
|
|
133
|
+
color: theme.edInk2,
|
|
134
|
+
marginBottom: SPACE.xs
|
|
135
|
+
}),
|
|
136
|
+
status: __spreadProps(__spreadValues({}, TYPE.caption), {
|
|
137
|
+
color: theme.edAccent
|
|
138
|
+
}),
|
|
135
139
|
input: {
|
|
136
|
-
minHeight:
|
|
137
|
-
borderRadius:
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
color:
|
|
140
|
+
minHeight: 72,
|
|
141
|
+
borderRadius: RADIUS.md,
|
|
142
|
+
backgroundColor: theme.edRaised,
|
|
143
|
+
paddingHorizontal: SPACE.md,
|
|
144
|
+
paddingVertical: 10,
|
|
145
|
+
fontSize: 14,
|
|
146
|
+
color: theme.edInk,
|
|
143
147
|
textAlignVertical: "top"
|
|
144
148
|
},
|
|
145
149
|
cta: {
|
|
146
150
|
alignItems: "center",
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
justifyContent: "center",
|
|
152
|
+
minHeight: 44,
|
|
153
|
+
borderRadius: RADIUS.pill,
|
|
154
|
+
backgroundColor: theme.edAccent
|
|
150
155
|
},
|
|
151
156
|
ctaOff: {
|
|
152
157
|
opacity: 0.5
|
|
153
158
|
},
|
|
154
|
-
ctaLabel: {
|
|
155
|
-
|
|
156
|
-
color:
|
|
157
|
-
}
|
|
158
|
-
});export{AgentCutPane};//# sourceMappingURL=AgentCutPane.js.map
|
|
159
|
+
ctaLabel: __spreadProps(__spreadValues({}, TYPE.label), {
|
|
160
|
+
fontSize: 14,
|
|
161
|
+
color: theme.edOnInk
|
|
162
|
+
})
|
|
163
|
+
}));export{AgentCutPane};//# sourceMappingURL=AgentCutPane.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentCutPane.js","sources":["../../../../../src/features/canvas/videoEditor/agent/AgentCutPane.tsx"],"sourcesContent":["/**\n * Agentic cut pane inside the video editor — describe the cut, tools rearrange clips.\n */\nimport React, { useRef, useState } from 'react';\nimport { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';\nimport type { EditorTimeline } from '../editorModel';\nimport type { RunMediaAction } from '../mediaActions';\nimport { deriveAgentEndpoint } from '../remoteMediaClient';\nimport { reflowSceneChildren } from '../sceneLayers';\nimport { runCutAgentTurn } from './agentLoop';\nimport { fetchLinkViaAgent, intakeLinks, linksIn, type AgentAttachment, type LinkMediaKind } from './attachments';\n\nexport function AgentCutPane({\n timeline,\n setTimeline,\n token,\n indexUrl,\n runAction,\n uploadMedia,\n onAddMedia,\n onFilm,\n}: {\n timeline: EditorTimeline;\n setTimeline: (next: EditorTimeline | ((prev: EditorTimeline) => EditorTimeline)) => void;\n token?: string | null;\n indexUrl?: string | null;\n /** Pasted links are fetched through the storage connector with this runner. */\n runAction?: RunMediaAction;\n /** Stores a fetched link's bytes (data: URL) and returns the hosted URL. */\n uploadMedia?: (localUri: string) => Promise<string>;\n /** Put a taken-in link into the editor library; returns its id. */\n onAddMedia?: (asset: { type: LinkMediaKind; src: string; name: string }) => string;\n /** film_scenes: film these colour scenes in the background. */\n onFilm?: (sceneIds: string[]) => void;\n}) {\n const timelineRef = useRef(timeline);\n timelineRef.current = timeline;\n const [prompt, setPrompt] = useState('Keep the strongest 3 clips and put the hero shot first');\n const [busy, setBusy] = useState(false);\n const [status, setStatus] = useState<string | null>(null);\n const [log, setLog] = useState<string[]>([]);\n const [history, setHistory] = useState<Array<{ role: 'user' | 'assistant'; content: string }>>([]);\n\n const run = async () => {\n if (!token || !indexUrl) {\n setLog((l) => [...l, 'Sign in needed for AI cut.']);\n return;\n }\n const text = prompt.trim();\n if (!text || busy) return;\n setBusy(true);\n setStatus('Starting…');\n setHistory((h) => [...h, { role: 'user', content: text }]);\n try {\n // Pasted links become library media the model is told about (pictures it sees).\n let attachments: AgentAttachment[] = [];\n const links = linksIn(text);\n if (links.length && runAction && uploadMedia && onAddMedia) {\n setStatus(`Taking in ${links.length} link${links.length === 1 ? '' : 's'}…`);\n attachments = await intakeLinks(links, {\n fetchUrl: (url, accept) => fetchLinkViaAgent(runAction, url, accept),\n upload: (dataUrl) => uploadMedia(dataUrl),\n addAsset: (asset) => onAddMedia(asset),\n });\n for (const a of attachments) {\n setLog((l) => [\n ...l,\n a.kind === 'unusable' ? `Could not take in ${a.name}: ${a.reason}` : `Took in ${a.name}`,\n ]);\n }\n }\n const result = await runCutAgentTurn({\n history,\n userText: text,\n attachments,\n token,\n agentEndpoint: deriveAgentEndpoint(indexUrl),\n onStatus: setStatus,\n ctx: {\n getTimeline: () => timelineRef.current,\n // Scene-scoped layers move with their scenes on agent edits too.\n setTimeline: (next) => {\n const reflowed = reflowSceneChildren(timelineRef.current, next);\n timelineRef.current = reflowed;\n setTimeline(reflowed);\n },\n ...(onFilm ? { film: onFilm } : {}),\n },\n });\n for (const step of result.steps) setLog((l) => [...l, step.label]);\n setLog((l) => [...l, result.text]);\n setHistory((h) => [...h, { role: 'assistant', content: result.text }]);\n setPrompt('');\n } catch (err: unknown) {\n setLog((l) => [...l, err instanceof Error ? err.message : String(err)]);\n } finally {\n setBusy(false);\n setStatus(null);\n }\n };\n\n return (\n <View style={styles.root}>\n <Text style={styles.title}>AI cut</Text>\n <Text style={styles.fine}>\n Describe the cut. The agent can inspect, trim, reorder and remove clips, add scenes to film and titles,\n and take in pasted links to pictures or videos.\n </Text>\n <ScrollView style={styles.log} contentContainerStyle={{ paddingBottom: 8 }}>\n {log.map((line, i) => (\n <Text key={`${i}-${line.slice(0, 12)}`} style={styles.logLine}>\n {line}\n </Text>\n ))}\n </ScrollView>\n {status ? <Text style={styles.status}>{status}</Text> : null}\n <TextInput\n value={prompt}\n onChangeText={setPrompt}\n style={styles.input}\n multiline\n placeholderTextColor=\"#94a3b8\"\n placeholder=\"e.g. Drop the last clip and tighten the open\"\n />\n <Pressable onPress={() => void run()} disabled={busy} style={[styles.cta, busy && styles.ctaOff]}>\n {busy ? <ActivityIndicator color=\"#0f172a\" /> : <Text style={styles.ctaLabel}>Run cut</Text>}\n </Pressable>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n root: { padding: 12, gap: 8 },\n title: { fontSize: 14, fontWeight: '700', color: '#0f172a' },\n fine: { fontSize: 12, color: '#64748b', lineHeight: 16 },\n log: { maxHeight: 140, backgroundColor: '#f8fafc', borderRadius: 10, padding: 8 },\n logLine: { fontSize: 12, color: '#334155', marginBottom: 4 },\n status: { fontSize: 12, color: '#7c3aed' },\n input: {\n minHeight: 64,\n borderRadius: 10,\n borderWidth: 1,\n borderColor: '#e2e8f0',\n paddingHorizontal: 10,\n paddingVertical: 8,\n color: '#0f172a',\n textAlignVertical: 'top',\n },\n cta: {\n alignItems: 'center',\n paddingVertical: 11,\n borderRadius: 10,\n backgroundColor: '#e2e8f0',\n },\n ctaOff: { opacity: 0.5 },\n ctaLabel: { fontWeight: '700', color: '#0f172a' },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgentCutPane.js","sources":["../../../../../src/features/canvas/videoEditor/agent/AgentCutPane.tsx"],"sourcesContent":["/**\n * Agentic cut pane inside the video editor: describe the cut, tools rearrange clips.\n */\nimport React, { useMemo, useRef, useState } from 'react';\nimport { ActivityIndicator, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';\nimport type { EditorTimeline } from '../editorModel';\nimport type { RunMediaAction } from '../mediaActions';\nimport { deriveAgentEndpoint } from '../remoteMediaClient';\nimport { reflowSceneChildren } from '../sceneLayers';\nimport { runCutAgentTurn } from './agentLoop';\nimport { fetchLinkViaAgent, intakeLinks, linksIn, type AgentAttachment, type LinkMediaKind } from './attachments';\nimport { useCanvasTheme, themedStyles, type CanvasPalette } from '../../canvasTheme';\nimport { Pressable, RADIUS, SPACE, TYPE, pressedStyle } from '../../canvasUi';\n\nexport function AgentCutPane({\n timeline,\n setTimeline,\n token,\n indexUrl,\n runAction,\n uploadMedia,\n onAddMedia,\n onFilm,\n}: {\n timeline: EditorTimeline;\n setTimeline: (next: EditorTimeline | ((prev: EditorTimeline) => EditorTimeline)) => void;\n token?: string | null;\n indexUrl?: string | null;\n /** Pasted links are fetched through the storage connector with this runner. */\n runAction?: RunMediaAction;\n /** Stores a fetched link's bytes (data: URL) and returns the hosted URL. */\n uploadMedia?: (localUri: string) => Promise<string>;\n /** Put a taken-in link into the editor library; returns its id. */\n onAddMedia?: (asset: { type: LinkMediaKind; src: string; name: string }) => string;\n /** film_scenes: film these colour scenes in the background. */\n onFilm?: (sceneIds: string[]) => void;\n}) {\n const theme = useCanvasTheme();\n const styles = useMemo(() => makeStyles(theme), [theme]);\n const timelineRef = useRef(timeline);\n timelineRef.current = timeline;\n const [prompt, setPrompt] = useState('Keep the strongest 3 clips and put the hero shot first');\n const [busy, setBusy] = useState(false);\n const [status, setStatus] = useState<string | null>(null);\n const [log, setLog] = useState<string[]>([]);\n const [history, setHistory] = useState<Array<{ role: 'user' | 'assistant'; content: string }>>([]);\n\n const run = async () => {\n if (!token || !indexUrl) {\n setLog((l) => [...l, 'Sign in needed for AI cut.']);\n return;\n }\n const text = prompt.trim();\n if (!text || busy) return;\n setBusy(true);\n setStatus('Starting…');\n setHistory((h) => [...h, { role: 'user', content: text }]);\n try {\n // Pasted links become library media the model is told about (pictures it sees).\n let attachments: AgentAttachment[] = [];\n const links = linksIn(text);\n if (links.length && runAction && uploadMedia && onAddMedia) {\n setStatus(`Taking in ${links.length} link${links.length === 1 ? '' : 's'}…`);\n attachments = await intakeLinks(links, {\n fetchUrl: (url, accept) => fetchLinkViaAgent(runAction, url, accept),\n upload: (dataUrl) => uploadMedia(dataUrl),\n addAsset: (asset) => onAddMedia(asset),\n });\n for (const a of attachments) {\n setLog((l) => [\n ...l,\n a.kind === 'unusable' ? `Could not take in ${a.name}: ${a.reason}` : `Took in ${a.name}`,\n ]);\n }\n }\n const result = await runCutAgentTurn({\n history,\n userText: text,\n attachments,\n token,\n agentEndpoint: deriveAgentEndpoint(indexUrl),\n onStatus: setStatus,\n ctx: {\n getTimeline: () => timelineRef.current,\n // Scene-scoped layers move with their scenes on agent edits too.\n setTimeline: (next) => {\n const reflowed = reflowSceneChildren(timelineRef.current, next);\n timelineRef.current = reflowed;\n setTimeline(reflowed);\n },\n ...(onFilm ? { film: onFilm } : {}),\n },\n });\n for (const step of result.steps) setLog((l) => [...l, step.label]);\n setLog((l) => [...l, result.text]);\n setHistory((h) => [...h, { role: 'assistant', content: result.text }]);\n setPrompt('');\n } catch (err: unknown) {\n setLog((l) => [...l, err instanceof Error ? err.message : String(err)]);\n } finally {\n setBusy(false);\n setStatus(null);\n }\n };\n\n return (\n <View style={styles.root}>\n <Text style={styles.title}>AI cut</Text>\n <Text style={styles.fine}>\n Describe the cut. The agent can inspect, trim, reorder and remove clips, add scenes to film and titles,\n and take in pasted links to pictures or videos.\n </Text>\n <ScrollView style={styles.log} contentContainerStyle={styles.logInner}>\n {log.map((line, i) => (\n <Text key={`${i}-${line.slice(0, 12)}`} style={styles.logLine}>\n {line}\n </Text>\n ))}\n </ScrollView>\n {status ? <Text style={styles.status}>{status}</Text> : null}\n <TextInput\n value={prompt}\n onChangeText={setPrompt}\n style={styles.input}\n multiline\n placeholderTextColor={theme.edInk3}\n placeholder=\"e.g. Drop the last clip and tighten the open\"\n />\n <Pressable\n onPress={() => void run()}\n disabled={busy}\n style={({ pressed }) => [styles.cta, busy && styles.ctaOff, pressedStyle(pressed)]}\n >\n {busy ? <ActivityIndicator color={theme.edOnInk} /> : <Text style={styles.ctaLabel}>Run cut</Text>}\n </Pressable>\n </View>\n );\n}\n\nconst makeStyles = themedStyles((theme: CanvasPalette) =>\n StyleSheet.create({\n root: { padding: SPACE.lg, gap: SPACE.sm },\n title: { ...TYPE.title, color: theme.edInk },\n fine: { ...TYPE.caption, fontWeight: '400', color: theme.edInk3 },\n log: { maxHeight: 140, backgroundColor: theme.edRaised, borderRadius: RADIUS.md, padding: SPACE.md },\n logInner: { paddingBottom: SPACE.sm },\n logLine: { ...TYPE.caption, fontWeight: '400', color: theme.edInk2, marginBottom: SPACE.xs },\n status: { ...TYPE.caption, color: theme.edAccent },\n input: {\n minHeight: 72,\n borderRadius: RADIUS.md,\n backgroundColor: theme.edRaised,\n paddingHorizontal: SPACE.md,\n paddingVertical: 10,\n fontSize: 14,\n color: theme.edInk,\n textAlignVertical: 'top',\n },\n cta: {\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 44,\n borderRadius: RADIUS.pill,\n backgroundColor: theme.edAccent,\n },\n ctaOff: { opacity: 0.5 },\n ctaLabel: { ...TYPE.label, fontSize: 14, color: theme.edOnInk },\n }),\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {hydrateCanvasTasks,addCanvasTask,patchCanvasTask,getCanvasTask,listCanvasTasks,isTerminal}from'../canvasTasks.js';import {ensureFetchableMediaUrl}from'../mediaUrls.js';import {prepareRenderTimeline}from'./exportPipeline.js';import {renderExportSpec}from'./exportRenderer.js';import {submitRenderTimeline,renderDeadline,RENDER_POLL_EVERY_MS,pollRenderTimeline,MAX_POLL_ERRORS}from'./renderTimeline.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {registerTaskResumer,hydrateCanvasTasks,addCanvasTask,patchCanvasTask,getCanvasTask,listCanvasTasks,isTerminal}from'../canvasTasks.js';import {ensureFetchableMediaUrl}from'../mediaUrls.js';import {prepareRenderTimeline}from'./exportPipeline.js';import {renderExportSpec}from'./exportRenderer.js';import {submitRenderTimeline,renderDeadline,RENDER_POLL_EVERY_MS,pollRenderTimeline,MAX_POLL_ERRORS}from'./renderTimeline.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -213,4 +213,5 @@ function resumeExportTasks(run) {
|
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
-
}
|
|
216
|
+
}
|
|
217
|
+
registerTaskResumer(resumeExportTasks);export{resumeExportTasks,startExportTask};//# sourceMappingURL=exportTask.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exportTask.js","sources":["../../../../src/features/canvas/videoEditor/exportTask.ts"],"sourcesContent":["/**\n * Durable video-editor export - native twin of web tasks/exportTask.ts.\n *\n * The editor's spec is prepared + compiled (exportPipeline), handed to the\n * connector's detached render (RENDER_TIMELINE_SUBMIT), and polled from\n * module scope as a canvasTasks entry of kind 'export' - so the editor can\n * close, the board can change and a relaunch picks the render back up from\n * the stored handle (canvasTasks.resumePromoTasks -> resumeExportTasks).\n *\n * When SUBMIT is rejected or unavailable (an older connector), the in-app\n * client chain (exportRenderer.renderExportSpec) renders it instead - not\n * durable, but it still exports.\n */\nimport {\n addCanvasTask,\n getCanvasTask,\n hydrateCanvasTasks,\n isTerminal,\n listCanvasTasks,\n patchCanvasTask,\n type CanvasTask,\n} from '../canvasTasks';\nimport type { PromoRunResult } from '../promoVideo';\nimport { ensureFetchableMediaUrl } from '../mediaUrls';\nimport type { VideoExportSpec } from './editorModel';\nimport { prepareRenderTimeline } from './exportPipeline';\nimport { renderExportSpec } from './exportRenderer';\nimport type { RunMediaAction } from './mediaActions';\nimport {\n MAX_POLL_ERRORS,\n RENDER_POLL_EVERY_MS,\n pollRenderTimeline,\n renderDeadline,\n submitRenderTimeline,\n type RenderHandle,\n type RenderPoll,\n} from './renderTimeline';\n\nexport interface ExportTaskDeps {\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n /** The client-chain fallback, replaceable in tests. */\n renderLocally: typeof renderExportSpec;\n}\n\nconst defaultDeps: ExportTaskDeps = {\n sleep: (ms) => new Promise((r) => setTimeout(r, ms)),\n now: () => Date.now(),\n renderLocally: renderExportSpec,\n};\nlet deps = defaultDeps;\n\n/** Test seam: fake clock/sleep/fallback; null restores the defaults. */\nexport function configureExportTaskDeps(next: Partial<ExportTaskDeps> | null): void {\n deps = next ? { ...defaultDeps, ...next } : defaultDeps;\n pollers.clear();\n working.clear();\n}\n\nexport interface StartExportTaskInput {\n spec: VideoExportSpec;\n boardId: string;\n /** The project's title - what the card shows. */\n brief: string;\n /** Host uploader for phone-local clips. */\n upload?: (localUri: string) => Promise<string>;\n}\n\n/** Renders this process is following (never doubled up by a resume). */\nconst pollers = new Map<string, Promise<void>>();\n/** Exports this process is still preparing/submitting or rendering locally. */\nconst working = new Set<string>();\n\nlet seq = 0;\nconst newId = () => `export-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\nconst stepLine = (poll: RenderPoll): string =>\n poll.step ? `Step ${poll.step.index} of ${poll.step.total} · ${poll.step.label}` : poll.label || 'Rendering…';\n\nconst errorText = (err: unknown, fallback: string): string =>\n (err instanceof Error ? err.message : typeof err === 'string' ? err : '') || fallback;\n\nconst settle = (id: string, patch: Partial<CanvasTask>) => patchCanvasTask(id, { ...patch, endedAt: deps.now() });\n\nfunction exportResult(url: string, task: CanvasTask | undefined): PromoRunResult {\n return {\n url,\n title: task?.brief || 'Video export',\n projectId: task?.render?.runId ?? task?.id ?? '',\n preset: 'export',\n pipeline: task?.local ? 'client-chain' : 'render-timeline',\n };\n}\n\n/**\n * Register an export task and start it. Resolves with the task id as soon as\n * it is registered; preparation, the SUBMIT and the poll carry on by\n * themselves (watch it with subscribeCanvasTasks / getCanvasTask).\n */\nexport async function startExportTask(run: RunMediaAction, input: StartExportTaskInput): Promise<string> {\n await hydrateCanvasTasks();\n const id = newId();\n addCanvasTask({\n id,\n kind: 'export',\n title: 'Video export',\n brief: input.brief,\n boardId: input.boardId,\n state: 'submitting',\n createdAt: deps.now(),\n request: { prompt: input.brief, preset: 'export', durationSeconds: 0, aspectRatio: '' },\n lastLine: 'Starting the render…',\n });\n working.add(id);\n void runExport(run, id, input).finally(() => working.delete(id));\n return id;\n}\n\nasync function runExport(run: RunMediaAction, id: string, input: StartExportTaskInput): Promise<void> {\n const line = (lastLine: string) => {\n if (getCanvasTask(id)?.state === 'submitting') patchCanvasTask(id, { lastLine });\n };\n let handle: RenderHandle;\n try {\n const compiled = await prepareRenderTimeline(input.spec, run, {\n upload: input.upload,\n refresh: (url) => ensureFetchableMediaUrl(run, url),\n onProgress: line,\n });\n if (compiled.warnings.length) patchCanvasTask(id, { warnings: compiled.warnings });\n // One untouched clip compiles to no steps: that clip is the export.\n if (compiled.steps.length === 0 && compiled.finalRef.kind === 'url') {\n settle(id, {\n state: 'succeeded',\n result: exportResult(compiled.finalRef.url, getCanvasTask(id)),\n lastLine: 'Ready',\n });\n return;\n }\n line('Starting the render…');\n try {\n handle = await submitRenderTimeline(run, compiled);\n } catch (err) {\n if (!getCanvasTask(id)) return;\n await renderLocally(run, id, input, err);\n return;\n }\n } catch (err) {\n settle(id, { state: 'failed', error: errorText(err, 'Could not start the render'), lastLine: 'Failed' });\n return;\n }\n if (!getCanvasTask(id)) return; // dismissed during the submit\n patchCanvasTask(id, {\n state: 'running',\n render: handle,\n startedAt: deps.now(),\n lastLine: 'Rendering…',\n ...(handle.notice ? { notice: handle.notice } : {}),\n });\n follow(run, id);\n}\n\n/** SUBMIT unavailable: the pre-durable client chain, in-process. */\nasync function renderLocally(run: RunMediaAction, id: string, input: StartExportTaskInput, why: unknown) {\n patchCanvasTask(id, {\n state: 'running',\n local: true,\n startedAt: deps.now(),\n lastLine: 'Rendering on this device…',\n });\n try {\n const url = await deps.renderLocally(input.spec, run, input.upload, (p) =>\n patchCanvasTask(id, { lastLine: p.stage }),\n );\n settle(id, { state: 'succeeded', result: exportResult(url, getCanvasTask(id)), lastLine: 'Ready' });\n } catch (err) {\n const submitError = errorText(why, '');\n settle(id, {\n state: 'failed',\n error: errorText(err, 'The render failed') + (submitError ? ` (render service: ${submitError})` : ''),\n lastLine: 'Failed',\n });\n }\n}\n\nfunction follow(run: RunMediaAction, id: string) {\n if (pollers.has(id)) return;\n const job = poll(run, id).finally(() => pollers.delete(id));\n pollers.set(id, job);\n}\n\n/** Keep polling one running render until it settles. The deadline is the RUN's: a relaunch never extends it. */\nasync function poll(run: RunMediaAction, id: string): Promise<void> {\n const start = getCanvasTask(id);\n if (!start?.render || start.state !== 'running') return;\n const handle = start.render;\n const deadlineAt = renderDeadline(start.startedAt ?? start.createdAt, handle);\n let errors = 0;\n while (deps.now() < deadlineAt) {\n await deps.sleep(RENDER_POLL_EVERY_MS);\n const current = getCanvasTask(id);\n if (current?.state !== 'running') return; // settled elsewhere or dismissed\n let answer: RenderPoll;\n try {\n answer = await pollRenderTimeline(run, handle);\n errors = 0;\n } catch (err) {\n if (++errors < MAX_POLL_ERRORS) continue;\n settle(id, { state: 'failed', error: errorText(err, 'Lost track of the render'), lastLine: 'Failed' });\n return;\n }\n if (answer.state === 'running') {\n patchCanvasTask(id, { ...(answer.step ? { step: answer.step } : {}), lastLine: stepLine(answer) });\n continue;\n }\n if (answer.state === 'failed') {\n settle(id, { state: 'failed', error: answer.error || 'The render failed', lastLine: 'Failed' });\n return;\n }\n settle(id, {\n state: 'succeeded',\n result: exportResult(answer.url || handle.outputUrl, current),\n lastLine: 'Ready',\n });\n return;\n }\n settle(id, {\n state: 'failed',\n error: 'The render is taking longer than expected - check back shortly.',\n lastLine: 'Timed out',\n });\n}\n\n/**\n * Pick up every export this app started and has not settled (call on app\n * open; canvasTasks.resumePromoTasks does). One caught mid-submit, or\n * rendering through the in-app chain, by an app close lost its work - it\n * fails with a reason instead of spinning forever.\n */\nexport function resumeExportTasks(run: RunMediaAction): void {\n for (const task of listCanvasTasks()) {\n if (task.kind !== 'export' || isTerminal(task.state) || pollers.has(task.id) || working.has(task.id)) continue;\n if (task.state === 'running' && task.render && !task.local) {\n follow(run, task.id);\n } else {\n settle(task.id, {\n state: 'failed',\n error: 'The app closed before the render finished starting - export again.',\n lastLine: 'Interrupted',\n });\n }\n }\n}\n\n/** Whether this process is following / working on an export right now. */\nexport const isExportActive = (id: string): boolean => pollers.has(id) || working.has(id);\n"],"names":["poll"],"mappings":";;;;;;;;;;;;;;;;;;;AA2BA,MAAM,WAA8B,GAAA;AAAA,EAClC,KAAA,EAAO,QAAM,IAAI,OAAA,CAAQ,OAAK,UAAW,CAAA,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,EAC/C,GAAA,EAAK,MAAM,IAAA,CAAK,GAAI,EAAA;AAAA,EACpB,aAAe,EAAA;AACjB,CAAA;AACA,IAAI,IAAO,GAAA,WAAA;AAqBX,MAAM,OAAA,uBAAc,GAA2B,EAAA;AAE/C,MAAM,OAAA,uBAAc,GAAY,EAAA;AAChC,IAAI,GAAM,GAAA,CAAA;AACV,MAAM,KAAQ,GAAA,MAAM,CAAU,OAAA,EAAA,IAAA,CAAK,GAAI,EAAA,CAAE,QAAS,CAAA,EAAE,CAAC,CAAA,CAAA,EAAA,CAAK,GAAO,EAAA,EAAA,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA;AAC7E,MAAM,WAAW,CAACA,KAAAA,KAA6BA,MAAK,IAAO,GAAA,CAAA,KAAA,EAAQA,MAAK,IAAK,CAAA,KAAK,OAAOA,KAAK,CAAA,IAAA,CAAK,KAAK,CAAMA,MAAAA,EAAAA,KAAAA,CAAK,KAAK,KAAK,CAAA,CAAA,GAAKA,MAAK,KAAS,IAAA,iBAAA;AAChJ,MAAM,SAAY,GAAA,CAAC,GAAc,EAAA,QAAA,KAAA,CAA8B,GAAe,YAAA,KAAA,GAAQ,GAAI,CAAA,OAAA,GAAU,OAAO,GAAA,KAAQ,QAAW,GAAA,GAAA,GAAM,EAAO,KAAA,QAAA;AAC3I,MAAM,SAAS,CAAC,EAAA,EAAY,UAA+B,eAAgB,CAAA,EAAA,EAAI,iCAC1E,KAD0E,CAAA,EAAA;AAAA,EAE7E,OAAA,EAAS,KAAK,GAAI;AACpB,CAAC,CAAA,CAAA;AACD,SAAS,YAAA,CAAa,KAAa,IAA8C,EAAA;AAhEjF,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AAiEE,EAAO,OAAA;AAAA,IACL,GAAA;AAAA,IACA,KAAA,EAAA,CAAO,6BAAM,KAAS,KAAA,cAAA;AAAA,IACtB,SAAA,EAAA,CAAW,8CAAM,MAAN,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAc,UAAd,IAAuB,GAAA,EAAA,GAAA,IAAA,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAM,OAA7B,IAAmC,GAAA,EAAA,GAAA,EAAA;AAAA,IAC9C,MAAQ,EAAA,QAAA;AAAA,IACR,QAAA,EAAA,CAAU,IAAM,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,KAAA,IAAQ,cAAiB,GAAA;AAAA,GAC3C;AACF;AAOsB,eAAA,eAAA,CAAgB,KAAqB,KAA8C,EAAA;AACvG,EAAA,MAAM,kBAAmB,EAAA;AACzB,EAAA,MAAM,KAAK,KAAM,EAAA;AACjB,EAAc,aAAA,CAAA;AAAA,IACZ,EAAA;AAAA,IACA,IAAM,EAAA,QAAA;AAAA,IACN,KAAO,EAAA,cAAA;AAAA,IACP,OAAO,KAAM,CAAA,KAAA;AAAA,IACb,SAAS,KAAM,CAAA,OAAA;AAAA,IACf,KAAO,EAAA,YAAA;AAAA,IACP,SAAA,EAAW,KAAK,GAAI,EAAA;AAAA,IACpB,OAAS,EAAA;AAAA,MACP,QAAQ,KAAM,CAAA,KAAA;AAAA,MACd,MAAQ,EAAA,QAAA;AAAA,MACR,eAAiB,EAAA,CAAA;AAAA,MACjB,WAAa,EAAA;AAAA,KACf;AAAA,IACA,QAAU,EAAA;AAAA,GACX,CAAA;AACD,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,EAAK,KAAA,SAAA,CAAU,GAAK,EAAA,EAAA,EAAI,KAAK,CAAA,CAAE,QAAQ,MAAM,OAAA,CAAQ,MAAO,CAAA,EAAE,CAAC,CAAA;AAC/D,EAAO,OAAA,EAAA;AACT;AACA,eAAe,SAAA,CAAU,GAAqB,EAAA,EAAA,EAAY,KAA4C,EAAA;AACpG,EAAM,MAAA,IAAA,GAAO,CAAC,QAAqB,KAAA;AAvGrC,IAAA,IAAA,EAAA;AAwGI,IAAA,IAAA,CAAA,CAAI,mBAAc,EAAE,CAAA,KAAhB,mBAAmB,KAAU,MAAA,YAAA,kBAA8B,EAAI,EAAA;AAAA,MACjE;AAAA,KACD,CAAA;AAAA,GACH;AACA,EAAI,IAAA,MAAA;AACJ,EAAI,IAAA;AACF,IAAA,MAAM,QAAW,GAAA,MAAM,qBAAsB,CAAA,KAAA,CAAM,MAAM,GAAK,EAAA;AAAA,MAC5D,QAAQ,KAAM,CAAA,MAAA;AAAA,MACd,OAAS,EAAA,CAAA,GAAA,KAAO,uBAAwB,CAAA,GAAA,EAAK,GAAG,CAAA;AAAA,MAChD,UAAY,EAAA;AAAA,KACb,CAAA;AACD,IAAA,IAAI,QAAS,CAAA,QAAA,CAAS,MAAQ,EAAA,eAAA,CAAgB,EAAI,EAAA;AAAA,MAChD,UAAU,QAAS,CAAA;AAAA,KACpB,CAAA;AAED,IAAA,IAAI,SAAS,KAAM,CAAA,MAAA,KAAW,KAAK,QAAS,CAAA,QAAA,CAAS,SAAS,KAAO,EAAA;AACnE,MAAA,MAAA,CAAO,EAAI,EAAA;AAAA,QACT,KAAO,EAAA,WAAA;AAAA,QACP,QAAQ,YAAa,CAAA,QAAA,CAAS,SAAS,GAAK,EAAA,aAAA,CAAc,EAAE,CAAC,CAAA;AAAA,QAC7D,QAAU,EAAA;AAAA,OACX,CAAA;AACD,MAAA;AAAA;AAEF,IAAA,IAAA,CAAK,2BAAsB,CAAA;AAC3B,IAAI,IAAA;AACF,MAAS,MAAA,GAAA,MAAM,oBAAqB,CAAA,GAAA,EAAK,QAAQ,CAAA;AAAA,aAC1C,GAAK,EAAA;AACZ,MAAI,IAAA,CAAC,aAAc,CAAA,EAAE,CAAG,EAAA;AACxB,MAAA,MAAM,aAAc,CAAA,GAAA,EAAK,EAAI,EAAA,KAAA,EAAO,GAAG,CAAA;AACvC,MAAA;AAAA;AACF,WACO,GAAK,EAAA;AACZ,IAAA,MAAA,CAAO,EAAI,EAAA;AAAA,MACT,KAAO,EAAA,QAAA;AAAA,MACP,KAAA,EAAO,SAAU,CAAA,GAAA,EAAK,4BAA4B,CAAA;AAAA,MAClD,QAAU,EAAA;AAAA,KACX,CAAA;AACD,IAAA;AAAA;AAEF,EAAI,IAAA,CAAC,aAAc,CAAA,EAAE,CAAG,EAAA;AACxB,EAAA,eAAA,CAAgB,EAAI,EAAA,cAAA,CAAA;AAAA,IAClB,KAAO,EAAA,SAAA;AAAA,IACP,MAAQ,EAAA,MAAA;AAAA,IACR,SAAA,EAAW,KAAK,GAAI,EAAA;AAAA,IACpB,QAAU,EAAA;AAAA,GAAA,EACN,OAAO,MAAS,GAAA;AAAA,IAClB,QAAQ,MAAO,CAAA;AAAA,GACjB,GAAI,EACL,CAAA,CAAA;AACD,EAAA,MAAA,CAAO,KAAK,EAAE,CAAA;AAChB;AAGA,eAAe,aAAc,CAAA,GAAA,EAAqB,EAAY,EAAA,KAAA,EAA6B,GAAc,EAAA;AACvG,EAAA,eAAA,CAAgB,EAAI,EAAA;AAAA,IAClB,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA,IAAA;AAAA,IACP,SAAA,EAAW,KAAK,GAAI,EAAA;AAAA,IACpB,QAAU,EAAA;AAAA,GACX,CAAA;AACD,EAAI,IAAA;AACF,IAAM,MAAA,GAAA,GAAM,MAAM,IAAA,CAAK,aAAc,CAAA,KAAA,CAAM,IAAM,EAAA,GAAA,EAAK,KAAM,CAAA,MAAA,EAAQ,CAAK,CAAA,KAAA,eAAA,CAAgB,EAAI,EAAA;AAAA,MAC3F,UAAU,CAAE,CAAA;AAAA,KACb,CAAC,CAAA;AACF,IAAA,MAAA,CAAO,EAAI,EAAA;AAAA,MACT,KAAO,EAAA,WAAA;AAAA,MACP,MAAQ,EAAA,YAAA,CAAa,GAAK,EAAA,aAAA,CAAc,EAAE,CAAC,CAAA;AAAA,MAC3C,QAAU,EAAA;AAAA,KACX,CAAA;AAAA,WACM,GAAK,EAAA;AACZ,IAAM,MAAA,WAAA,GAAc,SAAU,CAAA,GAAA,EAAK,EAAE,CAAA;AACrC,IAAA,MAAA,CAAO,EAAI,EAAA;AAAA,MACT,KAAO,EAAA,QAAA;AAAA,MACP,KAAA,EAAO,UAAU,GAAK,EAAA,mBAAmB,KAAK,WAAc,GAAA,CAAA,kBAAA,EAAqB,WAAW,CAAM,CAAA,CAAA,GAAA,EAAA,CAAA;AAAA,MAClG,QAAU,EAAA;AAAA,KACX,CAAA;AAAA;AAEL;AACA,SAAS,MAAA,CAAO,KAAqB,EAAY,EAAA;AAC/C,EAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,EAAE,CAAG,EAAA;AACrB,EAAM,MAAA,GAAA,GAAM,IAAK,CAAA,GAAA,EAAK,EAAE,CAAA,CAAE,QAAQ,MAAM,OAAA,CAAQ,MAAO,CAAA,EAAE,CAAC,CAAA;AAC1D,EAAQ,OAAA,CAAA,GAAA,CAAI,IAAI,GAAG,CAAA;AACrB;AAGA,eAAe,IAAA,CAAK,KAAqB,EAA2B,EAAA;AA7LpE,EAAA,IAAA,EAAA;AA8LE,EAAM,MAAA,KAAA,GAAQ,cAAc,EAAE,CAAA;AAC9B,EAAA,IAAI,EAAC,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,MAAU,CAAA,IAAA,KAAA,CAAM,UAAU,SAAW,EAAA;AACjD,EAAA,MAAM,SAAS,KAAM,CAAA,MAAA;AACrB,EAAA,MAAM,aAAa,cAAe,CAAA,CAAA,EAAA,GAAA,KAAA,CAAM,cAAN,IAAmB,GAAA,EAAA,GAAA,KAAA,CAAM,WAAW,MAAM,CAAA;AAC5E,EAAA,IAAI,MAAS,GAAA,CAAA;AACb,EAAO,OAAA,IAAA,CAAK,GAAI,EAAA,GAAI,UAAY,EAAA;AAC9B,IAAM,MAAA,IAAA,CAAK,MAAM,oBAAoB,CAAA;AACrC,IAAM,MAAA,OAAA,GAAU,cAAc,EAAE,CAAA;AAChC,IAAI,IAAA,CAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,WAAU,SAAW,EAAA;AAClC,IAAI,IAAA,MAAA;AACJ,IAAI,IAAA;AACF,MAAS,MAAA,GAAA,MAAM,kBAAmB,CAAA,GAAA,EAAK,MAAM,CAAA;AAC7C,MAAS,MAAA,GAAA,CAAA;AAAA,aACF,GAAK,EAAA;AACZ,MAAI,IAAA,EAAE,SAAS,eAAiB,EAAA;AAChC,MAAA,MAAA,CAAO,EAAI,EAAA;AAAA,QACT,KAAO,EAAA,QAAA;AAAA,QACP,KAAA,EAAO,SAAU,CAAA,GAAA,EAAK,0BAA0B,CAAA;AAAA,QAChD,QAAU,EAAA;AAAA,OACX,CAAA;AACD,MAAA;AAAA;AAEF,IAAI,IAAA,MAAA,CAAO,UAAU,SAAW,EAAA;AAC9B,MAAgB,eAAA,CAAA,EAAA,EAAI,aACd,CAAA,cAAA,CAAA,EAAA,EAAA,MAAA,CAAO,IAAO,GAAA;AAAA,QAChB,MAAM,MAAO,CAAA;AAAA,OACf,GAAI,EAHc,CAAA,EAAA;AAAA,QAIlB,QAAA,EAAU,SAAS,MAAM;AAAA,OAC1B,CAAA,CAAA;AACD,MAAA;AAAA;AAEF,IAAI,IAAA,MAAA,CAAO,UAAU,QAAU,EAAA;AAC7B,MAAA,MAAA,CAAO,EAAI,EAAA;AAAA,QACT,KAAO,EAAA,QAAA;AAAA,QACP,KAAA,EAAO,OAAO,KAAS,IAAA,mBAAA;AAAA,QACvB,QAAU,EAAA;AAAA,OACX,CAAA;AACD,MAAA;AAAA;AAEF,IAAA,MAAA,CAAO,EAAI,EAAA;AAAA,MACT,KAAO,EAAA,WAAA;AAAA,MACP,QAAQ,YAAa,CAAA,MAAA,CAAO,GAAO,IAAA,MAAA,CAAO,WAAW,OAAO,CAAA;AAAA,MAC5D,QAAU,EAAA;AAAA,KACX,CAAA;AACD,IAAA;AAAA;AAEF,EAAA,MAAA,CAAO,EAAI,EAAA;AAAA,IACT,KAAO,EAAA,QAAA;AAAA,IACP,KAAO,EAAA,iEAAA;AAAA,IACP,QAAU,EAAA;AAAA,GACX,CAAA;AACH;AAQO,SAAS,kBAAkB,GAA2B,EAAA;AAC3D,EAAW,KAAA,MAAA,IAAA,IAAQ,iBAAmB,EAAA;AACpC,IAAA,IAAI,KAAK,IAAS,KAAA,QAAA,IAAY,UAAW,CAAA,IAAA,CAAK,KAAK,CAAK,IAAA,OAAA,CAAQ,GAAI,CAAA,IAAA,CAAK,EAAE,CAAK,IAAA,OAAA,CAAQ,GAAI,CAAA,IAAA,CAAK,EAAE,CAAG,EAAA;AACtG,IAAA,IAAI,KAAK,KAAU,KAAA,SAAA,IAAa,KAAK,MAAU,IAAA,CAAC,KAAK,KAAO,EAAA;AAC1D,MAAO,MAAA,CAAA,GAAA,EAAK,KAAK,EAAE,CAAA;AAAA,KACd,MAAA;AACL,MAAA,MAAA,CAAO,KAAK,EAAI,EAAA;AAAA,QACd,KAAO,EAAA,QAAA;AAAA,QACP,KAAO,EAAA,oEAAA;AAAA,QACP,QAAU,EAAA;AAAA,OACX,CAAA;AAAA;AACH;AAEJ"}
|
|
1
|
+
{"version":3,"file":"exportTask.js","sources":["../../../../src/features/canvas/videoEditor/exportTask.ts"],"sourcesContent":["/**\n * Durable video-editor export - native twin of web tasks/exportTask.ts.\n *\n * The editor's spec is prepared + compiled (exportPipeline), handed to the\n * connector's detached render (RENDER_TIMELINE_SUBMIT), and polled from\n * module scope as a canvasTasks entry of kind 'export' - so the editor can\n * close, the board can change and a relaunch picks the render back up from\n * the stored handle (canvasTasks.resumePromoTasks -> resumeExportTasks).\n *\n * When SUBMIT is rejected or unavailable (an older connector), the in-app\n * client chain (exportRenderer.renderExportSpec) renders it instead - not\n * durable, but it still exports.\n */\nimport {\n addCanvasTask,\n getCanvasTask,\n hydrateCanvasTasks,\n isTerminal,\n listCanvasTasks,\n patchCanvasTask,\n registerTaskResumer,\n type CanvasTask,\n} from '../canvasTasks';\nimport type { PromoRunResult } from '../promoVideo';\nimport { ensureFetchableMediaUrl } from '../mediaUrls';\nimport type { VideoExportSpec } from './editorModel';\nimport { prepareRenderTimeline } from './exportPipeline';\nimport { renderExportSpec } from './exportRenderer';\nimport type { RunMediaAction } from './mediaActions';\nimport {\n MAX_POLL_ERRORS,\n RENDER_POLL_EVERY_MS,\n pollRenderTimeline,\n renderDeadline,\n submitRenderTimeline,\n type RenderHandle,\n type RenderPoll,\n} from './renderTimeline';\n\nexport interface ExportTaskDeps {\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n /** The client-chain fallback, replaceable in tests. */\n renderLocally: typeof renderExportSpec;\n}\n\nconst defaultDeps: ExportTaskDeps = {\n sleep: (ms) => new Promise((r) => setTimeout(r, ms)),\n now: () => Date.now(),\n renderLocally: renderExportSpec,\n};\nlet deps = defaultDeps;\n\n/** Test seam: fake clock/sleep/fallback; null restores the defaults. */\nexport function configureExportTaskDeps(next: Partial<ExportTaskDeps> | null): void {\n deps = next ? { ...defaultDeps, ...next } : defaultDeps;\n pollers.clear();\n working.clear();\n}\n\nexport interface StartExportTaskInput {\n spec: VideoExportSpec;\n boardId: string;\n /** The project's title - what the card shows. */\n brief: string;\n /** Host uploader for phone-local clips. */\n upload?: (localUri: string) => Promise<string>;\n}\n\n/** Renders this process is following (never doubled up by a resume). */\nconst pollers = new Map<string, Promise<void>>();\n/** Exports this process is still preparing/submitting or rendering locally. */\nconst working = new Set<string>();\n\nlet seq = 0;\nconst newId = () => `export-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\nconst stepLine = (poll: RenderPoll): string =>\n poll.step ? `Step ${poll.step.index} of ${poll.step.total} · ${poll.step.label}` : poll.label || 'Rendering…';\n\nconst errorText = (err: unknown, fallback: string): string =>\n (err instanceof Error ? err.message : typeof err === 'string' ? err : '') || fallback;\n\nconst settle = (id: string, patch: Partial<CanvasTask>) => patchCanvasTask(id, { ...patch, endedAt: deps.now() });\n\nfunction exportResult(url: string, task: CanvasTask | undefined): PromoRunResult {\n return {\n url,\n title: task?.brief || 'Video export',\n projectId: task?.render?.runId ?? task?.id ?? '',\n preset: 'export',\n pipeline: task?.local ? 'client-chain' : 'render-timeline',\n };\n}\n\n/**\n * Register an export task and start it. Resolves with the task id as soon as\n * it is registered; preparation, the SUBMIT and the poll carry on by\n * themselves (watch it with subscribeCanvasTasks / getCanvasTask).\n */\nexport async function startExportTask(run: RunMediaAction, input: StartExportTaskInput): Promise<string> {\n await hydrateCanvasTasks();\n const id = newId();\n addCanvasTask({\n id,\n kind: 'export',\n title: 'Video export',\n brief: input.brief,\n boardId: input.boardId,\n state: 'submitting',\n createdAt: deps.now(),\n request: { prompt: input.brief, preset: 'export', durationSeconds: 0, aspectRatio: '' },\n lastLine: 'Starting the render…',\n });\n working.add(id);\n void runExport(run, id, input).finally(() => working.delete(id));\n return id;\n}\n\nasync function runExport(run: RunMediaAction, id: string, input: StartExportTaskInput): Promise<void> {\n const line = (lastLine: string) => {\n if (getCanvasTask(id)?.state === 'submitting') patchCanvasTask(id, { lastLine });\n };\n let handle: RenderHandle;\n try {\n const compiled = await prepareRenderTimeline(input.spec, run, {\n upload: input.upload,\n refresh: (url) => ensureFetchableMediaUrl(run, url),\n onProgress: line,\n });\n if (compiled.warnings.length) patchCanvasTask(id, { warnings: compiled.warnings });\n // One untouched clip compiles to no steps: that clip is the export.\n if (compiled.steps.length === 0 && compiled.finalRef.kind === 'url') {\n settle(id, {\n state: 'succeeded',\n result: exportResult(compiled.finalRef.url, getCanvasTask(id)),\n lastLine: 'Ready',\n });\n return;\n }\n line('Starting the render…');\n try {\n handle = await submitRenderTimeline(run, compiled);\n } catch (err) {\n if (!getCanvasTask(id)) return;\n await renderLocally(run, id, input, err);\n return;\n }\n } catch (err) {\n settle(id, { state: 'failed', error: errorText(err, 'Could not start the render'), lastLine: 'Failed' });\n return;\n }\n if (!getCanvasTask(id)) return; // dismissed during the submit\n patchCanvasTask(id, {\n state: 'running',\n render: handle,\n startedAt: deps.now(),\n lastLine: 'Rendering…',\n ...(handle.notice ? { notice: handle.notice } : {}),\n });\n follow(run, id);\n}\n\n/** SUBMIT unavailable: the pre-durable client chain, in-process. */\nasync function renderLocally(run: RunMediaAction, id: string, input: StartExportTaskInput, why: unknown) {\n patchCanvasTask(id, {\n state: 'running',\n local: true,\n startedAt: deps.now(),\n lastLine: 'Rendering on this device…',\n });\n try {\n const url = await deps.renderLocally(input.spec, run, input.upload, (p) =>\n patchCanvasTask(id, { lastLine: p.stage }),\n );\n settle(id, { state: 'succeeded', result: exportResult(url, getCanvasTask(id)), lastLine: 'Ready' });\n } catch (err) {\n const submitError = errorText(why, '');\n settle(id, {\n state: 'failed',\n error: errorText(err, 'The render failed') + (submitError ? ` (render service: ${submitError})` : ''),\n lastLine: 'Failed',\n });\n }\n}\n\nfunction follow(run: RunMediaAction, id: string) {\n if (pollers.has(id)) return;\n const job = poll(run, id).finally(() => pollers.delete(id));\n pollers.set(id, job);\n}\n\n/** Keep polling one running render until it settles. The deadline is the RUN's: a relaunch never extends it. */\nasync function poll(run: RunMediaAction, id: string): Promise<void> {\n const start = getCanvasTask(id);\n if (!start?.render || start.state !== 'running') return;\n const handle = start.render;\n const deadlineAt = renderDeadline(start.startedAt ?? start.createdAt, handle);\n let errors = 0;\n while (deps.now() < deadlineAt) {\n await deps.sleep(RENDER_POLL_EVERY_MS);\n const current = getCanvasTask(id);\n if (current?.state !== 'running') return; // settled elsewhere or dismissed\n let answer: RenderPoll;\n try {\n answer = await pollRenderTimeline(run, handle);\n errors = 0;\n } catch (err) {\n if (++errors < MAX_POLL_ERRORS) continue;\n settle(id, { state: 'failed', error: errorText(err, 'Lost track of the render'), lastLine: 'Failed' });\n return;\n }\n if (answer.state === 'running') {\n patchCanvasTask(id, { ...(answer.step ? { step: answer.step } : {}), lastLine: stepLine(answer) });\n continue;\n }\n if (answer.state === 'failed') {\n settle(id, { state: 'failed', error: answer.error || 'The render failed', lastLine: 'Failed' });\n return;\n }\n settle(id, {\n state: 'succeeded',\n result: exportResult(answer.url || handle.outputUrl, current),\n lastLine: 'Ready',\n });\n return;\n }\n settle(id, {\n state: 'failed',\n error: 'The render is taking longer than expected - check back shortly.',\n lastLine: 'Timed out',\n });\n}\n\n/**\n * Pick up every export this app started and has not settled (call on app\n * open; canvasTasks.resumePromoTasks does). One caught mid-submit, or\n * rendering through the in-app chain, by an app close lost its work - it\n * fails with a reason instead of spinning forever.\n */\nexport function resumeExportTasks(run: RunMediaAction): void {\n for (const task of listCanvasTasks()) {\n if (task.kind !== 'export' || isTerminal(task.state) || pollers.has(task.id) || working.has(task.id)) continue;\n if (task.state === 'running' && task.render && !task.local) {\n follow(run, task.id);\n } else {\n settle(task.id, {\n state: 'failed',\n error: 'The app closed before the render finished starting - export again.',\n lastLine: 'Interrupted',\n });\n }\n }\n}\n\n// Resumed with the promo tasks on app start (registered, not imported, to keep canvasTasks cycle-free).\nregisterTaskResumer(resumeExportTasks);\n\n/** Whether this process is following / working on an export right now. */\nexport const isExportActive = (id: string): boolean => pollers.has(id) || working.has(id);\n"],"names":["poll"],"mappings":"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"}
|