@adminide-stack/yantra-mobile 12.0.129-alpha.0 → 12.0.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/compute.js +57 -1
- package/lib/compute.js.map +1 -1
- package/lib/features/agent-chat/NativeAgentChat.js +3 -2
- package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +10 -0
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/apps/mobileAppCatalog.js +11 -0
- package/lib/features/apps/mobileAppCatalog.js.map +1 -1
- package/lib/features/canvas/AudioEditorExperience.js +448 -105
- package/lib/features/canvas/AudioEditorExperience.js.map +1 -1
- package/lib/features/canvas/CanvasAgentChatPane.js +33 -14
- package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
- package/lib/features/canvas/CanvasBoardsGrid.js +493 -41
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasChatResultCard.js.map +1 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js +37 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +237 -22
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/CanvasGeneratePanel.js +119 -26
- package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
- package/lib/features/canvas/CanvasLooksPanel.js +17 -6
- package/lib/features/canvas/CanvasLooksPanel.js.map +1 -1
- package/lib/features/canvas/CanvasTasksPanel.js +18 -1
- package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
- package/lib/features/canvas/DesignCategoryGallery.js +423 -0
- package/lib/features/canvas/DesignCategoryGallery.js.map +1 -0
- package/lib/features/canvas/ImageEditorExperience.js +763 -187
- package/lib/features/canvas/ImageEditorExperience.js.map +1 -1
- package/lib/features/canvas/SetStudioExperience.js +199 -11
- package/lib/features/canvas/SetStudioExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditorExperience.js +59 -40
- package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
- package/lib/features/canvas/VideoGeneratorExperience.js +134 -34
- package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
- package/lib/features/canvas/aiEdit.js +4 -2
- package/lib/features/canvas/aiEdit.js.map +1 -1
- package/lib/features/canvas/audioEditor/AudioWaveform.js +96 -0
- package/lib/features/canvas/audioEditor/AudioWaveform.js.map +1 -0
- package/lib/features/canvas/audioEditor/audioPeaks.js +93 -0
- package/lib/features/canvas/audioEditor/audioPeaks.js.map +1 -0
- package/lib/features/canvas/canvasTaskSync.js +34 -7
- package/lib/features/canvas/canvasTaskSync.js.map +1 -1
- package/lib/features/canvas/canvasTasks.js +23 -3
- package/lib/features/canvas/canvasTasks.js.map +1 -1
- package/lib/features/canvas/canvasTheme.js +10 -24
- package/lib/features/canvas/canvasTheme.js.map +1 -1
- package/lib/features/canvas/canvasUi.js +1 -1
- package/lib/features/canvas/canvasUi.js.map +1 -1
- package/lib/features/canvas/createTiles.js +17 -9
- package/lib/features/canvas/createTiles.js.map +1 -1
- package/lib/features/canvas/deepLinks.js +35 -5
- package/lib/features/canvas/deepLinks.js.map +1 -1
- package/lib/features/canvas/designCatalog.js +165 -0
- package/lib/features/canvas/designCatalog.js.map +1 -0
- package/lib/features/canvas/designCategories.js +262 -0
- package/lib/features/canvas/designCategories.js.map +1 -0
- package/lib/features/canvas/editorControls.js +406 -0
- package/lib/features/canvas/editorControls.js.map +1 -0
- package/lib/features/canvas/generationModels.js +5 -3
- package/lib/features/canvas/generationModels.js.map +1 -1
- package/lib/features/canvas/generationTasks.js +162 -0
- package/lib/features/canvas/generationTasks.js.map +1 -0
- package/lib/features/canvas/generator/BottomSheet.js +167 -0
- package/lib/features/canvas/generator/BottomSheet.js.map +1 -0
- package/lib/features/canvas/generator/BusinessCardChatCard.js +155 -0
- package/lib/features/canvas/generator/BusinessCardChatCard.js.map +1 -0
- package/lib/features/canvas/generator/DirectorSheet.js +163 -0
- package/lib/features/canvas/generator/DirectorSheet.js.map +1 -0
- package/lib/features/canvas/generator/ReframePreview.js +122 -0
- package/lib/features/canvas/generator/ReframePreview.js.map +1 -0
- package/lib/features/canvas/generator/RunLogCard.js +119 -0
- package/lib/features/canvas/generator/RunLogCard.js.map +1 -0
- package/lib/features/canvas/generator/ShotPanel.js +261 -0
- package/lib/features/canvas/generator/ShotPanel.js.map +1 -0
- package/lib/features/canvas/generator/businessCardWidget.js +117 -0
- package/lib/features/canvas/generator/businessCardWidget.js.map +1 -0
- package/lib/features/canvas/generator/cameraVocabulary.js +142 -0
- package/lib/features/canvas/generator/cameraVocabulary.js.map +1 -0
- package/lib/features/canvas/generator/cinematicVocabulary.js +416 -0
- package/lib/features/canvas/generator/cinematicVocabulary.js.map +1 -0
- package/lib/features/canvas/generator/direction.js +41 -0
- package/lib/features/canvas/generator/direction.js.map +1 -0
- package/lib/features/canvas/generator/reframeGeometry.js +108 -0
- package/lib/features/canvas/generator/reframeGeometry.js.map +1 -0
- package/lib/features/canvas/generator/runLog.js +71 -0
- package/lib/features/canvas/generator/runLog.js.map +1 -0
- package/lib/features/canvas/generator/shot.js +133 -0
- package/lib/features/canvas/generator/shot.js.map +1 -0
- package/lib/features/canvas/generator/useShotSpec.js +87 -0
- package/lib/features/canvas/generator/useShotSpec.js.map +1 -0
- package/lib/features/canvas/home/HeroComposer.js +214 -0
- package/lib/features/canvas/home/HeroComposer.js.map +1 -0
- package/lib/features/canvas/home/HeroMonitor.js +225 -0
- package/lib/features/canvas/home/HeroMonitor.js.map +1 -0
- package/lib/features/canvas/home/LookDetail.js +185 -0
- package/lib/features/canvas/home/LookDetail.js.map +1 -0
- package/lib/features/canvas/home/LoopingVideo.js +37 -0
- package/lib/features/canvas/home/LoopingVideo.js.map +1 -0
- package/lib/features/canvas/home/TemplatesGallery.js +253 -0
- package/lib/features/canvas/home/TemplatesGallery.js.map +1 -0
- package/lib/features/canvas/home/heroShots.js +100 -0
- package/lib/features/canvas/home/heroShots.js.map +1 -0
- package/lib/features/canvas/homeWork.js +62 -3
- package/lib/features/canvas/homeWork.js.map +1 -1
- package/lib/features/canvas/imageEditor/ImageMarkup.js +195 -0
- package/lib/features/canvas/imageEditor/ImageMarkup.js.map +1 -0
- package/lib/features/canvas/imageEditor/imageEditOps.js +367 -0
- package/lib/features/canvas/imageEditor/imageEditOps.js.map +1 -0
- package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
- package/lib/features/canvas/rankedCatalogSearch.js +375 -0
- package/lib/features/canvas/rankedCatalogSearch.js.map +1 -0
- package/lib/features/canvas/recorder/CameraRecorderExperience.js +68 -20
- package/lib/features/canvas/recorder/CameraRecorderExperience.js.map +1 -1
- package/lib/features/canvas/recorder/RecordingReview.js +272 -0
- package/lib/features/canvas/recorder/RecordingReview.js.map +1 -0
- package/lib/features/canvas/recorder/RecordingsList.js +179 -0
- package/lib/features/canvas/recorder/RecordingsList.js.map +1 -0
- package/lib/features/canvas/recorder/recorderOps.js +99 -0
- package/lib/features/canvas/recorder/recorderOps.js.map +1 -0
- package/lib/features/canvas/seedanceShowcase.js +314 -0
- package/lib/features/canvas/seedanceShowcase.js.map +1 -0
- package/lib/features/canvas/serverTasks.js +149 -15
- package/lib/features/canvas/serverTasks.js.map +1 -1
- package/lib/features/canvas/sessionRenewal.js +114 -0
- package/lib/features/canvas/sessionRenewal.js.map +1 -0
- package/lib/features/canvas/set/SetViewportWebView.js +34 -1
- package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
- package/lib/features/canvas/set/agent/setTurn.js +4 -2
- package/lib/features/canvas/set/agent/setTurn.js.map +1 -1
- package/lib/features/canvas/set/setPresets.js +85 -0
- package/lib/features/canvas/set/setPresets.js.map +1 -0
- package/lib/features/canvas/set/setProject.js +4 -1
- package/lib/features/canvas/set/setProject.js.map +1 -1
- package/lib/features/canvas/studioCatalog.js +59 -4
- package/lib/features/canvas/studioCatalog.js.map +1 -1
- package/lib/features/canvas/studioLooks.js +31 -4
- package/lib/features/canvas/studioLooks.js.map +1 -1
- package/lib/features/canvas/surfaceIndex.js +1 -14
- package/lib/features/canvas/surfaceIndex.js.map +1 -1
- package/lib/features/canvas/templateSearch.js +489 -0
- package/lib/features/canvas/templateSearch.js.map +1 -0
- package/lib/features/canvas/useCanvasSession.js +28 -6
- package/lib/features/canvas/useCanvasSession.js.map +1 -1
- package/lib/features/canvas/useStudioCatalogTemplates.js +41 -5
- package/lib/features/canvas/useStudioCatalogTemplates.js.map +1 -1
- package/lib/features/canvas/videoEditor/EditorPanels.js +531 -0
- package/lib/features/canvas/videoEditor/EditorPanels.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +48 -4
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/agentLoop.js +2 -0
- package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/brainClient.js +97 -27
- package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/cutTools.js +707 -3
- package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
- package/lib/features/canvas/videoEditor/audioServices.js +165 -0
- package/lib/features/canvas/videoEditor/audioServices.js.map +1 -0
- package/lib/features/canvas/videoEditor/captions.js +144 -0
- package/lib/features/canvas/videoEditor/captions.js.map +1 -0
- package/lib/features/canvas/videoEditor/compileTimeline.js +24 -16
- package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -1
- package/lib/features/canvas/videoEditor/editorModel.js +12 -2
- package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportTask.js +89 -7
- package/lib/features/canvas/videoEditor/exportTask.js.map +1 -1
- package/lib/features/canvas/videoEditor/layers.js +117 -0
- package/lib/features/canvas/videoEditor/layers.js.map +1 -0
- package/lib/features/canvas/videoEditor/remoteMediaClient.js +45 -18
- package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/renderTimeline.js +18 -6
- package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -1
- package/lib/features/canvas/videoEditor/revoice.js +138 -0
- package/lib/features/canvas/videoEditor/revoice.js.map +1 -0
- package/lib/features/canvas/videoEditor/storageUpload.js +34 -0
- package/lib/features/canvas/videoEditor/storageUpload.js.map +1 -0
- package/lib/features/canvas/videoEditor/textMotion.js +109 -0
- package/lib/features/canvas/videoEditor/textMotion.js.map +1 -0
- package/lib/features/canvas/videoEditor/transitions.js +31 -0
- package/lib/features/canvas/videoEditor/transitions.js.map +1 -0
- package/lib/features/chat/TemplatesChatCards.js +8 -3
- package/lib/features/chat/TemplatesChatCards.js.map +1 -1
- package/lib/features/design/DesignEditorExperience.js +674 -644
- package/lib/features/design/DesignEditorExperience.js.map +1 -1
- package/lib/features/design/DesignExperience.js +285 -538
- package/lib/features/design/DesignExperience.js.map +1 -1
- package/lib/features/design/designCore.js +2 -212
- package/lib/features/design/designCore.js.map +1 -1
- package/lib/features/design/designIndex.js +1 -50
- package/lib/features/design/designIndex.js.map +1 -1
- package/lib/features/design/doc/aiDesign.js +247 -0
- package/lib/features/design/doc/aiDesign.js.map +1 -0
- package/lib/features/design/doc/artifacts.js +280 -0
- package/lib/features/design/doc/artifacts.js.map +1 -0
- package/lib/features/design/doc/chart.js +98 -0
- package/lib/features/design/doc/chart.js.map +1 -0
- package/lib/features/design/doc/crop.js +104 -0
- package/lib/features/design/doc/crop.js.map +1 -0
- package/lib/features/design/doc/curve.js +49 -0
- package/lib/features/design/doc/curve.js.map +1 -0
- package/lib/features/design/doc/docOps.js +397 -0
- package/lib/features/design/doc/docOps.js.map +1 -0
- package/lib/features/design/doc/findReplace.js +112 -0
- package/lib/features/design/doc/findReplace.js.map +1 -0
- package/lib/features/design/doc/fonts.js +79 -0
- package/lib/features/design/doc/fonts.js.map +1 -0
- package/lib/features/design/doc/frames.js +17 -0
- package/lib/features/design/doc/frames.js.map +1 -0
- package/lib/features/design/doc/geometry.js +133 -0
- package/lib/features/design/doc/geometry.js.map +1 -0
- package/lib/features/design/doc/imageAdjust.js +203 -0
- package/lib/features/design/doc/imageAdjust.js.map +1 -0
- package/lib/features/design/doc/legacyDoc.js +107 -0
- package/lib/features/design/doc/legacyDoc.js.map +1 -0
- package/lib/features/design/doc/newDoc.js +335 -0
- package/lib/features/design/doc/newDoc.js.map +1 -0
- package/lib/features/design/doc/pageRange.js +17 -0
- package/lib/features/design/doc/pageRange.js.map +1 -0
- package/lib/features/design/doc/pathScale.js +68 -0
- package/lib/features/design/doc/pathScale.js.map +1 -0
- package/lib/features/design/doc/qr.js +62 -0
- package/lib/features/design/doc/qr.js.map +1 -0
- package/lib/features/design/doc/shapes.js +366 -0
- package/lib/features/design/doc/shapes.js.map +1 -0
- package/lib/features/design/doc/sizes.js +230 -0
- package/lib/features/design/doc/sizes.js.map +1 -0
- package/lib/features/design/doc/textEffects.js +134 -0
- package/lib/features/design/doc/textEffects.js.map +1 -0
- package/lib/features/design/doc/textLayout.js +182 -0
- package/lib/features/design/doc/textLayout.js.map +1 -0
- package/lib/features/design/doc/types.js +30 -0
- package/lib/features/design/doc/types.js.map +1 -0
- package/lib/features/design/editor/AiPanel.js +194 -0
- package/lib/features/design/editor/AiPanel.js.map +1 -0
- package/lib/features/design/editor/ChartDataPanel.js +182 -0
- package/lib/features/design/editor/ChartDataPanel.js.map +1 -0
- package/lib/features/design/editor/CropOverlay.js +199 -0
- package/lib/features/design/editor/CropOverlay.js.map +1 -0
- package/lib/features/design/editor/DesignCanvas.js +363 -0
- package/lib/features/design/editor/DesignCanvas.js.map +1 -0
- package/lib/features/design/editor/ExportSheet.js +123 -0
- package/lib/features/design/editor/ExportSheet.js.map +1 -0
- package/lib/features/design/editor/FindReplacePanel.js +93 -0
- package/lib/features/design/editor/FindReplacePanel.js.map +1 -0
- package/lib/features/design/editor/ImageTools.js +188 -0
- package/lib/features/design/editor/ImageTools.js.map +1 -0
- package/lib/features/design/editor/LayerTools.js +485 -0
- package/lib/features/design/editor/LayerTools.js.map +1 -0
- package/lib/features/design/editor/PageStrip.js +203 -0
- package/lib/features/design/editor/PageStrip.js.map +1 -0
- package/lib/features/design/editor/Slideshow.js +97 -0
- package/lib/features/design/editor/Slideshow.js.map +1 -0
- package/lib/features/design/editor/ToolPanels.js +695 -0
- package/lib/features/design/editor/ToolPanels.js.map +1 -0
- package/lib/features/design/editor/controls.js +630 -0
- package/lib/features/design/editor/controls.js.map +1 -0
- package/lib/features/design/editor/useDesignSave.js +91 -0
- package/lib/features/design/editor/useDesignSave.js.map +1 -0
- package/lib/features/design/export/exportDesign.js +170 -0
- package/lib/features/design/export/exportDesign.js.map +1 -0
- package/lib/features/design/export/pdf.js +143 -0
- package/lib/features/design/export/pdf.js.map +1 -0
- package/lib/features/design/home/DesignHome.js +688 -0
- package/lib/features/design/home/DesignHome.js.map +1 -0
- package/lib/features/design/home/studioHome.js +61 -0
- package/lib/features/design/home/studioHome.js.map +1 -0
- package/lib/features/design/pickDesignImage.js +60 -0
- package/lib/features/design/pickDesignImage.js.map +1 -0
- package/lib/features/design/render/DesignPageView.js +69 -0
- package/lib/features/design/render/DesignPageView.js.map +1 -0
- package/lib/features/design/render/PageCapture.js +288 -0
- package/lib/features/design/render/PageCapture.js.map +1 -0
- package/lib/features/design/render/TextMeasure.js +115 -0
- package/lib/features/design/render/TextMeasure.js.map +1 -0
- package/lib/features/design/render/fontRegistry.js +110 -0
- package/lib/features/design/render/fontRegistry.js.map +1 -0
- package/lib/features/design/render/layers.js +392 -0
- package/lib/features/design/render/layers.js.map +1 -0
- package/lib/features/design/render/svg.js +35 -0
- package/lib/features/design/render/svg.js.map +1 -0
- package/lib/features/design/render/svgParts.js +435 -0
- package/lib/features/design/render/svgParts.js.map +1 -0
- package/lib/features/design/surface/BoardScreen.js +529 -0
- package/lib/features/design/surface/BoardScreen.js.map +1 -0
- package/lib/features/design/surface/CompareView.js +138 -0
- package/lib/features/design/surface/CompareView.js.map +1 -0
- package/lib/features/design/surface/CreationScreen.js +294 -0
- package/lib/features/design/surface/CreationScreen.js.map +1 -0
- package/lib/features/design/surface/DesignAgentChatPane.js +444 -0
- package/lib/features/design/surface/DesignAgentChatPane.js.map +1 -0
- package/lib/features/design/surface/DesignBoards.js +441 -0
- package/lib/features/design/surface/DesignBoards.js.map +1 -0
- package/lib/features/design/surface/DesignPreview.js +159 -0
- package/lib/features/design/surface/DesignPreview.js.map +1 -0
- package/lib/features/design/surface/DesignSurfaceExperience.js +80 -0
- package/lib/features/design/surface/DesignSurfaceExperience.js.map +1 -0
- package/lib/features/design/surface/FullScreenPreview.js +59 -0
- package/lib/features/design/surface/FullScreenPreview.js.map +1 -0
- package/lib/features/design/surface/NewSystemDialog.js +122 -0
- package/lib/features/design/surface/NewSystemDialog.js.map +1 -0
- package/lib/features/design/surface/PickerSheet.js +175 -0
- package/lib/features/design/surface/PickerSheet.js.map +1 -0
- package/lib/features/design/surface/TemplatesGallery.js +156 -0
- package/lib/features/design/surface/TemplatesGallery.js.map +1 -0
- package/lib/features/design/surface/WetPaint.js +140 -0
- package/lib/features/design/surface/WetPaint.js.map +1 -0
- package/lib/features/design/surface/agentTurn.js +229 -0
- package/lib/features/design/surface/agentTurn.js.map +1 -0
- package/lib/features/design/surface/designBoard.js +218 -0
- package/lib/features/design/surface/designBoard.js.map +1 -0
- package/lib/features/design/surface/designChannel.js +186 -0
- package/lib/features/design/surface/designChannel.js.map +1 -0
- package/lib/features/design/surface/designChat.js +141 -0
- package/lib/features/design/surface/designChat.js.map +1 -0
- package/lib/features/design/surface/designConnector.js +266 -0
- package/lib/features/design/surface/designConnector.js.map +1 -0
- package/lib/features/design/surface/designDocument.js +40 -0
- package/lib/features/design/surface/designDocument.js.map +1 -0
- package/lib/features/design/surface/designExport.js +55 -0
- package/lib/features/design/surface/designExport.js.map +1 -0
- package/lib/features/design/surface/designLinks.js +64 -0
- package/lib/features/design/surface/designLinks.js.map +1 -0
- package/lib/features/design/surface/designPalette.js +24 -0
- package/lib/features/design/surface/designPalette.js.map +1 -0
- package/lib/features/design/surface/designRun.js +161 -0
- package/lib/features/design/surface/designRun.js.map +1 -0
- package/lib/features/design/surface/designTheme.js +119 -0
- package/lib/features/design/surface/designTheme.js.map +1 -0
- package/lib/features/design/surface/execStream.js +206 -0
- package/lib/features/design/surface/execStream.js.map +1 -0
- package/lib/features/design/surface/metaball.js +48 -0
- package/lib/features/design/surface/metaball.js.map +1 -0
- package/lib/features/design/surface/pickReferenceFiles.js +35 -0
- package/lib/features/design/surface/pickReferenceFiles.js.map +1 -0
- package/lib/features/design/surface/useDesignSurface.js +379 -0
- package/lib/features/design/surface/useDesignSurface.js.map +1 -0
- package/lib/features/docs/DocBlockRow.js +336 -0
- package/lib/features/docs/DocBlockRow.js.map +1 -0
- package/lib/features/docs/DocsEditorExperience.js +949 -0
- package/lib/features/docs/DocsEditorExperience.js.map +1 -0
- package/lib/features/docs/DocsToolbar.js +247 -0
- package/lib/features/docs/DocsToolbar.js.map +1 -0
- package/lib/features/docs/blocks.js +560 -0
- package/lib/features/docs/blocks.js.map +1 -0
- package/lib/features/docs/docArtifacts.js +129 -0
- package/lib/features/docs/docArtifacts.js.map +1 -0
- package/lib/features/docs/docEdits.js +201 -0
- package/lib/features/docs/docEdits.js.map +1 -0
- package/lib/features/docs/docExport.js +235 -0
- package/lib/features/docs/docExport.js.map +1 -0
- package/lib/features/docs/docShare.js +62 -0
- package/lib/features/docs/docShare.js.map +1 -0
- package/lib/features/links/openInApp.js +38 -2
- package/lib/features/links/openInApp.js.map +1 -1
- package/lib/routes.json +54 -0
- package/lib/screens/DesignNative/index.js +35 -0
- package/lib/screens/DesignNative/index.js.map +1 -0
- package/package.json +4 -4
- package/lib/features/design/exportDesign.js +0 -133
- 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: (
|
|
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: (
|
|
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: (
|
|
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
|
|
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")
|
|
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,
|
|
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
|
|
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:
|
|
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:
|
|
235
|
+
children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: next === "dark" ? "weather-night" : "weather-sunny", size, color: palette.foreground })
|
|
250
236
|
}
|
|
251
237
|
);
|
|
252
238
|
}
|