@adminide-stack/yantra-mobile 12.0.128 → 12.0.129-alpha.1

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.
Files changed (360) hide show
  1. package/lib/compute.js +57 -1
  2. package/lib/compute.js.map +1 -1
  3. package/lib/features/agent-chat/NativeAgentChat.js +3 -2
  4. package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
  5. package/lib/features/apps/AppsCatalog.js +10 -0
  6. package/lib/features/apps/AppsCatalog.js.map +1 -1
  7. package/lib/features/apps/mobileAppCatalog.js +11 -0
  8. package/lib/features/apps/mobileAppCatalog.js.map +1 -1
  9. package/lib/features/canvas/AudioEditorExperience.js +448 -105
  10. package/lib/features/canvas/AudioEditorExperience.js.map +1 -1
  11. package/lib/features/canvas/CanvasAgentChatPane.js +33 -14
  12. package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
  13. package/lib/features/canvas/CanvasBoardsGrid.js +493 -41
  14. package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
  15. package/lib/features/canvas/CanvasChatResultCard.js.map +1 -1
  16. package/lib/features/canvas/CanvasEditToolsPanel.js +37 -1
  17. package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
  18. package/lib/features/canvas/CanvasExperience.js +237 -22
  19. package/lib/features/canvas/CanvasExperience.js.map +1 -1
  20. package/lib/features/canvas/CanvasGeneratePanel.js +119 -26
  21. package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
  22. package/lib/features/canvas/CanvasLooksPanel.js +17 -6
  23. package/lib/features/canvas/CanvasLooksPanel.js.map +1 -1
  24. package/lib/features/canvas/CanvasTasksPanel.js +18 -1
  25. package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
  26. package/lib/features/canvas/DesignCategoryGallery.js +423 -0
  27. package/lib/features/canvas/DesignCategoryGallery.js.map +1 -0
  28. package/lib/features/canvas/ImageEditorExperience.js +763 -187
  29. package/lib/features/canvas/ImageEditorExperience.js.map +1 -1
  30. package/lib/features/canvas/SetStudioExperience.js +199 -11
  31. package/lib/features/canvas/SetStudioExperience.js.map +1 -1
  32. package/lib/features/canvas/VideoEditorExperience.js +59 -40
  33. package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
  34. package/lib/features/canvas/VideoGeneratorExperience.js +134 -34
  35. package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
  36. package/lib/features/canvas/aiEdit.js +4 -2
  37. package/lib/features/canvas/aiEdit.js.map +1 -1
  38. package/lib/features/canvas/audioEditor/AudioWaveform.js +96 -0
  39. package/lib/features/canvas/audioEditor/AudioWaveform.js.map +1 -0
  40. package/lib/features/canvas/audioEditor/audioPeaks.js +93 -0
  41. package/lib/features/canvas/audioEditor/audioPeaks.js.map +1 -0
  42. package/lib/features/canvas/canvasTaskSync.js +34 -7
  43. package/lib/features/canvas/canvasTaskSync.js.map +1 -1
  44. package/lib/features/canvas/canvasTasks.js +23 -3
  45. package/lib/features/canvas/canvasTasks.js.map +1 -1
  46. package/lib/features/canvas/canvasTheme.js +10 -24
  47. package/lib/features/canvas/canvasTheme.js.map +1 -1
  48. package/lib/features/canvas/canvasUi.js +1 -1
  49. package/lib/features/canvas/canvasUi.js.map +1 -1
  50. package/lib/features/canvas/createTiles.js +17 -9
  51. package/lib/features/canvas/createTiles.js.map +1 -1
  52. package/lib/features/canvas/deepLinks.js +35 -5
  53. package/lib/features/canvas/deepLinks.js.map +1 -1
  54. package/lib/features/canvas/designCatalog.js +165 -0
  55. package/lib/features/canvas/designCatalog.js.map +1 -0
  56. package/lib/features/canvas/designCategories.js +262 -0
  57. package/lib/features/canvas/designCategories.js.map +1 -0
  58. package/lib/features/canvas/editorControls.js +406 -0
  59. package/lib/features/canvas/editorControls.js.map +1 -0
  60. package/lib/features/canvas/generationModels.js +5 -3
  61. package/lib/features/canvas/generationModels.js.map +1 -1
  62. package/lib/features/canvas/generationTasks.js +162 -0
  63. package/lib/features/canvas/generationTasks.js.map +1 -0
  64. package/lib/features/canvas/generator/BottomSheet.js +167 -0
  65. package/lib/features/canvas/generator/BottomSheet.js.map +1 -0
  66. package/lib/features/canvas/generator/BusinessCardChatCard.js +155 -0
  67. package/lib/features/canvas/generator/BusinessCardChatCard.js.map +1 -0
  68. package/lib/features/canvas/generator/DirectorSheet.js +163 -0
  69. package/lib/features/canvas/generator/DirectorSheet.js.map +1 -0
  70. package/lib/features/canvas/generator/ReframePreview.js +122 -0
  71. package/lib/features/canvas/generator/ReframePreview.js.map +1 -0
  72. package/lib/features/canvas/generator/RunLogCard.js +119 -0
  73. package/lib/features/canvas/generator/RunLogCard.js.map +1 -0
  74. package/lib/features/canvas/generator/ShotPanel.js +261 -0
  75. package/lib/features/canvas/generator/ShotPanel.js.map +1 -0
  76. package/lib/features/canvas/generator/businessCardWidget.js +117 -0
  77. package/lib/features/canvas/generator/businessCardWidget.js.map +1 -0
  78. package/lib/features/canvas/generator/cameraVocabulary.js +142 -0
  79. package/lib/features/canvas/generator/cameraVocabulary.js.map +1 -0
  80. package/lib/features/canvas/generator/cinematicVocabulary.js +416 -0
  81. package/lib/features/canvas/generator/cinematicVocabulary.js.map +1 -0
  82. package/lib/features/canvas/generator/direction.js +41 -0
  83. package/lib/features/canvas/generator/direction.js.map +1 -0
  84. package/lib/features/canvas/generator/reframeGeometry.js +108 -0
  85. package/lib/features/canvas/generator/reframeGeometry.js.map +1 -0
  86. package/lib/features/canvas/generator/runLog.js +71 -0
  87. package/lib/features/canvas/generator/runLog.js.map +1 -0
  88. package/lib/features/canvas/generator/shot.js +133 -0
  89. package/lib/features/canvas/generator/shot.js.map +1 -0
  90. package/lib/features/canvas/generator/useShotSpec.js +87 -0
  91. package/lib/features/canvas/generator/useShotSpec.js.map +1 -0
  92. package/lib/features/canvas/home/HeroComposer.js +214 -0
  93. package/lib/features/canvas/home/HeroComposer.js.map +1 -0
  94. package/lib/features/canvas/home/HeroMonitor.js +225 -0
  95. package/lib/features/canvas/home/HeroMonitor.js.map +1 -0
  96. package/lib/features/canvas/home/LookDetail.js +185 -0
  97. package/lib/features/canvas/home/LookDetail.js.map +1 -0
  98. package/lib/features/canvas/home/LoopingVideo.js +37 -0
  99. package/lib/features/canvas/home/LoopingVideo.js.map +1 -0
  100. package/lib/features/canvas/home/TemplatesGallery.js +253 -0
  101. package/lib/features/canvas/home/TemplatesGallery.js.map +1 -0
  102. package/lib/features/canvas/home/heroShots.js +100 -0
  103. package/lib/features/canvas/home/heroShots.js.map +1 -0
  104. package/lib/features/canvas/homeWork.js +62 -3
  105. package/lib/features/canvas/homeWork.js.map +1 -1
  106. package/lib/features/canvas/imageEditor/ImageMarkup.js +195 -0
  107. package/lib/features/canvas/imageEditor/ImageMarkup.js.map +1 -0
  108. package/lib/features/canvas/imageEditor/imageEditOps.js +367 -0
  109. package/lib/features/canvas/imageEditor/imageEditOps.js.map +1 -0
  110. package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
  111. package/lib/features/canvas/rankedCatalogSearch.js +375 -0
  112. package/lib/features/canvas/rankedCatalogSearch.js.map +1 -0
  113. package/lib/features/canvas/recorder/CameraRecorderExperience.js +68 -20
  114. package/lib/features/canvas/recorder/CameraRecorderExperience.js.map +1 -1
  115. package/lib/features/canvas/recorder/RecordingReview.js +272 -0
  116. package/lib/features/canvas/recorder/RecordingReview.js.map +1 -0
  117. package/lib/features/canvas/recorder/RecordingsList.js +179 -0
  118. package/lib/features/canvas/recorder/RecordingsList.js.map +1 -0
  119. package/lib/features/canvas/recorder/recorderOps.js +99 -0
  120. package/lib/features/canvas/recorder/recorderOps.js.map +1 -0
  121. package/lib/features/canvas/seedanceShowcase.js +314 -0
  122. package/lib/features/canvas/seedanceShowcase.js.map +1 -0
  123. package/lib/features/canvas/serverTasks.js +149 -15
  124. package/lib/features/canvas/serverTasks.js.map +1 -1
  125. package/lib/features/canvas/sessionRenewal.js +114 -0
  126. package/lib/features/canvas/sessionRenewal.js.map +1 -0
  127. package/lib/features/canvas/set/SetViewportWebView.js +34 -1
  128. package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
  129. package/lib/features/canvas/set/agent/setTurn.js +4 -2
  130. package/lib/features/canvas/set/agent/setTurn.js.map +1 -1
  131. package/lib/features/canvas/set/setPresets.js +85 -0
  132. package/lib/features/canvas/set/setPresets.js.map +1 -0
  133. package/lib/features/canvas/set/setProject.js +4 -1
  134. package/lib/features/canvas/set/setProject.js.map +1 -1
  135. package/lib/features/canvas/studioCatalog.js +59 -4
  136. package/lib/features/canvas/studioCatalog.js.map +1 -1
  137. package/lib/features/canvas/studioLooks.js +31 -4
  138. package/lib/features/canvas/studioLooks.js.map +1 -1
  139. package/lib/features/canvas/surfaceIndex.js +1 -14
  140. package/lib/features/canvas/surfaceIndex.js.map +1 -1
  141. package/lib/features/canvas/templateSearch.js +489 -0
  142. package/lib/features/canvas/templateSearch.js.map +1 -0
  143. package/lib/features/canvas/useCanvasSession.js +28 -6
  144. package/lib/features/canvas/useCanvasSession.js.map +1 -1
  145. package/lib/features/canvas/useStudioCatalogTemplates.js +41 -5
  146. package/lib/features/canvas/useStudioCatalogTemplates.js.map +1 -1
  147. package/lib/features/canvas/videoEditor/EditorPanels.js +531 -0
  148. package/lib/features/canvas/videoEditor/EditorPanels.js.map +1 -0
  149. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +48 -4
  150. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
  151. package/lib/features/canvas/videoEditor/agent/agentLoop.js +2 -0
  152. package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
  153. package/lib/features/canvas/videoEditor/agent/brainClient.js +97 -27
  154. package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
  155. package/lib/features/canvas/videoEditor/agent/cutTools.js +707 -3
  156. package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
  157. package/lib/features/canvas/videoEditor/audioServices.js +165 -0
  158. package/lib/features/canvas/videoEditor/audioServices.js.map +1 -0
  159. package/lib/features/canvas/videoEditor/captions.js +144 -0
  160. package/lib/features/canvas/videoEditor/captions.js.map +1 -0
  161. package/lib/features/canvas/videoEditor/compileTimeline.js +24 -16
  162. package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -1
  163. package/lib/features/canvas/videoEditor/editorModel.js +12 -2
  164. package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
  165. package/lib/features/canvas/videoEditor/exportTask.js +89 -7
  166. package/lib/features/canvas/videoEditor/exportTask.js.map +1 -1
  167. package/lib/features/canvas/videoEditor/layers.js +117 -0
  168. package/lib/features/canvas/videoEditor/layers.js.map +1 -0
  169. package/lib/features/canvas/videoEditor/remoteMediaClient.js +45 -18
  170. package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
  171. package/lib/features/canvas/videoEditor/renderTimeline.js +18 -6
  172. package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -1
  173. package/lib/features/canvas/videoEditor/revoice.js +138 -0
  174. package/lib/features/canvas/videoEditor/revoice.js.map +1 -0
  175. package/lib/features/canvas/videoEditor/storageUpload.js +34 -0
  176. package/lib/features/canvas/videoEditor/storageUpload.js.map +1 -0
  177. package/lib/features/canvas/videoEditor/textMotion.js +109 -0
  178. package/lib/features/canvas/videoEditor/textMotion.js.map +1 -0
  179. package/lib/features/canvas/videoEditor/transitions.js +31 -0
  180. package/lib/features/canvas/videoEditor/transitions.js.map +1 -0
  181. package/lib/features/chat/TemplatesChatCards.js +8 -3
  182. package/lib/features/chat/TemplatesChatCards.js.map +1 -1
  183. package/lib/features/design/DesignEditorExperience.js +674 -644
  184. package/lib/features/design/DesignEditorExperience.js.map +1 -1
  185. package/lib/features/design/DesignExperience.js +285 -538
  186. package/lib/features/design/DesignExperience.js.map +1 -1
  187. package/lib/features/design/designCore.js +2 -212
  188. package/lib/features/design/designCore.js.map +1 -1
  189. package/lib/features/design/designIndex.js +1 -50
  190. package/lib/features/design/designIndex.js.map +1 -1
  191. package/lib/features/design/doc/aiDesign.js +247 -0
  192. package/lib/features/design/doc/aiDesign.js.map +1 -0
  193. package/lib/features/design/doc/artifacts.js +280 -0
  194. package/lib/features/design/doc/artifacts.js.map +1 -0
  195. package/lib/features/design/doc/chart.js +98 -0
  196. package/lib/features/design/doc/chart.js.map +1 -0
  197. package/lib/features/design/doc/crop.js +104 -0
  198. package/lib/features/design/doc/crop.js.map +1 -0
  199. package/lib/features/design/doc/curve.js +49 -0
  200. package/lib/features/design/doc/curve.js.map +1 -0
  201. package/lib/features/design/doc/docOps.js +397 -0
  202. package/lib/features/design/doc/docOps.js.map +1 -0
  203. package/lib/features/design/doc/findReplace.js +112 -0
  204. package/lib/features/design/doc/findReplace.js.map +1 -0
  205. package/lib/features/design/doc/fonts.js +79 -0
  206. package/lib/features/design/doc/fonts.js.map +1 -0
  207. package/lib/features/design/doc/frames.js +17 -0
  208. package/lib/features/design/doc/frames.js.map +1 -0
  209. package/lib/features/design/doc/geometry.js +133 -0
  210. package/lib/features/design/doc/geometry.js.map +1 -0
  211. package/lib/features/design/doc/imageAdjust.js +203 -0
  212. package/lib/features/design/doc/imageAdjust.js.map +1 -0
  213. package/lib/features/design/doc/legacyDoc.js +107 -0
  214. package/lib/features/design/doc/legacyDoc.js.map +1 -0
  215. package/lib/features/design/doc/newDoc.js +335 -0
  216. package/lib/features/design/doc/newDoc.js.map +1 -0
  217. package/lib/features/design/doc/pageRange.js +17 -0
  218. package/lib/features/design/doc/pageRange.js.map +1 -0
  219. package/lib/features/design/doc/pathScale.js +68 -0
  220. package/lib/features/design/doc/pathScale.js.map +1 -0
  221. package/lib/features/design/doc/qr.js +62 -0
  222. package/lib/features/design/doc/qr.js.map +1 -0
  223. package/lib/features/design/doc/shapes.js +366 -0
  224. package/lib/features/design/doc/shapes.js.map +1 -0
  225. package/lib/features/design/doc/sizes.js +230 -0
  226. package/lib/features/design/doc/sizes.js.map +1 -0
  227. package/lib/features/design/doc/textEffects.js +134 -0
  228. package/lib/features/design/doc/textEffects.js.map +1 -0
  229. package/lib/features/design/doc/textLayout.js +182 -0
  230. package/lib/features/design/doc/textLayout.js.map +1 -0
  231. package/lib/features/design/doc/types.js +30 -0
  232. package/lib/features/design/doc/types.js.map +1 -0
  233. package/lib/features/design/editor/AiPanel.js +194 -0
  234. package/lib/features/design/editor/AiPanel.js.map +1 -0
  235. package/lib/features/design/editor/ChartDataPanel.js +182 -0
  236. package/lib/features/design/editor/ChartDataPanel.js.map +1 -0
  237. package/lib/features/design/editor/CropOverlay.js +199 -0
  238. package/lib/features/design/editor/CropOverlay.js.map +1 -0
  239. package/lib/features/design/editor/DesignCanvas.js +363 -0
  240. package/lib/features/design/editor/DesignCanvas.js.map +1 -0
  241. package/lib/features/design/editor/ExportSheet.js +123 -0
  242. package/lib/features/design/editor/ExportSheet.js.map +1 -0
  243. package/lib/features/design/editor/FindReplacePanel.js +93 -0
  244. package/lib/features/design/editor/FindReplacePanel.js.map +1 -0
  245. package/lib/features/design/editor/ImageTools.js +188 -0
  246. package/lib/features/design/editor/ImageTools.js.map +1 -0
  247. package/lib/features/design/editor/LayerTools.js +485 -0
  248. package/lib/features/design/editor/LayerTools.js.map +1 -0
  249. package/lib/features/design/editor/PageStrip.js +203 -0
  250. package/lib/features/design/editor/PageStrip.js.map +1 -0
  251. package/lib/features/design/editor/Slideshow.js +97 -0
  252. package/lib/features/design/editor/Slideshow.js.map +1 -0
  253. package/lib/features/design/editor/ToolPanels.js +695 -0
  254. package/lib/features/design/editor/ToolPanels.js.map +1 -0
  255. package/lib/features/design/editor/controls.js +630 -0
  256. package/lib/features/design/editor/controls.js.map +1 -0
  257. package/lib/features/design/editor/useDesignSave.js +91 -0
  258. package/lib/features/design/editor/useDesignSave.js.map +1 -0
  259. package/lib/features/design/export/exportDesign.js +170 -0
  260. package/lib/features/design/export/exportDesign.js.map +1 -0
  261. package/lib/features/design/export/pdf.js +143 -0
  262. package/lib/features/design/export/pdf.js.map +1 -0
  263. package/lib/features/design/home/DesignHome.js +688 -0
  264. package/lib/features/design/home/DesignHome.js.map +1 -0
  265. package/lib/features/design/home/studioHome.js +61 -0
  266. package/lib/features/design/home/studioHome.js.map +1 -0
  267. package/lib/features/design/pickDesignImage.js +60 -0
  268. package/lib/features/design/pickDesignImage.js.map +1 -0
  269. package/lib/features/design/render/DesignPageView.js +69 -0
  270. package/lib/features/design/render/DesignPageView.js.map +1 -0
  271. package/lib/features/design/render/PageCapture.js +288 -0
  272. package/lib/features/design/render/PageCapture.js.map +1 -0
  273. package/lib/features/design/render/TextMeasure.js +115 -0
  274. package/lib/features/design/render/TextMeasure.js.map +1 -0
  275. package/lib/features/design/render/fontRegistry.js +110 -0
  276. package/lib/features/design/render/fontRegistry.js.map +1 -0
  277. package/lib/features/design/render/layers.js +392 -0
  278. package/lib/features/design/render/layers.js.map +1 -0
  279. package/lib/features/design/render/svg.js +35 -0
  280. package/lib/features/design/render/svg.js.map +1 -0
  281. package/lib/features/design/render/svgParts.js +435 -0
  282. package/lib/features/design/render/svgParts.js.map +1 -0
  283. package/lib/features/design/surface/BoardScreen.js +529 -0
  284. package/lib/features/design/surface/BoardScreen.js.map +1 -0
  285. package/lib/features/design/surface/CompareView.js +138 -0
  286. package/lib/features/design/surface/CompareView.js.map +1 -0
  287. package/lib/features/design/surface/CreationScreen.js +294 -0
  288. package/lib/features/design/surface/CreationScreen.js.map +1 -0
  289. package/lib/features/design/surface/DesignAgentChatPane.js +444 -0
  290. package/lib/features/design/surface/DesignAgentChatPane.js.map +1 -0
  291. package/lib/features/design/surface/DesignBoards.js +441 -0
  292. package/lib/features/design/surface/DesignBoards.js.map +1 -0
  293. package/lib/features/design/surface/DesignPreview.js +159 -0
  294. package/lib/features/design/surface/DesignPreview.js.map +1 -0
  295. package/lib/features/design/surface/DesignSurfaceExperience.js +80 -0
  296. package/lib/features/design/surface/DesignSurfaceExperience.js.map +1 -0
  297. package/lib/features/design/surface/FullScreenPreview.js +59 -0
  298. package/lib/features/design/surface/FullScreenPreview.js.map +1 -0
  299. package/lib/features/design/surface/NewSystemDialog.js +122 -0
  300. package/lib/features/design/surface/NewSystemDialog.js.map +1 -0
  301. package/lib/features/design/surface/PickerSheet.js +175 -0
  302. package/lib/features/design/surface/PickerSheet.js.map +1 -0
  303. package/lib/features/design/surface/TemplatesGallery.js +156 -0
  304. package/lib/features/design/surface/TemplatesGallery.js.map +1 -0
  305. package/lib/features/design/surface/WetPaint.js +140 -0
  306. package/lib/features/design/surface/WetPaint.js.map +1 -0
  307. package/lib/features/design/surface/agentTurn.js +229 -0
  308. package/lib/features/design/surface/agentTurn.js.map +1 -0
  309. package/lib/features/design/surface/designBoard.js +218 -0
  310. package/lib/features/design/surface/designBoard.js.map +1 -0
  311. package/lib/features/design/surface/designChannel.js +186 -0
  312. package/lib/features/design/surface/designChannel.js.map +1 -0
  313. package/lib/features/design/surface/designChat.js +141 -0
  314. package/lib/features/design/surface/designChat.js.map +1 -0
  315. package/lib/features/design/surface/designConnector.js +266 -0
  316. package/lib/features/design/surface/designConnector.js.map +1 -0
  317. package/lib/features/design/surface/designDocument.js +40 -0
  318. package/lib/features/design/surface/designDocument.js.map +1 -0
  319. package/lib/features/design/surface/designExport.js +55 -0
  320. package/lib/features/design/surface/designExport.js.map +1 -0
  321. package/lib/features/design/surface/designLinks.js +64 -0
  322. package/lib/features/design/surface/designLinks.js.map +1 -0
  323. package/lib/features/design/surface/designPalette.js +24 -0
  324. package/lib/features/design/surface/designPalette.js.map +1 -0
  325. package/lib/features/design/surface/designRun.js +161 -0
  326. package/lib/features/design/surface/designRun.js.map +1 -0
  327. package/lib/features/design/surface/designTheme.js +119 -0
  328. package/lib/features/design/surface/designTheme.js.map +1 -0
  329. package/lib/features/design/surface/execStream.js +206 -0
  330. package/lib/features/design/surface/execStream.js.map +1 -0
  331. package/lib/features/design/surface/metaball.js +48 -0
  332. package/lib/features/design/surface/metaball.js.map +1 -0
  333. package/lib/features/design/surface/pickReferenceFiles.js +35 -0
  334. package/lib/features/design/surface/pickReferenceFiles.js.map +1 -0
  335. package/lib/features/design/surface/useDesignSurface.js +379 -0
  336. package/lib/features/design/surface/useDesignSurface.js.map +1 -0
  337. package/lib/features/docs/DocBlockRow.js +336 -0
  338. package/lib/features/docs/DocBlockRow.js.map +1 -0
  339. package/lib/features/docs/DocsEditorExperience.js +949 -0
  340. package/lib/features/docs/DocsEditorExperience.js.map +1 -0
  341. package/lib/features/docs/DocsToolbar.js +247 -0
  342. package/lib/features/docs/DocsToolbar.js.map +1 -0
  343. package/lib/features/docs/blocks.js +560 -0
  344. package/lib/features/docs/blocks.js.map +1 -0
  345. package/lib/features/docs/docArtifacts.js +129 -0
  346. package/lib/features/docs/docArtifacts.js.map +1 -0
  347. package/lib/features/docs/docEdits.js +201 -0
  348. package/lib/features/docs/docEdits.js.map +1 -0
  349. package/lib/features/docs/docExport.js +235 -0
  350. package/lib/features/docs/docExport.js.map +1 -0
  351. package/lib/features/docs/docShare.js +62 -0
  352. package/lib/features/docs/docShare.js.map +1 -0
  353. package/lib/features/links/openInApp.js +38 -2
  354. package/lib/features/links/openInApp.js.map +1 -1
  355. package/lib/routes.json +54 -0
  356. package/lib/screens/DesignNative/index.js +35 -0
  357. package/lib/screens/DesignNative/index.js.map +1 -0
  358. package/package.json +4 -4
  359. package/lib/features/design/exportDesign.js +0 -133
  360. package/lib/features/design/exportDesign.js.map +0 -1
@@ -0,0 +1,93 @@
1
+ import {resultUrl}from'../videoEditor/mediaActions.js';const PEAK_BUCKETS = 160;
2
+ function wavPeaks(buf, buckets = PEAK_BUCKETS) {
3
+ const view = new DataView(buf);
4
+ if (buf.byteLength < 44 || view.getUint32(0, false) !== 1380533830 || view.getUint32(8, false) !== 1463899717) return null;
5
+ let offset = 12;
6
+ let channels = 1;
7
+ let sampleRate = 0;
8
+ let bits = 16;
9
+ let formatTag = 1;
10
+ let dataStart = -1;
11
+ let dataLen = 0;
12
+ while (offset + 8 <= buf.byteLength) {
13
+ const id = view.getUint32(offset, false);
14
+ const size = view.getUint32(offset + 4, true);
15
+ const body = offset + 8;
16
+ if (id === 1718449184) {
17
+ formatTag = view.getUint16(body, true);
18
+ channels = Math.max(1, view.getUint16(body + 2, true));
19
+ sampleRate = view.getUint32(body + 4, true);
20
+ bits = view.getUint16(body + 14, true);
21
+ } else if (id === 1684108385) {
22
+ dataStart = body;
23
+ dataLen = Math.min(size, buf.byteLength - body);
24
+ break;
25
+ }
26
+ offset = body + size + size % 2;
27
+ }
28
+ if (dataStart < 0 || !sampleRate) return null;
29
+ const bytes = bits / 8;
30
+ const frame = bytes * channels;
31
+ const frames = Math.floor(dataLen / frame);
32
+ if (!frames) return null;
33
+ const read = (pos) => {
34
+ if (formatTag === 3 && bits === 32) return view.getFloat32(pos, true);
35
+ if (bits === 8) return (view.getUint8(pos) - 128) / 128;
36
+ if (bits === 16) return view.getInt16(pos, true) / 32768;
37
+ if (bits === 24) {
38
+ const v = view.getUint8(pos) | view.getUint8(pos + 1) << 8 | view.getInt8(pos + 2) << 16;
39
+ return v / 8388608;
40
+ }
41
+ return view.getInt32(pos, true) / 2147483648;
42
+ };
43
+ const per = Math.max(1, Math.floor(frames / buckets));
44
+ const stride = Math.max(1, Math.floor(per / 64));
45
+ const peaks = [];
46
+ for (let b = 0; b < buckets; b += 1) {
47
+ let max = 0;
48
+ const end = Math.min(frames, (b + 1) * per);
49
+ for (let f = b * per; f < end; f += stride) {
50
+ const v = Math.abs(read(dataStart + f * frame));
51
+ if (v > max) max = v;
52
+ }
53
+ peaks.push(Math.min(1, max));
54
+ }
55
+ const top = Math.max(0.05, ...peaks);
56
+ return {
57
+ peaks: peaks.map((p) => p / top),
58
+ durationSec: frames / sampleRate
59
+ };
60
+ }
61
+ function placeholderPeaks(seed, buckets = PEAK_BUCKETS) {
62
+ let h = 2166136261;
63
+ for (let i = 0; i < seed.length; i += 1) h = Math.imul(h ^ seed.charCodeAt(i), 16777619);
64
+ return Array.from({
65
+ length: buckets
66
+ }, (_, i) => {
67
+ h = Math.imul(h ^ h >>> 13, 1274126177) ^ i;
68
+ return 0.25 + (h >>> 0) % 1e3 / 1600;
69
+ });
70
+ }
71
+ async function fetchAudioPeaks(run, src) {
72
+ const action = "YANTRA_AUDIO_EDIT_CONVERT";
73
+ const result = await run("yantra-audio-editing", action, {
74
+ input_url: src,
75
+ format: "wav",
76
+ sample_rate: 8e3,
77
+ channels: 1
78
+ });
79
+ const res = await fetch(resultUrl(result, action));
80
+ if (!res.ok) throw new Error(`waveform fetch failed: ${res.status}`);
81
+ const parsed = wavPeaks(await res.arrayBuffer());
82
+ if (!parsed) throw new Error("waveform decode failed");
83
+ return parsed;
84
+ }
85
+ function selectionFromDrag(x0, x1, width, durationSec) {
86
+ const w = Math.max(1, width);
87
+ const a = Math.min(1, Math.max(0, x0 / w)) * durationSec;
88
+ const b = Math.min(1, Math.max(0, x1 / w)) * durationSec;
89
+ return {
90
+ start: Math.min(a, b),
91
+ end: Math.max(a, b)
92
+ };
93
+ }export{PEAK_BUCKETS,fetchAudioPeaks,placeholderPeaks,selectionFromDrag,wavPeaks};//# sourceMappingURL=audioPeaks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioPeaks.js","sources":["../../../../src/features/canvas/audioEditor/audioPeaks.ts"],"sourcesContent":["/**\n * Real waveform peaks on a phone. The web decodes with WebAudio\n * (Waveform.tsx computePeaks); the remote has no decoder, so the connector\n * renders a small mono WAV (`convert`, 8 kHz) and this reads its PCM.\n */\nimport type { RunMediaAction } from '../videoEditor/mediaActions';\nimport { resultUrl } from '../videoEditor/mediaActions';\n\nexport const PEAK_BUCKETS = 160;\n\n/** Peak per bucket (0..1) and the duration, from a RIFF/WAVE buffer (PCM 8/16/24/32-bit or float32). */\nexport function wavPeaks(buf: ArrayBuffer, buckets = PEAK_BUCKETS): { peaks: number[]; durationSec: number } | null {\n const view = new DataView(buf);\n if (buf.byteLength < 44 || view.getUint32(0, false) !== 0x52494646 || view.getUint32(8, false) !== 0x57415645)\n return null;\n let offset = 12;\n let channels = 1;\n let sampleRate = 0;\n let bits = 16;\n let formatTag = 1;\n let dataStart = -1;\n let dataLen = 0;\n while (offset + 8 <= buf.byteLength) {\n const id = view.getUint32(offset, false);\n const size = view.getUint32(offset + 4, true);\n const body = offset + 8;\n if (id === 0x666d7420) {\n formatTag = view.getUint16(body, true);\n channels = Math.max(1, view.getUint16(body + 2, true));\n sampleRate = view.getUint32(body + 4, true);\n bits = view.getUint16(body + 14, true);\n } else if (id === 0x64617461) {\n dataStart = body;\n // ffmpeg streaming a WAV writes 0xFFFFFFFF; read to the end then.\n dataLen = Math.min(size, buf.byteLength - body);\n break;\n }\n offset = body + size + (size % 2);\n }\n if (dataStart < 0 || !sampleRate) return null;\n const bytes = bits / 8;\n const frame = bytes * channels;\n const frames = Math.floor(dataLen / frame);\n if (!frames) return null;\n const read = (pos: number): number => {\n if (formatTag === 3 && bits === 32) return view.getFloat32(pos, true);\n if (bits === 8) return (view.getUint8(pos) - 128) / 128;\n if (bits === 16) return view.getInt16(pos, true) / 32768;\n if (bits === 24) {\n const v = view.getUint8(pos) | (view.getUint8(pos + 1) << 8) | (view.getInt8(pos + 2) << 16);\n return v / 8388608;\n }\n return view.getInt32(pos, true) / 2147483648;\n };\n const per = Math.max(1, Math.floor(frames / buckets));\n const stride = Math.max(1, Math.floor(per / 64));\n const peaks: number[] = [];\n for (let b = 0; b < buckets; b += 1) {\n let max = 0;\n const end = Math.min(frames, (b + 1) * per);\n for (let f = b * per; f < end; f += stride) {\n const v = Math.abs(read(dataStart + f * frame));\n if (v > max) max = v;\n }\n peaks.push(Math.min(1, max));\n }\n const top = Math.max(0.05, ...peaks);\n return { peaks: peaks.map((p) => p / top), durationSec: frames / sampleRate };\n}\n\n/** A stable stand-in shape when the track cannot be decoded (same src, same bars). */\nexport function placeholderPeaks(seed: string, buckets = PEAK_BUCKETS): number[] {\n let h = 2166136261;\n for (let i = 0; i < seed.length; i += 1) h = Math.imul(h ^ seed.charCodeAt(i), 16777619);\n return Array.from({ length: buckets }, (_, i) => {\n h = Math.imul(h ^ (h >>> 13), 1274126177) ^ i;\n return 0.25 + ((h >>> 0) % 1000) / 1600;\n });\n}\n\n/** Render a tiny mono WAV through the connector and read its peaks. */\nexport async function fetchAudioPeaks(\n run: RunMediaAction,\n src: string,\n): Promise<{ peaks: number[]; durationSec: number }> {\n const action = 'YANTRA_AUDIO_EDIT_CONVERT';\n const result = await run('yantra-audio-editing', action, {\n input_url: src,\n format: 'wav',\n sample_rate: 8000,\n channels: 1,\n });\n const res = await fetch(resultUrl(result, action));\n if (!res.ok) throw new Error(`waveform fetch failed: ${res.status}`);\n const parsed = wavPeaks(await res.arrayBuffer());\n if (!parsed) throw new Error('waveform decode failed');\n return parsed;\n}\n\n/** Pick the [start, end] (seconds) a drag across the waveform covers. */\nexport function selectionFromDrag(\n x0: number,\n x1: number,\n width: number,\n durationSec: number,\n): { start: number; end: number } {\n const w = Math.max(1, width);\n const a = Math.min(1, Math.max(0, x0 / w)) * durationSec;\n const b = Math.min(1, Math.max(0, x1 / w)) * durationSec;\n return { start: Math.min(a, b), end: Math.max(a, b) };\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {useState,useEffect}from'react';import {applyServerPatch,isTerminal,listCanvasTasks}from'./canvasTasks.js';import {taskApiTransport,listRemoteJobs,canvasTaskToJob,recordSurfaceJob,jobFingerprint,jobKey,sortJobs,CANVAS_SURFACE,promoVideoFromVerdict,serverProgressLine,updateSurfaceJob,surfaceJobPatch,isStaleJob,removeSurfaceJob,claimDelivery}from'./serverTasks.js';var __defProp = Object.defineProperty;
1
+ import {useState,useEffect}from'react';import {applyServerPatch,isTerminal,listCanvasTasks}from'./canvasTasks.js';import {taskApiTransport,listRemoteJobs,canvasTaskToJob,recordSurfaceJob,jobFingerprint,jobKey,sortJobs,CANVAS_SURFACE,promoVideoFromVerdict,agentHasJob,serverProgressLine,updateSurfaceJob,surfaceJobPatch,isStaleJob,removeSurfaceJob,claimDelivery}from'./serverTasks.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -103,14 +103,41 @@ function renderTimeLeft(projectedMs, elapsedMs) {
103
103
  return `About ${Math.max(1, Math.round(left / 6e4))} min left`;
104
104
  }
105
105
  function reconcilePatches(local, remote, now = Date.now()) {
106
- var _a, _b, _c, _d;
106
+ var _a, _b, _c, _d, _e, _f, _g, _h;
107
107
  const byId = new Map(remote.filter((j) => j.surface === CANVAS_SURFACE).map((j) => [j.id, j]));
108
108
  const out = [];
109
109
  for (const task of local) {
110
- if (task.kind !== "promo") continue;
110
+ if (task.kind !== "promo" && task.kind !== "generate") continue;
111
111
  const job = byId.get(task.id);
112
112
  if (!job) continue;
113
113
  const browserFailure = task.state === "failed" && task.verdictBy !== "agent" && !task.delivered;
114
+ if (task.kind === "generate" && job.state !== "running" && job.verdictBy === "agent" && (!isTerminal(task.state) || browserFailure)) {
115
+ const url = job.state === "succeeded" ? (_b = (_a = job.results) == null ? void 0 : _a.find((r) => r.url)) == null ? void 0 : _b.url : void 0;
116
+ out.push({
117
+ id: task.id,
118
+ patch: url ? {
119
+ state: "succeeded",
120
+ result: {
121
+ url,
122
+ title: task.brief || task.title,
123
+ projectId: "",
124
+ preset: "generate",
125
+ pipeline: ""
126
+ },
127
+ lastLine: "Ready",
128
+ error: void 0,
129
+ delivered: false,
130
+ endedAt: (_c = job.endedAt) != null ? _c : now,
131
+ verdictBy: "agent"
132
+ } : {
133
+ state: "failed",
134
+ error: job.error || "Generation failed",
135
+ endedAt: (_d = job.endedAt) != null ? _d : now,
136
+ verdictBy: "agent"
137
+ }
138
+ });
139
+ continue;
140
+ }
114
141
  if (job.state !== "running" && job.verdictBy === "agent" && (!isTerminal(task.state) || browserFailure)) {
115
142
  const video = job.state === "succeeded" ? promoVideoFromVerdict(job) : void 0;
116
143
  out.push({
@@ -120,25 +147,25 @@ function reconcilePatches(local, remote, now = Date.now()) {
120
147
  result: {
121
148
  url: video.url,
122
149
  title: video.title || "Marketing video",
123
- projectId: (_b = (_a = task.handle) == null ? void 0 : _a.projectId) != null ? _b : "",
150
+ projectId: (_f = (_e = task.handle) == null ? void 0 : _e.projectId) != null ? _f : "",
124
151
  preset: task.request.preset,
125
152
  pipeline: ""
126
153
  },
127
154
  lastLine: "Ready",
128
155
  error: void 0,
129
156
  delivered: false,
130
- endedAt: (_c = job.endedAt) != null ? _c : now,
157
+ endedAt: (_g = job.endedAt) != null ? _g : now,
131
158
  verdictBy: "agent"
132
159
  } : {
133
160
  state: "failed",
134
161
  error: job.error || (job.state === "succeeded" ? "Production finished but returned no video" : "Production failed"),
135
- endedAt: (_d = job.endedAt) != null ? _d : now,
162
+ endedAt: (_h = job.endedAt) != null ? _h : now,
136
163
  verdictBy: "agent"
137
164
  }
138
165
  });
139
166
  continue;
140
167
  }
141
- if (!isTerminal(task.state) && job.state === "running" && job.agentOwned) {
168
+ if (!isTerminal(task.state) && job.state === "running" && agentHasJob(job)) {
142
169
  const line = serverProgressLine(job);
143
170
  if (line && line !== task.lastLine) out.push({
144
171
  id: task.id,
@@ -1 +1 @@
1
- {"version":3,"file":"canvasTaskSync.js","sources":["../../../src/features/canvas/canvasTaskSync.ts"],"sourcesContent":["/**\n * The Tasks sheet's list - native twin of canvas `tasks/rows`, `tasks/reconcile`\n * and the store half of `tasks/remote` (the mirror).\n *\n * One list: this phone's productions (live, from ./canvasTasks) and the\n * caller's canvas jobs on the Task API that no local task holds - a run\n * started on the web, on another phone, or a lip sync. The server rows are\n * also how a production the agent followed settles here (reconcile), and how\n * a production this phone settled itself reaches every other panel (mirror).\n *\n * The pure halves (`buildTaskRows`, `reconcilePatches`, `mirrorPlan`) carry\n * the rules and are tested; `syncCanvasTasks` applies them.\n */\nimport { useEffect, useState } from 'react';\nimport { applyServerPatch, isTerminal, listCanvasTasks, type CanvasTask } from './canvasTasks';\nimport {\n CANVAS_SURFACE,\n canvasTaskToJob,\n claimDelivery,\n isStaleJob,\n jobFingerprint,\n jobKey,\n listRemoteJobs,\n promoVideoFromVerdict,\n recordSurfaceJob,\n removeSurfaceJob,\n serverProgressLine,\n sortJobs,\n surfaceJobPatch,\n taskApiTransport,\n updateSurfaceJob,\n type JobRecord,\n type TaskApiTransport,\n} from './serverTasks';\nimport type { RunMediaAction } from './videoEditor/mediaActions';\n\n// ── Rows ─────────────────────────────────────────────────────────────────────\n\nexport type TaskRow =\n | { kind: 'task'; key: string; task: CanvasTask; remote?: JobRecord }\n | { kind: 'job'; key: string; job: JobRecord };\n\n/** Local tasks first-class, then every server row no local task holds; running first, newest first. */\nexport function buildTaskRows(local: CanvasTask[], remote: JobRecord[], hidden?: ReadonlySet<string>): TaskRow[] {\n const byKey = new Map(remote.map((job) => [jobKey(job), job]));\n const rows: (TaskRow & { state: JobRecord['state']; createdAt: number })[] = [];\n const held = new Set<string>();\n for (const task of local) {\n const job = canvasTaskToJob(task);\n const key = jobKey(job);\n held.add(key);\n const row = byKey.get(key);\n rows.push({\n kind: 'task',\n key,\n task,\n ...(row ? { remote: row } : {}),\n state: job.state,\n createdAt: job.createdAt,\n });\n }\n for (const job of remote) {\n const key = jobKey(job);\n if (held.has(key) || hidden?.has(key)) continue;\n rows.push({ kind: 'job', key, job, state: job.state, createdAt: job.createdAt });\n }\n return sortJobs(rows).map(({ state: _s, createdAt: _c, ...row }) => row as TaskRow);\n}\n\n/** Still marked running past its deadline: shown as \"Stopped responding\", never with a growing clock. */\nexport function isRowStaleAt(row: TaskRow, now: number): boolean {\n if (row.kind === 'job') return isStaleJob(row.job, now);\n const { task } = row;\n return (\n !isTerminal(task.state) &&\n isStaleJob({ state: 'running', deadlineAt: task.deadlineAt, createdAt: task.createdAt }, now)\n );\n}\n\nexport const isRowRunningAt = (row: TaskRow, now: number): boolean =>\n (row.kind === 'task' ? !isTerminal(row.task.state) : row.job.state === 'running') && !isRowStaleAt(row, now);\n\n// ── The card's numbers ───────────────────────────────────────────────────────\n\n/** \"1m 05s\" - how long a run has worked (web `formatWorked`). */\nexport function formatWorked(ms: number): string {\n const s = Math.max(0, Math.round(ms / 1000));\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${String(s % 60).padStart(2, '0')}s`;\n const h = Math.floor(m / 60);\n return `${h}h ${String(m % 60).padStart(2, '0')}m`;\n}\n\n/** An export's bar: steps done, or time against the projection - never the finish on time alone. */\nexport function renderProgressPct(\n step: { index: number; total: number } | undefined,\n projectedMs: number | undefined,\n elapsedMs: number,\n): number {\n const byStep = step && step.total > 0 ? Math.min(100, ((step.index - 1) / step.total) * 100) : 0;\n const byTime = projectedMs ? Math.min(95, (elapsedMs / projectedMs) * 100) : 0;\n return Math.max(0, byStep, byTime);\n}\n\nexport function renderTimeLeft(projectedMs: number, elapsedMs: number): string {\n const left = projectedMs - elapsedMs;\n if (left <= 0) return 'Taking longer than estimated';\n if (left < 60_000) return 'Less than a minute left';\n return `About ${Math.max(1, Math.round(left / 60_000))} min left`;\n}\n\n// ── Reconcile: the rows' word on local tasks ─────────────────────────────────\n\nexport interface TaskPatch {\n id: string;\n patch: Partial<CanvasTask>;\n}\n\n/**\n * What the server rows change on this phone's tasks: the agent's verdict\n * (final - also over a failure this phone decided while the agent still had\n * the run, as long as nothing was placed), and the progress line while the\n * agent works. Productions only; an export's row is the export lane's.\n */\nexport function reconcilePatches(local: CanvasTask[], remote: JobRecord[], now = Date.now()): TaskPatch[] {\n const byId = new Map(remote.filter((j) => j.surface === CANVAS_SURFACE).map((j) => [j.id, j]));\n const out: TaskPatch[] = [];\n for (const task of local) {\n if (task.kind !== 'promo') continue;\n const job = byId.get(task.id);\n if (!job) continue;\n const browserFailure = task.state === 'failed' && task.verdictBy !== 'agent' && !task.delivered;\n if (job.state !== 'running' && job.verdictBy === 'agent' && (!isTerminal(task.state) || browserFailure)) {\n const video = job.state === 'succeeded' ? promoVideoFromVerdict(job) : undefined;\n out.push({\n id: task.id,\n patch: video\n ? {\n state: 'succeeded',\n result: {\n url: video.url,\n title: video.title || 'Marketing video',\n projectId: task.handle?.projectId ?? '',\n preset: task.request.preset,\n pipeline: '',\n },\n lastLine: 'Ready',\n error: undefined,\n delivered: false,\n endedAt: job.endedAt ?? now,\n verdictBy: 'agent',\n }\n : {\n state: 'failed',\n error:\n job.error ||\n (job.state === 'succeeded'\n ? 'Production finished but returned no video'\n : 'Production failed'),\n endedAt: job.endedAt ?? now,\n verdictBy: 'agent',\n },\n });\n continue;\n }\n if (!isTerminal(task.state) && job.state === 'running' && job.agentOwned) {\n const line = serverProgressLine(job);\n if (line && line !== task.lastLine) out.push({ id: task.id, patch: { lastLine: line } });\n }\n }\n return out;\n}\n\n// ── Mirror: this phone's word on its own rows ────────────────────────────────\n\nexport interface MirrorPlan {\n /** Local tasks with no row yet (recorded before a backend answered, or by an older build). */\n create: CanvasTask[];\n /** Rows behind what this phone knows: a production it followed and settled itself. */\n update: { remoteId: string; task: CanvasTask }[];\n}\n\n/**\n * What to write so every panel reads what this phone knows. A run the agent\n * follows is the agent's to report; an agent verdict is never written over.\n * `sent` holds fingerprints already written this session.\n */\nexport function mirrorPlan(\n local: CanvasTask[],\n remote: JobRecord[],\n sent: ReadonlyMap<string, string> = new Map(),\n): MirrorPlan {\n const byId = new Map(remote.filter((j) => j.surface === CANVAS_SURFACE).map((j) => [j.id, j]));\n const plan: MirrorPlan = { create: [], update: [] };\n for (const task of local) {\n const job = canvasTaskToJob(task);\n const print = jobFingerprint(job);\n if (sent.get(task.id) === print) continue;\n const row = byId.get(task.id);\n if (!row) {\n if (task.state !== 'submitting') plan.create.push(task);\n continue;\n }\n if (!row.remoteId || row.verdictBy === 'agent') continue;\n if (task.agentReports && !isTerminal(task.state)) continue;\n if (jobFingerprint(row) === print) continue;\n plan.update.push({ remoteId: row.remoteId, task });\n }\n return plan;\n}\n\nconst sentPrints = new Map<string, string>();\n\n/** One pass: list the rows, settle local tasks from them, write back what the rows lack. */\nexport async function syncCanvasTasks(t: TaskApiTransport | null = taskApiTransport()): Promise<JobRecord[]> {\n if (!t) return [];\n const remote = await listRemoteJobs(t, CANVAS_SURFACE);\n for (const { id, patch } of reconcilePatches(listCanvasTasks(), remote)) applyServerPatch(id, patch);\n const plan = mirrorPlan(listCanvasTasks(), remote, sentPrints);\n await Promise.all([\n ...plan.create.map(async (task) => {\n const job = canvasTaskToJob(task);\n if (await recordSurfaceJob(t, job).catch(() => null)) sentPrints.set(task.id, jobFingerprint(job));\n }),\n ...plan.update.map(async ({ remoteId, task }) => {\n const job = canvasTaskToJob(task);\n await updateSurfaceJobSafe(t, remoteId, job);\n sentPrints.set(task.id, jobFingerprint(job));\n }),\n ]);\n return remote;\n}\n\nasync function updateSurfaceJobSafe(t: TaskApiTransport, remoteId: string, job: JobRecord): Promise<void> {\n await updateSurfaceJob(t, remoteId, surfaceJobPatch(job)).catch(() => undefined);\n}\n\n/** Take a row down (a dismissed run). Best effort. */\nexport async function removeRemoteRow(remoteId: string | undefined): Promise<void> {\n const t = taskApiTransport();\n if (!t || !remoteId) return;\n await removeSurfaceJob(t, remoteId).catch(() => undefined);\n}\n\n/**\n * Claim a finished row before placing its result: true for exactly one\n * device. No row, no backend, or a backend without claims: place as before.\n */\nexport async function claimRow(remoteId: string | undefined): Promise<boolean> {\n const t = taskApiTransport();\n if (!t || !remoteId) return true;\n const claimed = await claimDelivery(t, remoteId).catch(() => undefined);\n return claimed !== false;\n}\n\n// ── The host: what the sheet cannot learn from its own props ────────────────\n\nexport interface CanvasTasksHost {\n /** The board on screen, so a ready task offers \"Place on board\" or \"Open board\". */\n openBoardId: string | null;\n openBoard?: (boardId: string) => void;\n boardLabel?: (boardId: string) => string | undefined;\n /** For \"Run again\". */\n runAction?: RunMediaAction;\n}\n\nlet host: CanvasTasksHost = { openBoardId: null };\nconst hostListeners = new Set<() => void>();\n\n/** CanvasExperience keeps this current; the sheet reads it. */\nexport function setCanvasTasksHost(next: Partial<CanvasTasksHost>): void {\n host = { ...host, ...next };\n hostListeners.forEach((l) => l());\n}\n\nexport function useCanvasTasksHost(): CanvasTasksHost {\n const [value, setValue] = useState(host);\n useEffect(() => {\n const listener = () => setValue(host);\n hostListeners.add(listener);\n listener();\n return () => {\n hostListeners.delete(listener);\n };\n }, []);\n return value;\n}\n\n/** How often the sheet re-reads the rows: briskly while one is running, rarely when all are done. */\nexport const SYNC_RUNNING_MS = 8_000;\nexport const SYNC_IDLE_MS = 30_000;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canvasTaskSync.js","sources":["../../../src/features/canvas/canvasTaskSync.ts"],"sourcesContent":["/**\n * The Tasks sheet's list - native twin of canvas `tasks/rows`, `tasks/reconcile`\n * and the store half of `tasks/remote` (the mirror).\n *\n * One list: this phone's productions (live, from ./canvasTasks) and the\n * caller's canvas jobs on the Task API that no local task holds - a run\n * started on the web, on another phone, or a lip sync. The server rows are\n * also how a production the agent followed settles here (reconcile), and how\n * a production this phone settled itself reaches every other panel (mirror).\n *\n * The pure halves (`buildTaskRows`, `reconcilePatches`, `mirrorPlan`) carry\n * the rules and are tested; `syncCanvasTasks` applies them.\n */\nimport { useEffect, useState } from 'react';\nimport { applyServerPatch, isTerminal, listCanvasTasks, type CanvasTask } from './canvasTasks';\nimport {\n agentHasJob,\n CANVAS_SURFACE,\n canvasTaskToJob,\n claimDelivery,\n isStaleJob,\n jobFingerprint,\n jobKey,\n listRemoteJobs,\n promoVideoFromVerdict,\n recordSurfaceJob,\n removeSurfaceJob,\n serverProgressLine,\n sortJobs,\n surfaceJobPatch,\n taskApiTransport,\n updateSurfaceJob,\n type JobRecord,\n type TaskApiTransport,\n} from './serverTasks';\nimport type { RunMediaAction } from './videoEditor/mediaActions';\n\n// ── Rows ─────────────────────────────────────────────────────────────────────\n\nexport type TaskRow =\n | { kind: 'task'; key: string; task: CanvasTask; remote?: JobRecord }\n | { kind: 'job'; key: string; job: JobRecord };\n\n/** Local tasks first-class, then every server row no local task holds; running first, newest first. */\nexport function buildTaskRows(local: CanvasTask[], remote: JobRecord[], hidden?: ReadonlySet<string>): TaskRow[] {\n const byKey = new Map(remote.map((job) => [jobKey(job), job]));\n const rows: (TaskRow & { state: JobRecord['state']; createdAt: number })[] = [];\n const held = new Set<string>();\n for (const task of local) {\n const job = canvasTaskToJob(task);\n const key = jobKey(job);\n held.add(key);\n const row = byKey.get(key);\n rows.push({\n kind: 'task',\n key,\n task,\n ...(row ? { remote: row } : {}),\n state: job.state,\n createdAt: job.createdAt,\n });\n }\n for (const job of remote) {\n const key = jobKey(job);\n if (held.has(key) || hidden?.has(key)) continue;\n rows.push({ kind: 'job', key, job, state: job.state, createdAt: job.createdAt });\n }\n return sortJobs(rows).map(({ state: _s, createdAt: _c, ...row }) => row as TaskRow);\n}\n\n/** Still marked running past its deadline: shown as \"Stopped responding\", never with a growing clock. */\nexport function isRowStaleAt(row: TaskRow, now: number): boolean {\n if (row.kind === 'job') return isStaleJob(row.job, now);\n const { task } = row;\n return (\n !isTerminal(task.state) &&\n isStaleJob({ state: 'running', deadlineAt: task.deadlineAt, createdAt: task.createdAt }, now)\n );\n}\n\nexport const isRowRunningAt = (row: TaskRow, now: number): boolean =>\n (row.kind === 'task' ? !isTerminal(row.task.state) : row.job.state === 'running') && !isRowStaleAt(row, now);\n\n// ── The card's numbers ───────────────────────────────────────────────────────\n\n/** \"1m 05s\" - how long a run has worked (web `formatWorked`). */\nexport function formatWorked(ms: number): string {\n const s = Math.max(0, Math.round(ms / 1000));\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${String(s % 60).padStart(2, '0')}s`;\n const h = Math.floor(m / 60);\n return `${h}h ${String(m % 60).padStart(2, '0')}m`;\n}\n\n/** An export's bar: steps done, or time against the projection - never the finish on time alone. */\nexport function renderProgressPct(\n step: { index: number; total: number } | undefined,\n projectedMs: number | undefined,\n elapsedMs: number,\n): number {\n const byStep = step && step.total > 0 ? Math.min(100, ((step.index - 1) / step.total) * 100) : 0;\n const byTime = projectedMs ? Math.min(95, (elapsedMs / projectedMs) * 100) : 0;\n return Math.max(0, byStep, byTime);\n}\n\nexport function renderTimeLeft(projectedMs: number, elapsedMs: number): string {\n const left = projectedMs - elapsedMs;\n if (left <= 0) return 'Taking longer than estimated';\n if (left < 60_000) return 'Less than a minute left';\n return `About ${Math.max(1, Math.round(left / 60_000))} min left`;\n}\n\n// ── Reconcile: the rows' word on local tasks ─────────────────────────────────\n\nexport interface TaskPatch {\n id: string;\n patch: Partial<CanvasTask>;\n}\n\n/**\n * What the server rows change on this phone's tasks: the agent's verdict\n * (final - also over a failure this phone decided while the agent still had\n * the run, as long as nothing was placed), and the progress line while the\n * agent works. Productions and generations; an export's row is the export lane's.\n */\nexport function reconcilePatches(local: CanvasTask[], remote: JobRecord[], now = Date.now()): TaskPatch[] {\n const byId = new Map(remote.filter((j) => j.surface === CANVAS_SURFACE).map((j) => [j.id, j]));\n const out: TaskPatch[] = [];\n for (const task of local) {\n if (task.kind !== 'promo' && task.kind !== 'generate') continue;\n const job = byId.get(task.id);\n if (!job) continue;\n const browserFailure = task.state === 'failed' && task.verdictBy !== 'agent' && !task.delivered;\n if (\n task.kind === 'generate' &&\n job.state !== 'running' &&\n job.verdictBy === 'agent' &&\n (!isTerminal(task.state) || browserFailure)\n ) {\n const url = job.state === 'succeeded' ? job.results?.find((r) => r.url)?.url : undefined;\n out.push({\n id: task.id,\n patch: url\n ? {\n state: 'succeeded',\n result: {\n url,\n title: task.brief || task.title,\n projectId: '',\n preset: 'generate',\n pipeline: '',\n },\n lastLine: 'Ready',\n error: undefined,\n delivered: false,\n endedAt: job.endedAt ?? now,\n verdictBy: 'agent',\n }\n : {\n state: 'failed',\n error: job.error || 'Generation failed',\n endedAt: job.endedAt ?? now,\n verdictBy: 'agent',\n },\n });\n continue;\n }\n if (job.state !== 'running' && job.verdictBy === 'agent' && (!isTerminal(task.state) || browserFailure)) {\n const video = job.state === 'succeeded' ? promoVideoFromVerdict(job) : undefined;\n out.push({\n id: task.id,\n patch: video\n ? {\n state: 'succeeded',\n result: {\n url: video.url,\n title: video.title || 'Marketing video',\n projectId: task.handle?.projectId ?? '',\n preset: task.request.preset,\n pipeline: '',\n },\n lastLine: 'Ready',\n error: undefined,\n delivered: false,\n endedAt: job.endedAt ?? now,\n verdictBy: 'agent',\n }\n : {\n state: 'failed',\n error:\n job.error ||\n (job.state === 'succeeded'\n ? 'Production finished but returned no video'\n : 'Production failed'),\n endedAt: job.endedAt ?? now,\n verdictBy: 'agent',\n },\n });\n continue;\n }\n if (!isTerminal(task.state) && job.state === 'running' && agentHasJob(job)) {\n const line = serverProgressLine(job);\n if (line && line !== task.lastLine) out.push({ id: task.id, patch: { lastLine: line } });\n }\n }\n return out;\n}\n\n// ── Mirror: this phone's word on its own rows ────────────────────────────────\n\nexport interface MirrorPlan {\n /** Local tasks with no row yet (recorded before a backend answered, or by an older build). */\n create: CanvasTask[];\n /** Rows behind what this phone knows: a production it followed and settled itself. */\n update: { remoteId: string; task: CanvasTask }[];\n}\n\n/**\n * What to write so every panel reads what this phone knows. A run the agent\n * follows is the agent's to report; an agent verdict is never written over.\n * `sent` holds fingerprints already written this session.\n */\nexport function mirrorPlan(\n local: CanvasTask[],\n remote: JobRecord[],\n sent: ReadonlyMap<string, string> = new Map(),\n): MirrorPlan {\n const byId = new Map(remote.filter((j) => j.surface === CANVAS_SURFACE).map((j) => [j.id, j]));\n const plan: MirrorPlan = { create: [], update: [] };\n for (const task of local) {\n const job = canvasTaskToJob(task);\n const print = jobFingerprint(job);\n if (sent.get(task.id) === print) continue;\n const row = byId.get(task.id);\n if (!row) {\n if (task.state !== 'submitting') plan.create.push(task);\n continue;\n }\n if (!row.remoteId || row.verdictBy === 'agent') continue;\n if (task.agentReports && !isTerminal(task.state)) continue;\n if (jobFingerprint(row) === print) continue;\n plan.update.push({ remoteId: row.remoteId, task });\n }\n return plan;\n}\n\nconst sentPrints = new Map<string, string>();\n\n/** One pass: list the rows, settle local tasks from them, write back what the rows lack. */\nexport async function syncCanvasTasks(t: TaskApiTransport | null = taskApiTransport()): Promise<JobRecord[]> {\n if (!t) return [];\n const remote = await listRemoteJobs(t, CANVAS_SURFACE);\n for (const { id, patch } of reconcilePatches(listCanvasTasks(), remote)) applyServerPatch(id, patch);\n const plan = mirrorPlan(listCanvasTasks(), remote, sentPrints);\n await Promise.all([\n ...plan.create.map(async (task) => {\n const job = canvasTaskToJob(task);\n if (await recordSurfaceJob(t, job).catch(() => null)) sentPrints.set(task.id, jobFingerprint(job));\n }),\n ...plan.update.map(async ({ remoteId, task }) => {\n const job = canvasTaskToJob(task);\n await updateSurfaceJobSafe(t, remoteId, job);\n sentPrints.set(task.id, jobFingerprint(job));\n }),\n ]);\n return remote;\n}\n\nasync function updateSurfaceJobSafe(t: TaskApiTransport, remoteId: string, job: JobRecord): Promise<void> {\n await updateSurfaceJob(t, remoteId, surfaceJobPatch(job)).catch(() => undefined);\n}\n\n/** Take a row down (a dismissed run). Best effort. */\nexport async function removeRemoteRow(remoteId: string | undefined): Promise<void> {\n const t = taskApiTransport();\n if (!t || !remoteId) return;\n await removeSurfaceJob(t, remoteId).catch(() => undefined);\n}\n\n/**\n * Claim a finished row before placing its result: true for exactly one\n * device. No row, no backend, or a backend without claims: place as before.\n */\nexport async function claimRow(remoteId: string | undefined): Promise<boolean> {\n const t = taskApiTransport();\n if (!t || !remoteId) return true;\n const claimed = await claimDelivery(t, remoteId).catch(() => undefined);\n return claimed !== false;\n}\n\n// ── The host: what the sheet cannot learn from its own props ────────────────\n\nexport interface CanvasTasksHost {\n /** The board on screen, so a ready task offers \"Place on board\" or \"Open board\". */\n openBoardId: string | null;\n openBoard?: (boardId: string) => void;\n boardLabel?: (boardId: string) => string | undefined;\n /** For \"Run again\". */\n runAction?: RunMediaAction;\n}\n\nlet host: CanvasTasksHost = { openBoardId: null };\nconst hostListeners = new Set<() => void>();\n\n/** CanvasExperience keeps this current; the sheet reads it. */\nexport function setCanvasTasksHost(next: Partial<CanvasTasksHost>): void {\n host = { ...host, ...next };\n hostListeners.forEach((l) => l());\n}\n\nexport function useCanvasTasksHost(): CanvasTasksHost {\n const [value, setValue] = useState(host);\n useEffect(() => {\n const listener = () => setValue(host);\n hostListeners.add(listener);\n listener();\n return () => {\n hostListeners.delete(listener);\n };\n }, []);\n return value;\n}\n\n/** How often the sheet re-reads the rows: briskly while one is running, rarely when all are done. */\nexport const SYNC_RUNNING_MS = 8_000;\nexport const SYNC_IDLE_MS = 30_000;\n"],"names":[],"mappings":"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"}
@@ -33,12 +33,14 @@ function persist() {
33
33
  function coerceTask(value) {
34
34
  if (!value || typeof value !== "object") return null;
35
35
  const t = value;
36
- if (typeof t.id !== "string" || !t.id || t.kind !== "promo" && t.kind !== "export") return null;
36
+ if (typeof t.id !== "string" || !t.id || t.kind !== "promo" && t.kind !== "export" && t.kind !== "generate") {
37
+ return null;
38
+ }
37
39
  if (typeof t.state !== "string") return null;
38
40
  if (!["submitting", "running", "succeeded", "failed"].includes(t.state)) return null;
39
41
  if (!t.request || typeof t.request !== "object" || typeof t.boardId !== "string") return null;
40
42
  return __spreadProps(__spreadValues({}, t), {
41
- title: typeof t.title === "string" ? t.title : t.kind === "export" ? "Video export" : "Marketing video",
43
+ title: typeof t.title === "string" ? t.title : t.kind === "export" ? "Video export" : t.kind === "generate" ? "Generation" : "Marketing video",
42
44
  brief: typeof t.brief === "string" ? t.brief : "",
43
45
  createdAt: typeof t.createdAt === "number" ? t.createdAt : 0
44
46
  });
@@ -261,12 +263,30 @@ async function startPromoTask(run, input) {
261
263
  return tasks.find((t) => t.id === id);
262
264
  }
263
265
  const taskResumers = /* @__PURE__ */ new Set();
266
+ const liveGenerations = /* @__PURE__ */ new Set();
267
+ function markGenerationLive(id, live) {
268
+ if (live) liveGenerations.add(id);
269
+ else liveGenerations.delete(id);
270
+ }
271
+ function settleOrphanedGenerations() {
272
+ for (const task of tasks) {
273
+ if (task.kind !== "generate" || isTerminal(task.state) || liveGenerations.has(task.id)) continue;
274
+ if (task.agentReports) continue;
275
+ patchTask(task.id, {
276
+ state: "failed",
277
+ endedAt: Date.now(),
278
+ error: "The app closed before the generation finished - generate again.",
279
+ lastLine: "Interrupted"
280
+ });
281
+ }
282
+ }
264
283
  function registerTaskResumer(resume) {
265
284
  taskResumers.add(resume);
266
285
  }
267
286
  function resumePromoTasks(run) {
268
287
  void hydrateCanvasTasks().then(() => {
269
288
  taskResumers.forEach((resume) => resume(run));
289
+ settleOrphanedGenerations();
270
290
  for (const task of tasks) {
271
291
  if (task.kind !== "promo") continue;
272
292
  if ((task.state === "running" || task.state === "submitting") && task.handle && !pollers.has(task.id)) {
@@ -275,4 +295,4 @@ function resumePromoTasks(run) {
275
295
  }
276
296
  }
277
297
  });
278
- }export{addCanvasTask,applyServerPatch,coerceTask,dismissTask,getCanvasTask,hydrateCanvasTasks,isTerminal,listCanvasTasks,markTaskDelivered,patchCanvasTask,registerTaskResumer,resumePromoTasks,runningTaskCount,startPromoTask,subscribeCanvasTasks};//# sourceMappingURL=canvasTasks.js.map
298
+ }export{addCanvasTask,applyServerPatch,coerceTask,dismissTask,getCanvasTask,hydrateCanvasTasks,isTerminal,listCanvasTasks,markGenerationLive,markTaskDelivered,patchCanvasTask,registerTaskResumer,resumePromoTasks,runningTaskCount,startPromoTask,subscribeCanvasTasks};//# sourceMappingURL=canvasTasks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvasTasks.js","sources":["../../../src/features/canvas/canvasTasks.ts"],"sourcesContent":["/**\n * Background canvas tasks — native twin of canvas-surface `tasks/taskStore` + `promoTask`.\n * Promo productions outlive the generate sheet; More → Tasks shows progress.\n */\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport {\n PRODUCE_STATUS_ACTION,\n PRODUCE_SUBMIT_ACTION,\n PROMO_CONNECTOR,\n PROMO_POLL_EVERY_MS,\n buildPromoRunParams,\n promoPollMaxMs,\n promoRunTimeoutMs,\n parsePollResult,\n parseSubmitResult,\n type PromoRunOptions,\n type PromoRunResult,\n type PromoSubmitHandle,\n} from './promoVideo';\nimport type { RunMediaAction } from './videoEditor/mediaActions';\nimport type { RenderHandle, RenderPoll } from './videoEditor/renderTimeline';\n// Cycle by design: exportTask drives tasks through this store's public API.\nimport {\n PROMO_FOLLOW_SLACK_MS,\n awaitAgentVerdict,\n canvasJobKey,\n forgetServerJob,\n jobDeadlineAt,\n lookupRemoteJobId,\n promoVideoFromVerdict,\n registerPromoJob,\n runWithJob,\n serverJobId,\n serverProgressLine,\n} from './serverTasks';\n\nexport type TaskState = 'submitting' | 'running' | 'succeeded' | 'failed';\n\n/**\n * 'promo' - marketing production (PRODUCE_SUBMIT/STATUS): `handle` + `request`.\n * 'export' - the video editor's detached timeline render (videoEditor/exportTask,\n * RENDER_TIMELINE_SUBMIT/STATUS): `render`, `step`, `notice`,\n * `warnings`, `local`, and `result.url` = the finished mp4. Its\n * `request` is a descriptive stub (preset 'export') - never\n * resubmit it as a promo.\n */\nexport type CanvasTaskKind = 'promo' | 'export';\n\nexport interface CanvasTask {\n id: string;\n kind: CanvasTaskKind;\n title: string;\n brief: string;\n boardId: string;\n state: TaskState;\n createdAt: number;\n startedAt?: number;\n endedAt?: number;\n handle?: PromoSubmitHandle;\n lastLine?: string;\n request: PromoRunOptions;\n result?: PromoRunResult;\n error?: string;\n delivered?: boolean;\n /** Past this a task still running has stopped responding (its budget + the follow slack + grace). */\n deadlineAt?: number;\n /** The SUBMIT carried the server job: the agent follows the run and reports to its row (./serverTasks). */\n agentReports?: boolean;\n /** Who gave the terminal state, when it came from the server row. */\n verdictBy?: 'agent' | 'browser' | 'deadline';\n // ── kind 'export' only (optional; promo tasks never carry them) ──\n /** The detached render's handle (sandbox/run ids, output url, projected time, lease). */\n render?: RenderHandle;\n /** Latest render progress from STATUS. */\n step?: RenderPoll['step'];\n /** The connector's word on the render time limit, shown to the person. */\n notice?: string;\n /** Compile warnings (a transition that overlaps footage, ...). */\n warnings?: string[];\n /** Rendering through the in-app client chain (SUBMIT unavailable): dies with the app. */\n local?: boolean;\n}\n\nconst STORAGE_KEY = 'canvas.tasks.v1';\nconst MAX_FINISHED = 20;\nconst listeners = new Set<() => void>();\nlet tasks: CanvasTask[] = [];\nlet hydrated = false;\nconst pollers = new Map<string, Promise<void>>();\n\nexport const isTerminal = (state: TaskState): boolean => state === 'succeeded' || state === 'failed';\n\nfunction emit() {\n listeners.forEach((l) => l());\n}\n\nfunction persist() {\n void AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(tasks)).catch(() => undefined);\n}\n\nexport function coerceTask(value: unknown): CanvasTask | null {\n if (!value || typeof value !== 'object') return null;\n const t = value as Record<string, unknown>;\n if (typeof t.id !== 'string' || !t.id || (t.kind !== 'promo' && t.kind !== 'export')) return null;\n if (typeof t.state !== 'string') return null;\n if (!['submitting', 'running', 'succeeded', 'failed'].includes(t.state)) return null;\n if (!t.request || typeof t.request !== 'object' || typeof t.boardId !== 'string') return null;\n return {\n ...(t as unknown as CanvasTask),\n title: typeof t.title === 'string' ? t.title : t.kind === 'export' ? 'Video export' : 'Marketing video',\n brief: typeof t.brief === 'string' ? t.brief : '',\n createdAt: typeof t.createdAt === 'number' ? t.createdAt : 0,\n };\n}\n\nexport async function hydrateCanvasTasks(): Promise<void> {\n if (hydrated) return;\n hydrated = true;\n try {\n const raw = await AsyncStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const parsed = JSON.parse(raw);\n tasks = Array.isArray(parsed) ? parsed.map(coerceTask).filter((t): t is CanvasTask => t !== null) : [];\n emit();\n } catch {\n tasks = [];\n }\n}\n\nexport function getCanvasTask(id: string): CanvasTask | undefined {\n return tasks.find((t) => t.id === id);\n}\n\n/** Patch one task (no-op for an unknown id) - used by the export runner. */\nexport function patchCanvasTask(id: string, patch: Partial<CanvasTask>) {\n if (!tasks.some((t) => t.id === id)) return;\n patchTask(id, patch);\n}\n\n/** Register a new task (newest first) - used by the export runner. */\nexport function addCanvasTask(task: CanvasTask) {\n tasks = [task, ...tasks.filter((t) => t.id !== task.id)];\n persist();\n emit();\n}\n\nexport function listCanvasTasks(): CanvasTask[] {\n return tasks;\n}\n\nexport function subscribeCanvasTasks(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function runningTaskCount(): number {\n return tasks.filter((t) => t.state === 'submitting' || t.state === 'running').length;\n}\n\nfunction pruneFinished(list: CanvasTask[]): CanvasTask[] {\n const finished = list.filter((t) => isTerminal(t.state)).sort((a, b) => b.createdAt - a.createdAt);\n const keep = new Set(finished.slice(0, MAX_FINISHED).map((t) => t.id));\n return list.filter((t) => !isTerminal(t.state) || keep.has(t.id));\n}\n\nfunction patchTask(id: string, patch: Partial<CanvasTask>) {\n tasks = pruneFinished(tasks.map((t) => (t.id === id ? { ...t, ...patch } : t)));\n persist();\n emit();\n}\n\nexport function dismissTask(id: string) {\n tasks = tasks.filter((t) => t.id !== id);\n persist();\n emit();\n}\n\nexport function markTaskDelivered(id: string) {\n patchTask(id, { delivered: true });\n}\n\n/** A patch from the task's server row (./canvasTaskSync reconcile). No-op for an unknown id. */\nexport function applyServerPatch(id: string, patch: Partial<CanvasTask>) {\n if (!tasks.some((t) => t.id === id)) return;\n patchTask(id, patch);\n}\n\nlet seq = 0;\nconst newId = () => `task-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\n/**\n * Wait on the agent's verdict for a run it was handed, instead of polling\n * STATUS beside it (a promo sandbox dies on the first terminal answer, so two\n * pollers race). True when the row settled the task; false to poll as before.\n */\nasync function awaitAgentFor(id: string): Promise<boolean> {\n const task = tasks.find((t) => t.id === id);\n if (!task?.agentReports) return false;\n // After a restart the token is gone (memory only) but the row is not: find it in the listing.\n const remoteId = serverJobId(canvasJobKey(id)) ?? (await lookupRemoteJobId(id).catch(() => undefined));\n if (!remoteId) return false;\n try {\n const verdict = await awaitAgentVerdict(remoteId, {\n submittedAt: task.startedAt ?? task.createdAt,\n deadlineAt: task.deadlineAt ?? Date.now() + promoPollMaxMs(task.request),\n onProgress: (row) => {\n const line = serverProgressLine(row);\n if (line) patchTask(id, { state: 'running', lastLine: line });\n },\n });\n if (!verdict) {\n patchTask(id, { agentReports: false });\n return false;\n }\n const video = verdict.state === 'succeeded' ? promoVideoFromVerdict(verdict) : undefined;\n patchTask(id, {\n ...(video\n ? {\n state: 'succeeded' as const,\n result: {\n url: video.url,\n title: video.title || 'Marketing video',\n projectId: task.handle?.projectId ?? '',\n preset: task.request.preset,\n pipeline: '',\n },\n lastLine: 'Ready',\n }\n : {\n state: 'failed' as const,\n error:\n verdict.error ||\n (verdict.state === 'succeeded'\n ? 'Production finished but returned no video'\n : 'Production failed'),\n }),\n endedAt: verdict.endedAt ?? Date.now(),\n ...(verdict.verdictBy ? { verdictBy: verdict.verdictBy } : {}),\n });\n forgetServerJob(canvasJobKey(id));\n return true;\n } catch (err: unknown) {\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: err instanceof Error ? err.message : String(err),\n });\n return true;\n }\n}\n\nasync function pollTask(run: RunMediaAction, id: string) {\n if (await awaitAgentFor(id)) return;\n const started = Date.now();\n // A studio production runs ~100 min; its wait has to outlast that.\n const request = tasks.find((t) => t.id === id)?.request;\n const pollMax = request ? promoPollMaxMs(request) : promoPollMaxMs({ preset: '' });\n while (Date.now() - started < pollMax) {\n const task = tasks.find((t) => t.id === id);\n if (!task?.handle) return;\n try {\n const raw = await run(PROMO_CONNECTOR, PRODUCE_STATUS_ACTION, {\n projectId: task.handle.projectId,\n sandboxId: task.handle.sandboxId,\n });\n const poll = parsePollResult(raw);\n if (poll.state === 'succeeded' && poll.result) {\n patchTask(id, {\n state: 'succeeded',\n endedAt: Date.now(),\n result: poll.result,\n lastLine: poll.progress.at(-1) || 'Done',\n });\n return;\n }\n if (poll.state === 'failed') {\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: poll.error || 'Production failed',\n lastLine: poll.error || 'Failed',\n });\n return;\n }\n patchTask(id, {\n state: 'running',\n lastLine: poll.progress.at(-1) || 'Working…',\n });\n } catch (err: unknown) {\n patchTask(id, {\n lastLine: err instanceof Error ? err.message : 'Poll error — retrying',\n });\n }\n await new Promise((r) => setTimeout(r, PROMO_POLL_EVERY_MS));\n }\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: 'Timed out waiting for the marketing video',\n });\n}\n\n/** Submit promo and poll in the background (does not block the UI). */\nexport async function startPromoTask(\n run: RunMediaAction,\n input: { request: PromoRunOptions; boardId: string; brief: string },\n): Promise<CanvasTask> {\n await hydrateCanvasTasks();\n const id = newId();\n const createdAt = Date.now();\n const task: CanvasTask = {\n id,\n kind: 'promo',\n title: 'Marketing video',\n brief: input.brief,\n boardId: input.boardId,\n state: 'submitting',\n createdAt,\n // The run's own budget, the follow's slack past it, then the grace.\n deadlineAt: jobDeadlineAt(createdAt, promoRunTimeoutMs(input.request) + PROMO_FOLLOW_SLACK_MS),\n request: input.request,\n lastLine: 'Submitting…',\n };\n tasks = [task, ...tasks];\n persist();\n emit();\n\n try {\n // Recorded before the submit (two seconds at most), so the SUBMIT can hand the agent the job.\n const job = await registerPromoJob(task, () => tasks.some((t) => t.id === id)).catch(() => undefined);\n const { result: raw, handed } = await runWithJob(\n run,\n PROMO_CONNECTOR,\n PRODUCE_SUBMIT_ACTION,\n buildPromoRunParams(input.request),\n job,\n );\n const handle = parseSubmitResult(raw);\n if (!handle) throw new Error('No production handle returned');\n patchTask(id, {\n state: 'running',\n handle,\n startedAt: Date.now(),\n lastLine: 'Queued',\n ...(handed ? { agentReports: true } : {}),\n });\n if (!pollers.has(id)) {\n const job = pollTask(run, id).finally(() => pollers.delete(id));\n pollers.set(id, job);\n }\n } catch (err: unknown) {\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: err instanceof Error ? err.message : String(err),\n lastLine: 'Submit failed',\n });\n }\n return tasks.find((t) => t.id === id)!;\n}\n\n/** Resume any incomplete tasks after app open (promo productions and video exports). */\n/**\n * Other task kinds resume themselves through this registry instead of being\n * imported here: `videoEditor/exportTask` imports this module, so importing it\n * back made a require cycle that can hand either side an undefined export.\n */\nconst taskResumers = new Set<(run: RunMediaAction) => void>();\n\nexport function registerTaskResumer(resume: (run: RunMediaAction) => void): void {\n taskResumers.add(resume);\n}\n\nexport function resumePromoTasks(run: RunMediaAction) {\n void hydrateCanvasTasks().then(() => {\n taskResumers.forEach((resume) => resume(run));\n for (const task of tasks) {\n if (task.kind !== 'promo') continue;\n if ((task.state === 'running' || task.state === 'submitting') && task.handle && !pollers.has(task.id)) {\n const job = pollTask(run, task.id).finally(() => pollers.delete(task.id));\n pollers.set(task.id, job);\n }\n }\n });\n}\n"],"names":["job"],"mappings":"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"}
1
+ {"version":3,"file":"canvasTasks.js","sources":["../../../src/features/canvas/canvasTasks.ts"],"sourcesContent":["/**\n * Background canvas tasks — native twin of canvas-surface `tasks/taskStore` + `promoTask`.\n * Promo productions outlive the generate sheet; More → Tasks shows progress.\n */\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport {\n PRODUCE_STATUS_ACTION,\n PRODUCE_SUBMIT_ACTION,\n PROMO_CONNECTOR,\n PROMO_POLL_EVERY_MS,\n buildPromoRunParams,\n promoPollMaxMs,\n promoRunTimeoutMs,\n parsePollResult,\n parseSubmitResult,\n type PromoRunOptions,\n type PromoRunResult,\n type PromoSubmitHandle,\n} from './promoVideo';\nimport type { RunMediaAction } from './videoEditor/mediaActions';\nimport type { RenderHandle, RenderPoll } from './videoEditor/renderTimeline';\n// Cycle by design: exportTask drives tasks through this store's public API.\nimport {\n PROMO_FOLLOW_SLACK_MS,\n awaitAgentVerdict,\n canvasJobKey,\n forgetServerJob,\n jobDeadlineAt,\n lookupRemoteJobId,\n promoVideoFromVerdict,\n registerPromoJob,\n runWithJob,\n serverJobId,\n serverProgressLine,\n} from './serverTasks';\n\nexport type TaskState = 'submitting' | 'running' | 'succeeded' | 'failed';\n\n/**\n * 'promo' - marketing production (PRODUCE_SUBMIT/STATUS): `handle` + `request`.\n * 'export' - the video editor's detached timeline render (videoEditor/exportTask,\n * RENDER_TIMELINE_SUBMIT/STATUS): `render`, `step`, `notice`,\n * `warnings`, `local`, and `result.url` = the finished mp4. Its\n * `request` is a descriptive stub (preset 'export') - never\n * resubmit it as a promo.\n * 'generate' - one prompt-to-media generation (image/video/audio) run as a\n * server job (./generationTasks runTrackedGeneration): `media`,\n * `input` (the call as sent, for a retry) and `result.url`. Its\n * `request` is a descriptive stub (preset 'generate').\n */\nexport type CanvasTaskKind = 'promo' | 'export' | 'generate';\n\n/** What a 'generate' task produced. */\nexport type GenerationMedia = 'image' | 'video' | 'audio';\n\n/** The connector call a 'generate' task ran - what \"Run again\" re-sends. */\nexport interface GenerationTaskInput {\n prompt: string;\n connector: string;\n action: string;\n params: Record<string, unknown>;\n model?: string;\n aspectRatio?: string;\n references?: string[];\n}\n\nexport interface CanvasTask {\n id: string;\n kind: CanvasTaskKind;\n title: string;\n brief: string;\n boardId: string;\n state: TaskState;\n createdAt: number;\n startedAt?: number;\n endedAt?: number;\n handle?: PromoSubmitHandle;\n lastLine?: string;\n request: PromoRunOptions;\n result?: PromoRunResult;\n error?: string;\n delivered?: boolean;\n /** Past this a task still running has stopped responding (its budget + the follow slack + grace). */\n deadlineAt?: number;\n /** The SUBMIT carried the server job: the agent follows the run and reports to its row (./serverTasks). */\n agentReports?: boolean;\n /** Who gave the terminal state, when it came from the server row. */\n verdictBy?: 'agent' | 'browser' | 'deadline';\n // ── kind 'export' only (optional; promo tasks never carry them) ──\n /** The detached render's handle (sandbox/run ids, output url, projected time, lease). */\n render?: RenderHandle;\n /** Latest render progress from STATUS. */\n step?: RenderPoll['step'];\n /** The connector's word on the render time limit, shown to the person. */\n notice?: string;\n /** Compile warnings (a transition that overlaps footage, ...). */\n warnings?: string[];\n /** Rendering through the in-app client chain (SUBMIT unavailable): dies with the app. */\n local?: boolean;\n // ── kind 'generate' only ──\n /** The media the generation makes. */\n media?: GenerationMedia;\n /** The call as sent. */\n input?: GenerationTaskInput;\n}\n\nconst STORAGE_KEY = 'canvas.tasks.v1';\nconst MAX_FINISHED = 20;\nconst listeners = new Set<() => void>();\nlet tasks: CanvasTask[] = [];\nlet hydrated = false;\nconst pollers = new Map<string, Promise<void>>();\n\nexport const isTerminal = (state: TaskState): boolean => state === 'succeeded' || state === 'failed';\n\nfunction emit() {\n listeners.forEach((l) => l());\n}\n\nfunction persist() {\n void AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(tasks)).catch(() => undefined);\n}\n\nexport function coerceTask(value: unknown): CanvasTask | null {\n if (!value || typeof value !== 'object') return null;\n const t = value as Record<string, unknown>;\n if (typeof t.id !== 'string' || !t.id || (t.kind !== 'promo' && t.kind !== 'export' && t.kind !== 'generate')) {\n return null;\n }\n if (typeof t.state !== 'string') return null;\n if (!['submitting', 'running', 'succeeded', 'failed'].includes(t.state)) return null;\n if (!t.request || typeof t.request !== 'object' || typeof t.boardId !== 'string') return null;\n return {\n ...(t as unknown as CanvasTask),\n title:\n typeof t.title === 'string'\n ? t.title\n : t.kind === 'export'\n ? 'Video export'\n : t.kind === 'generate'\n ? 'Generation'\n : 'Marketing video',\n brief: typeof t.brief === 'string' ? t.brief : '',\n createdAt: typeof t.createdAt === 'number' ? t.createdAt : 0,\n };\n}\n\nexport async function hydrateCanvasTasks(): Promise<void> {\n if (hydrated) return;\n hydrated = true;\n try {\n const raw = await AsyncStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const parsed = JSON.parse(raw);\n tasks = Array.isArray(parsed) ? parsed.map(coerceTask).filter((t): t is CanvasTask => t !== null) : [];\n emit();\n } catch {\n tasks = [];\n }\n}\n\nexport function getCanvasTask(id: string): CanvasTask | undefined {\n return tasks.find((t) => t.id === id);\n}\n\n/** Patch one task (no-op for an unknown id) - used by the export runner. */\nexport function patchCanvasTask(id: string, patch: Partial<CanvasTask>) {\n if (!tasks.some((t) => t.id === id)) return;\n patchTask(id, patch);\n}\n\n/** Register a new task (newest first) - used by the export runner. */\nexport function addCanvasTask(task: CanvasTask) {\n tasks = [task, ...tasks.filter((t) => t.id !== task.id)];\n persist();\n emit();\n}\n\nexport function listCanvasTasks(): CanvasTask[] {\n return tasks;\n}\n\nexport function subscribeCanvasTasks(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function runningTaskCount(): number {\n return tasks.filter((t) => t.state === 'submitting' || t.state === 'running').length;\n}\n\nfunction pruneFinished(list: CanvasTask[]): CanvasTask[] {\n const finished = list.filter((t) => isTerminal(t.state)).sort((a, b) => b.createdAt - a.createdAt);\n const keep = new Set(finished.slice(0, MAX_FINISHED).map((t) => t.id));\n return list.filter((t) => !isTerminal(t.state) || keep.has(t.id));\n}\n\nfunction patchTask(id: string, patch: Partial<CanvasTask>) {\n tasks = pruneFinished(tasks.map((t) => (t.id === id ? { ...t, ...patch } : t)));\n persist();\n emit();\n}\n\nexport function dismissTask(id: string) {\n tasks = tasks.filter((t) => t.id !== id);\n persist();\n emit();\n}\n\nexport function markTaskDelivered(id: string) {\n patchTask(id, { delivered: true });\n}\n\n/** A patch from the task's server row (./canvasTaskSync reconcile). No-op for an unknown id. */\nexport function applyServerPatch(id: string, patch: Partial<CanvasTask>) {\n if (!tasks.some((t) => t.id === id)) return;\n patchTask(id, patch);\n}\n\nlet seq = 0;\nconst newId = () => `task-${Date.now().toString(36)}-${(seq++).toString(36)}`;\n\n/**\n * Wait on the agent's verdict for a run it was handed, instead of polling\n * STATUS beside it (a promo sandbox dies on the first terminal answer, so two\n * pollers race). True when the row settled the task; false to poll as before.\n */\nasync function awaitAgentFor(id: string): Promise<boolean> {\n const task = tasks.find((t) => t.id === id);\n if (!task?.agentReports) return false;\n // After a restart the token is gone (memory only) but the row is not: find it in the listing.\n const remoteId = serverJobId(canvasJobKey(id)) ?? (await lookupRemoteJobId(id).catch(() => undefined));\n if (!remoteId) return false;\n try {\n const verdict = await awaitAgentVerdict(remoteId, {\n submittedAt: task.startedAt ?? task.createdAt,\n deadlineAt: task.deadlineAt ?? Date.now() + promoPollMaxMs(task.request),\n onProgress: (row) => {\n const line = serverProgressLine(row);\n if (line) patchTask(id, { state: 'running', lastLine: line });\n },\n });\n if (!verdict) {\n patchTask(id, { agentReports: false });\n return false;\n }\n const video = verdict.state === 'succeeded' ? promoVideoFromVerdict(verdict) : undefined;\n patchTask(id, {\n ...(video\n ? {\n state: 'succeeded' as const,\n result: {\n url: video.url,\n title: video.title || 'Marketing video',\n projectId: task.handle?.projectId ?? '',\n preset: task.request.preset,\n pipeline: '',\n },\n lastLine: 'Ready',\n }\n : {\n state: 'failed' as const,\n error:\n verdict.error ||\n (verdict.state === 'succeeded'\n ? 'Production finished but returned no video'\n : 'Production failed'),\n }),\n endedAt: verdict.endedAt ?? Date.now(),\n ...(verdict.verdictBy ? { verdictBy: verdict.verdictBy } : {}),\n });\n forgetServerJob(canvasJobKey(id));\n return true;\n } catch (err: unknown) {\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: err instanceof Error ? err.message : String(err),\n });\n return true;\n }\n}\n\nasync function pollTask(run: RunMediaAction, id: string) {\n if (await awaitAgentFor(id)) return;\n const started = Date.now();\n // A studio production runs ~100 min; its wait has to outlast that.\n const request = tasks.find((t) => t.id === id)?.request;\n const pollMax = request ? promoPollMaxMs(request) : promoPollMaxMs({ preset: '' });\n while (Date.now() - started < pollMax) {\n const task = tasks.find((t) => t.id === id);\n if (!task?.handle) return;\n try {\n const raw = await run(PROMO_CONNECTOR, PRODUCE_STATUS_ACTION, {\n projectId: task.handle.projectId,\n sandboxId: task.handle.sandboxId,\n });\n const poll = parsePollResult(raw);\n if (poll.state === 'succeeded' && poll.result) {\n patchTask(id, {\n state: 'succeeded',\n endedAt: Date.now(),\n result: poll.result,\n lastLine: poll.progress.at(-1) || 'Done',\n });\n return;\n }\n if (poll.state === 'failed') {\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: poll.error || 'Production failed',\n lastLine: poll.error || 'Failed',\n });\n return;\n }\n patchTask(id, {\n state: 'running',\n lastLine: poll.progress.at(-1) || 'Working…',\n });\n } catch (err: unknown) {\n patchTask(id, {\n lastLine: err instanceof Error ? err.message : 'Poll error — retrying',\n });\n }\n await new Promise((r) => setTimeout(r, PROMO_POLL_EVERY_MS));\n }\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: 'Timed out waiting for the marketing video',\n });\n}\n\n/** Submit promo and poll in the background (does not block the UI). */\nexport async function startPromoTask(\n run: RunMediaAction,\n input: { request: PromoRunOptions; boardId: string; brief: string },\n): Promise<CanvasTask> {\n await hydrateCanvasTasks();\n const id = newId();\n const createdAt = Date.now();\n const task: CanvasTask = {\n id,\n kind: 'promo',\n title: 'Marketing video',\n brief: input.brief,\n boardId: input.boardId,\n state: 'submitting',\n createdAt,\n // The run's own budget, the follow's slack past it, then the grace.\n deadlineAt: jobDeadlineAt(createdAt, promoRunTimeoutMs(input.request) + PROMO_FOLLOW_SLACK_MS),\n request: input.request,\n lastLine: 'Submitting…',\n };\n tasks = [task, ...tasks];\n persist();\n emit();\n\n try {\n // Recorded before the submit (two seconds at most), so the SUBMIT can hand the agent the job.\n const job = await registerPromoJob(task, () => tasks.some((t) => t.id === id)).catch(() => undefined);\n const { result: raw, handed } = await runWithJob(\n run,\n PROMO_CONNECTOR,\n PRODUCE_SUBMIT_ACTION,\n buildPromoRunParams(input.request),\n job,\n );\n const handle = parseSubmitResult(raw);\n if (!handle) throw new Error('No production handle returned');\n patchTask(id, {\n state: 'running',\n handle,\n startedAt: Date.now(),\n lastLine: 'Queued',\n ...(handed ? { agentReports: true } : {}),\n });\n if (!pollers.has(id)) {\n const job = pollTask(run, id).finally(() => pollers.delete(id));\n pollers.set(id, job);\n }\n } catch (err: unknown) {\n patchTask(id, {\n state: 'failed',\n endedAt: Date.now(),\n error: err instanceof Error ? err.message : String(err),\n lastLine: 'Submit failed',\n });\n }\n return tasks.find((t) => t.id === id)!;\n}\n\n/** Resume any incomplete tasks after app open (promo productions and video exports). */\n/**\n * Other task kinds resume themselves through this registry instead of being\n * imported here: `videoEditor/exportTask` imports this module, so importing it\n * back made a require cycle that can hand either side an undefined export.\n */\nconst taskResumers = new Set<(run: RunMediaAction) => void>();\n\n/** Generations this process is running right now (./generationTasks marks them). */\nconst liveGenerations = new Set<string>();\n\nexport function markGenerationLive(id: string, live: boolean): void {\n if (live) liveGenerations.add(id);\n else liveGenerations.delete(id);\n}\n\n/**\n * A generation is one request held open by this process: after a relaunch it\n * is gone. One the agent was handed settles from its server row\n * (./canvasTaskSync reconcile); any other fails with a reason, not a spinner.\n */\nfunction settleOrphanedGenerations(): void {\n for (const task of tasks) {\n if (task.kind !== 'generate' || isTerminal(task.state) || liveGenerations.has(task.id)) continue;\n if (task.agentReports) continue;\n patchTask(task.id, {\n state: 'failed',\n endedAt: Date.now(),\n error: 'The app closed before the generation finished - generate again.',\n lastLine: 'Interrupted',\n });\n }\n}\n\nexport function registerTaskResumer(resume: (run: RunMediaAction) => void): void {\n taskResumers.add(resume);\n}\n\nexport function resumePromoTasks(run: RunMediaAction) {\n void hydrateCanvasTasks().then(() => {\n taskResumers.forEach((resume) => resume(run));\n settleOrphanedGenerations();\n for (const task of tasks) {\n if (task.kind !== 'promo') continue;\n if ((task.state === 'running' || task.state === 'submitting') && task.handle && !pollers.has(task.id)) {\n const job = pollTask(run, task.id).finally(() => pollers.delete(task.id));\n pollers.set(task.id, job);\n }\n }\n });\n}\n"],"names":["job"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {jsx,Fragment}from'react/jsx-runtime';import {MaterialCommunityIcons}from'@expo/vector-icons';import {createContext,useContext,useState,useEffect,useMemo,useCallback}from'react';import {StyleSheet,useColorScheme,Pressable}from'react-native';var _a;
1
+ import {jsx,Fragment}from'react/jsx-runtime';import {MaterialCommunityIcons}from'@expo/vector-icons';import {useContext,createContext,useState,useEffect,useMemo,useCallback}from'react';import {useColorScheme,Pressable,StyleSheet}from'react-native';var _a;
2
2
  const CANVAS_THEME_STORAGE_KEY = "canvas.theme";
3
3
  const rgba = (rgb) => (alpha) => `rgba(${rgb},${alpha})`;
4
4
  const CANVAS_LIGHT = {
@@ -173,6 +173,7 @@ function osMode(scheme) {
173
173
  }
174
174
  function CanvasThemeProvider({
175
175
  mode,
176
+ palette,
176
177
  children
177
178
  }) {
178
179
  const parent = useContext(CanvasThemeContext);
@@ -187,13 +188,13 @@ function CanvasThemeProvider({
187
188
  listeners.delete(listener);
188
189
  };
189
190
  }, []);
190
- const resolved = preference !== "system" ? preference : mode != null ? mode : osMode(scheme);
191
+ const resolved = parent && mode == null ? parent.palette.mode : preference !== "system" ? preference : mode != null ? mode : osMode(scheme);
191
192
  const value = useMemo(() => ({
192
- palette: canvasPalette(resolved),
193
+ palette: (palette != null ? palette : canvasPalette)(resolved),
193
194
  preference,
194
195
  setPreference: setCanvasThemePreference
195
- }), [resolved, preference]);
196
- if (parent && mode == null) return /* @__PURE__ */ jsx(Fragment, { children });
196
+ }), [resolved, preference, palette]);
197
+ if (parent && mode == null && !palette) return /* @__PURE__ */ jsx(Fragment, { children });
197
198
  return /* @__PURE__ */ jsx(CanvasThemeContext.Provider, { value, children });
198
199
  }
199
200
  function useCanvasTheme() {
@@ -210,43 +211,28 @@ function useCanvasThemeControls() {
210
211
  setPreference: setCanvasThemePreference
211
212
  };
212
213
  }
213
- const NEXT_PREFERENCE = {
214
- system: "light",
215
- light: "dark",
216
- dark: "system"
217
- };
218
- const PREFERENCE_ICON = {
219
- system: "theme-light-dark",
220
- light: "weather-sunny",
221
- dark: "weather-night"
222
- };
223
- const PREFERENCE_LABEL = {
224
- system: "Theme: follows system",
225
- light: "Theme: light",
226
- dark: "Theme: dark"
227
- };
228
214
  function CanvasThemeToggle({
229
215
  style,
230
216
  size = 18
231
217
  }) {
232
218
  const {
233
219
  palette,
234
- preference,
235
220
  setPreference
236
221
  } = useCanvasThemeControls();
237
- const onPress = useCallback(() => setPreference(NEXT_PREFERENCE[preference]), [preference, setPreference]);
222
+ const next = palette.isDark ? "light" : "dark";
223
+ const onPress = useCallback(() => setPreference(next), [next, setPreference]);
238
224
  return /* @__PURE__ */ jsx(
239
225
  Pressable,
240
226
  {
241
227
  onPress,
242
228
  hitSlop: 8,
243
229
  accessibilityRole: "button",
244
- accessibilityLabel: `${PREFERENCE_LABEL[preference]}. Tap to change.`,
230
+ accessibilityLabel: next === "dark" ? "Switch to dark mode" : "Switch to light mode",
245
231
  style: StyleSheet.flatten([toggleStyles.button, {
246
232
  backgroundColor: palette.surface,
247
233
  borderColor: palette.border
248
234
  }, style]),
249
- children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: PREFERENCE_ICON[preference], size, color: palette.foreground })
235
+ children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: next === "dark" ? "weather-night" : "weather-sunny", size, color: palette.foreground })
250
236
  }
251
237
  );
252
238
  }