@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.
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SetViewportWebView.js","sources":["../../../../src/features/canvas/set/SetViewportWebView.tsx"],"sourcesContent":["/**\n * Three.js set viewport in a WebView — orbit + still capture for native Set studio.\n * Full desktop SetEditor gizmos stay on web; this ships the interactive viewport\n * and the set's objects (stock kit pieces, generated GLBs, image planes), kept\n * in step with the native SetProject through postMessage:\n *\n * objects the whole list - added, moved and removed objects diffed by id\n * addObject / moveObject / removeObject one object at a time\n * setCamera / setLight / frameObject / capture\n *\n * The page answers `ready`, `frame`, `loadError` and `objectError`.\n */\nimport React, { useEffect, useMemo, useRef } from 'react';\nimport { StyleSheet, View } from 'react-native';\nimport { DEFAULT_LIGHTING, MESH_TARGET_HEIGHT_M, type SetCamera, type SetLighting, type SetObject } from './setProject';\nimport { KIT_ENTRIES } from './supplyLibrary';\nimport { useWebViewRetention } from '../../../hooks/useWebViewRetention';\n\nfunction loadWebView(): React.ComponentType<Record<string, unknown>> | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require\n return require('react-native-webview').WebView as React.ComponentType<Record<string, unknown>>;\n } catch {\n return null;\n }\n}\n\nfunction esc(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<');\n}\n\n/** What the page needs of each kit entry: its parts and colour, by id. */\nconst KIT_FOR_PAGE = JSON.stringify(\n Object.fromEntries(KIT_ENTRIES.map((entry) => [entry.id, { parts: entry.parts, color: entry.color }])),\n).replace(/</g, '\\\\u003c');\n\n/** A message the page understands - pure, so the wire contract is testable. */\nexport type SetViewportMessage =\n | { type: 'capture' }\n | { type: 'setCamera'; camera: SetCamera }\n | { type: 'objects'; objects: SetObject[] }\n | { type: 'addObject'; object: SetObject }\n | { type: 'moveObject'; object: Pick<SetObject, 'id' | 'position' | 'rotation' | 'scale'> & { hidden?: boolean } }\n | { type: 'removeObject'; id: string }\n | { type: 'setLight'; lighting: SetLighting }\n | { type: 'frameObject'; id: string };\n\n/** The JS that delivers one message to the page's handler. */\nexport function viewportMessageScript(msg: SetViewportMessage): string {\n return `window.dispatchEvent(new MessageEvent('message',{data:${JSON.stringify(JSON.stringify(msg))}}));true;`;\n}\n\nfunction setViewportHtml(opts: { worldUrl?: string; meshOrImageUrl?: string; camera: SetCamera }): string {\n const world = opts.worldUrl ? esc(opts.worldUrl) : '';\n const prop = opts.meshOrImageUrl ? esc(opts.meshOrImageUrl) : '';\n const cam = opts.camera;\n return `<!DOCTYPE html><html><head>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no\">\n<style>html,body{margin:0;height:100%;background:#0b0b0e;overflow:hidden}canvas{display:block;width:100%;height:100%}</style>\n</head><body>\n<script type=\"importmap\">{\"imports\":{\"three\":\"https://unpkg.com/three@0.160.0/build/three.module.js\",\"three/addons/\":\"https://unpkg.com/three@0.160.0/examples/jsm/\"}}</script>\n<script type=\"module\">\nimport * as THREE from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\nconst worldUrl=${JSON.stringify(world)};\nconst propUrl=${JSON.stringify(prop)};\nconst KIT=${KIT_FOR_PAGE};\nconst MESH_H=${MESH_TARGET_HEIGHT_M};\nconst D2R=Math.PI/180;\nconst scene=new THREE.Scene();\nscene.background=new THREE.Color(0x1a1a1e);\nconst camera=new THREE.PerspectiveCamera(${cam.fov},1,0.05,200);\ncamera.position.set(${cam.position.x},${cam.position.y},${cam.position.z});\n/* preserveDrawingBuffer stays FALSE: it doubles the framebuffer and stops the\n driver discarding it after compositing. capture() re-renders synchronously\n immediately before toDataURL(), which reads valid pixels without it. */\nconst renderer=new THREE.WebGLRenderer({antialias:true,preserveDrawingBuffer:false});\nrenderer.setPixelRatio(Math.min(devicePixelRatio,2));\ndocument.body.appendChild(renderer.domElement);\nconst controls=new OrbitControls(camera,renderer.domElement);\ncontrols.target.set(${cam.target.x},${cam.target.y},${cam.target.z});\ncontrols.enableDamping=true;\nconst light=new THREE.DirectionalLight(0xffffff,1.1);\nlight.position.set(2,4,3);scene.add(light);\nconst ambient=new THREE.AmbientLight(0xffffff,0.45);scene.add(ambient);\nconst ground=new THREE.Mesh(new THREE.CircleGeometry(4,48),new THREE.MeshStandardMaterial({color:0x2a2a30,roughness:0.9}));\nground.rotation.x=-Math.PI/2;scene.add(ground);\nfunction fit(){const w=innerWidth,h=innerHeight;camera.aspect=w/Math.max(1,h);camera.updateProjectionMatrix();renderer.setSize(w,h,false);}\naddEventListener('resize',fit);fit();\nfunction post(type,payload){window.ReactNativeWebView&&window.ReactNativeWebView.postMessage(JSON.stringify({type,...payload}));}\n/* A generated model or world that will not load must say so, not draw nothing. */\nfunction failed(what){return ()=>post('loadError',{what});}\nif(worldUrl){new THREE.TextureLoader().load(worldUrl,tex=>{tex.mapping=THREE.EquirectangularReflectionMapping;scene.background=tex;scene.environment=tex;},undefined,failed('world'));}\nlet gltfLoader=null;\nfunction loadGlb(url,ok,bad){\n (gltfLoader?Promise.resolve(gltfLoader):import('three/addons/loaders/GLTFLoader.js').then(({GLTFLoader})=>(gltfLoader=new GLTFLoader())))\n .then(l=>l.load(url,ok,undefined,bad)).catch(bad);\n}\nif(propUrl){\n if(/\\\\.glb($|\\\\?)/i.test(propUrl)){\n loadGlb(propUrl,g=>{const root=g.scene;root.position.set(0,0,0);scene.add(root);},failed('object'));\n } else {\n new THREE.TextureLoader().load(propUrl,tex=>{\n const aspect=tex.image.width/Math.max(1,tex.image.height);\n const w=1.2,h=w/aspect;\n const mesh=new THREE.Mesh(new THREE.PlaneGeometry(w,h),new THREE.MeshBasicMaterial({map:tex,transparent:true}));\n mesh.position.set(0,h/2,0);scene.add(mesh);\n },undefined,failed('object'));\n }\n}\n/* ── The set's objects ─────────────────────────────────────────────────── */\nconst live=new Map();\nfunction partGeometry(p){\n switch(p.shape){\n case 'box':return new THREE.BoxGeometry(p.a,p.b??p.a,p.c??p.a);\n case 'sphere':return new THREE.SphereGeometry(p.a,24,16);\n case 'cylinder':return new THREE.CylinderGeometry(p.a,p.a,p.b??1,24);\n case 'cone':return new THREE.ConeGeometry(p.a,p.b??1,24);\n case 'torus':return new THREE.TorusGeometry(p.a,p.b??0.1,12,32);\n case 'capsule':return new THREE.CapsuleGeometry(p.a,p.b??0.5,6,12);\n case 'plane':{const g=new THREE.PlaneGeometry(p.a,p.b??p.a);g.rotateX(-Math.PI/2);g.translate(0,0.003,0);return g;}\n default:return new THREE.BoxGeometry(0.3,0.3,0.3);\n }\n}\nfunction placeholder(holder,why){\n const box=new THREE.Mesh(new THREE.BoxGeometry(0.4,0.4,0.4),new THREE.MeshBasicMaterial({color:0xd97b3f,wireframe:true}));\n box.position.y=0.2;holder.add(box);\n if(why)post('objectError',{id:holder.userData.id,why});\n}\nfunction buildKit(o,holder){\n const e=KIT[o.kitId];\n if(!e){placeholder(holder,'unknown kit '+o.kitId);return;}\n for(const p of e.parts){\n const m=new THREE.Mesh(partGeometry(p),new THREE.MeshStandardMaterial({color:p.color||o.color||e.color,roughness:0.8}));\n if(p.offset)m.position.set(p.offset[0],p.offset[1],p.offset[2]);\n if(p.rotate)m.rotation.set(p.rotate[0]*D2R,p.rotate[1]*D2R,p.rotate[2]*D2R);\n holder.add(m);\n }\n}\nfunction buildMesh(o,holder){\n if(!o.modelUrl){placeholder(holder,'no model');return;}\n loadGlb(o.modelUrl,g=>{\n const root=g.scene;\n const box=new THREE.Box3().setFromObject(root);const size=box.getSize(new THREE.Vector3());\n const k=size.y>0?MESH_H/size.y:1;root.scale.setScalar(k);\n const c=box.getCenter(new THREE.Vector3());root.position.set(-c.x*k,-box.min.y*k,-c.z*k);\n holder.add(root);\n },()=>{placeholder(holder,'the model would not load');post('loadError',{what:'object'});});\n}\nfunction buildImage(o,holder){\n if(!o.imageUrl){placeholder(holder,'no image');return;}\n new THREE.TextureLoader().load(o.imageUrl,tex=>{\n const w=o.imageWidthM||1,h=w*tex.image.height/Math.max(1,tex.image.width);\n const m=new THREE.Mesh(new THREE.PlaneGeometry(w,h),new THREE.MeshBasicMaterial({map:tex,transparent:true,side:THREE.DoubleSide}));\n m.position.y=h/2;holder.add(m);\n },undefined,()=>{placeholder(holder,'the image would not load');post('loadError',{what:'object'});});\n}\nconst sigOf=o=>[o.source,o.kitId||o.modelUrl||o.imageUrl||'',o.color||'',o.imageWidthM||''].join('|');\nfunction place(holder,o){\n if(o.position)holder.position.set(o.position.x,o.position.y,o.position.z);\n if(o.rotation)holder.rotation.set(o.rotation.x*D2R,o.rotation.y*D2R,o.rotation.z*D2R);\n if(o.scale)holder.scale.set(o.scale.x,o.scale.y,o.scale.z);\n if(typeof o.hidden==='boolean')holder.visible=!o.hidden;\n}\nfunction addObject(o){\n const prev=live.get(o.id);\n if(prev&&prev.sig===sigOf(o)){place(prev.holder,o);return;}\n if(prev)scene.remove(prev.holder);\n const holder=new THREE.Group();holder.userData.id=o.id;\n if(o.source==='kit')buildKit(o,holder);else if(o.source==='mesh')buildMesh(o,holder);else buildImage(o,holder);\n place(holder,o);scene.add(holder);live.set(o.id,{holder,sig:sigOf(o)});\n}\nfunction removeObject(id){const rec=live.get(id);if(rec){scene.remove(rec.holder);live.delete(id);}}\nfunction syncObjects(list){\n const keep=new Set(list.map(o=>o.id));\n for(const id of [...live.keys()])if(!keep.has(id))removeObject(id);\n list.forEach(addObject);\n}\nfunction setLight(l){\n const az=l.keyAzimuthDeg*D2R,el=l.keyElevationDeg*D2R;\n light.position.set(Math.sin(az)*Math.cos(el)*6,Math.sin(el)*6,Math.cos(az)*Math.cos(el)*6);\n light.intensity=l.keyIntensity*0.42;ambient.intensity=l.ambientIntensity*0.82;\n}\nfunction frameObject(id){\n const rec=live.get(id);if(!rec)return;\n const box=new THREE.Box3().setFromObject(rec.holder);if(box.isEmpty())return;\n const c=box.getCenter(new THREE.Vector3());const r=Math.max(0.15,box.getSize(new THREE.Vector3()).length()/2);\n const dir=camera.position.clone().sub(controls.target).normalize();\n controls.target.copy(c);camera.position.copy(c.clone().add(dir.multiplyScalar(r*3)));controls.update();\n}\nfunction tick(){controls.update();renderer.render(scene,camera);requestAnimationFrame(tick);}tick();\nfunction capture(){renderer.render(scene,camera);return renderer.domElement.toDataURL('image/jpeg',0.92);}\nfunction onMessage(ev){\n let msg={};try{msg=JSON.parse(ev.data);}catch(e){return;}\n if(msg.type==='capture'){post('frame',{dataUrl:capture()});}\n if(msg.type==='setCamera'&&msg.camera){\n const c=msg.camera;camera.position.set(c.position.x,c.position.y,c.position.z);\n if(c.fov){camera.fov=c.fov;camera.updateProjectionMatrix();}\n controls.target.set(c.target.x,c.target.y,c.target.z);controls.update();\n }\n if(msg.type==='objects'&&Array.isArray(msg.objects))syncObjects(msg.objects);\n if(msg.type==='addObject'&&msg.object)addObject(msg.object);\n if(msg.type==='moveObject'&&msg.object){const rec=live.get(msg.object.id);if(rec)place(rec.holder,msg.object);}\n if(msg.type==='removeObject'&&msg.id)removeObject(msg.id);\n if(msg.type==='setLight'&&msg.lighting)setLight(msg.lighting);\n if(msg.type==='frameObject'&&msg.id)frameObject(msg.id);\n}\naddEventListener('message',onMessage);\ndocument.addEventListener('message',onMessage);\npost('ready',{});\n</script></body></html>`;\n}\n\nexport interface SetViewportApi {\n capture: () => void;\n setCamera: (c: SetCamera) => void;\n addObject: (object: SetObject) => void;\n moveObject: (object: SetObject) => void;\n removeObject: (id: string) => void;\n syncObjects: (objects: SetObject[]) => void;\n setLight: (lighting: SetLighting) => void;\n frameObject: (id: string) => void;\n}\n\nexport function SetViewportWebView({\n worldUrl,\n propUrl,\n camera,\n objects,\n lighting,\n onFrame,\n onLoadError,\n webRef,\n}: {\n worldUrl?: string;\n propUrl?: string;\n camera: SetCamera;\n /** The set's objects; the page is kept in step with every change. */\n objects?: SetObject[];\n lighting?: SetLighting;\n onFrame?: (dataUrl: string) => void;\n /** The world backdrop or the 3D object failed to load in the viewport. */\n onLoadError?: (what: 'world' | 'object') => void;\n webRef?: React.MutableRefObject<SetViewportApi | null>;\n}) {\n const WebView = loadWebView();\n const ref = useRef<{ injectJavaScript?: (js: string) => void } | null>(null);\n // The page is built once per world/prop; later camera moves are messages, not reloads.\n const cameraRef = useRef(camera);\n cameraRef.current = camera;\n const objectsRef = useRef(objects);\n objectsRef.current = objects;\n const lightingRef = useRef(lighting);\n lightingRef.current = lighting;\n const html = useMemo(\n () => setViewportHtml({ worldUrl, meshOrImageUrl: propUrl, camera: cameraRef.current }),\n [worldUrl, propUrl],\n );\n /**\n * A live WebGL context with its own three.js runtime is the single most\n * expensive thing this app can hold. It rebuilds from `html` on return, so\n * release it once the viewport is off-screen or the app is backgrounded.\n */\n const shouldRender = useWebViewRetention({ releaseOnBlur: true });\n\n const send = (msg: SetViewportMessage) => ref.current?.injectJavaScript?.(viewportMessageScript(msg));\n\n if (webRef) {\n webRef.current = {\n capture: () => send({ type: 'capture' }),\n setCamera: (c) => send({ type: 'setCamera', camera: c }),\n addObject: (object) => send({ type: 'addObject', object }),\n moveObject: (object) =>\n send({\n type: 'moveObject',\n object: {\n id: object.id,\n position: object.position,\n rotation: object.rotation,\n scale: object.scale,\n hidden: Boolean(object.hidden),\n },\n }),\n removeObject: (id) => send({ type: 'removeObject', id }),\n syncObjects: (list) => send({ type: 'objects', objects: list }),\n setLight: (l) => send({ type: 'setLight', lighting: l }),\n frameObject: (id) => send({ type: 'frameObject', id }),\n };\n }\n\n useEffect(() => {\n if (objects) send({ type: 'objects', objects });\n }, [objects]);\n useEffect(() => {\n if (lighting) send({ type: 'setLight', lighting });\n }, [lighting]);\n const firstCamera = useRef(true);\n useEffect(() => {\n if (firstCamera.current) {\n firstCamera.current = false;\n return;\n }\n send({ type: 'setCamera', camera });\n }, [camera]);\n\n if (!WebView || !shouldRender) return <View style={styles.fallback} />;\n\n return (\n <WebView\n ref={(node: { injectJavaScript?: (js: string) => void } | null) => {\n ref.current = node;\n }}\n originWhitelist={['*']}\n source={{ html }}\n style={styles.view}\n onMessage={(event: { nativeEvent: { data: string } }) => {\n try {\n const msg = JSON.parse(event.nativeEvent.data) as {\n type?: string;\n dataUrl?: string;\n what?: string;\n };\n if (msg.type === 'frame' && msg.dataUrl) onFrame?.(msg.dataUrl);\n if (msg.type === 'loadError') onLoadError?.(msg.what === 'world' ? 'world' : 'object');\n if (msg.type === 'ready') {\n // A fresh page (first load, a new world, a return from the background) starts empty.\n send({ type: 'setLight', lighting: lightingRef.current ?? DEFAULT_LIGHTING });\n if (objectsRef.current?.length) send({ type: 'objects', objects: objectsRef.current });\n send({ type: 'setCamera', camera: cameraRef.current });\n }\n } catch {\n /* ignore */\n }\n }}\n allowFileAccess\n mixedContentMode=\"always\"\n />\n );\n}\n\nconst styles = StyleSheet.create({\n view: { flex: 1, backgroundColor: '#0B0B0E', minHeight: 220 },\n fallback: { flex: 1, minHeight: 220, backgroundColor: '#0B0B0E' },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SetViewportWebView.js","sources":["../../../../src/features/canvas/set/SetViewportWebView.tsx"],"sourcesContent":["/**\n * Three.js set viewport in a WebView - orbit + still capture for native Set studio.\n * Full desktop SetEditor gizmos stay on web; this ships the interactive viewport\n * and the set's objects (stock kit pieces, generated GLBs, image planes), kept\n * in step with the native SetProject through postMessage:\n *\n * objects the whole list - added, moved and removed objects diffed by id\n * addObject / moveObject / removeObject one object at a time\n * setCamera / setLight / setWorld / frameObject / capture\n *\n * The page answers `ready`, `frame`, `loadError` and `objectError`.\n */\nimport React, { useEffect, useMemo, useRef } from 'react';\nimport { StyleSheet, View } from 'react-native';\nimport { DEFAULT_LIGHTING, MESH_TARGET_HEIGHT_M, type SetCamera, type SetLighting, type SetObject } from './setProject';\nimport { KIT_ENTRIES } from './supplyLibrary';\nimport { useWebViewRetention } from '../../../hooks/useWebViewRetention';\n\nfunction loadWebView(): React.ComponentType<Record<string, unknown>> | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require\n return require('react-native-webview').WebView as React.ComponentType<Record<string, unknown>>;\n } catch {\n return null;\n }\n}\n\nfunction esc(value: string): string {\n return value.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<');\n}\n\n/** What the page needs of each kit entry: its parts and colour, by id. */\nconst KIT_FOR_PAGE = JSON.stringify(\n Object.fromEntries(KIT_ENTRIES.map((entry) => [entry.id, { parts: entry.parts, color: entry.color }])),\n).replace(/</g, '\\\\u003c');\n\n/** A message the page understands - pure, so the wire contract is testable. */\nexport type SetViewportMessage =\n | { type: 'capture' }\n | { type: 'setCamera'; camera: SetCamera }\n | { type: 'objects'; objects: SetObject[] }\n | { type: 'addObject'; object: SetObject }\n | { type: 'moveObject'; object: Pick<SetObject, 'id' | 'position' | 'rotation' | 'scale'> & { hidden?: boolean } }\n | { type: 'removeObject'; id: string }\n | { type: 'setLight'; lighting: SetLighting }\n | { type: 'setWorld'; world: ViewportWorld }\n | { type: 'frameObject'; id: string };\n\n/** The world fields the page draws: panorama turn, plain backdrop colour, ground and grid. */\nexport interface ViewportWorld {\n rotationDeg: number;\n background: string;\n showGround: boolean;\n}\n\n/** The JS that delivers one message to the page's handler. */\nexport function viewportMessageScript(msg: SetViewportMessage): string {\n return `window.dispatchEvent(new MessageEvent('message',{data:${JSON.stringify(JSON.stringify(msg))}}));true;`;\n}\n\nfunction setViewportHtml(opts: { worldUrl?: string; meshOrImageUrl?: string; camera: SetCamera }): string {\n const world = opts.worldUrl ? esc(opts.worldUrl) : '';\n const prop = opts.meshOrImageUrl ? esc(opts.meshOrImageUrl) : '';\n const cam = opts.camera;\n return `<!DOCTYPE html><html><head>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no\">\n<style>html,body{margin:0;height:100%;background:#0b0b0e;overflow:hidden}canvas{display:block;width:100%;height:100%}</style>\n</head><body>\n<script type=\"importmap\">{\"imports\":{\"three\":\"https://unpkg.com/three@0.160.0/build/three.module.js\",\"three/addons/\":\"https://unpkg.com/three@0.160.0/examples/jsm/\"}}</script>\n<script type=\"module\">\nimport * as THREE from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\nconst worldUrl=${JSON.stringify(world)};\nconst propUrl=${JSON.stringify(prop)};\nconst KIT=${KIT_FOR_PAGE};\nconst MESH_H=${MESH_TARGET_HEIGHT_M};\nconst D2R=Math.PI/180;\nconst scene=new THREE.Scene();\nscene.background=new THREE.Color(0x1a1a1e);\nconst camera=new THREE.PerspectiveCamera(${cam.fov},1,0.05,200);\ncamera.position.set(${cam.position.x},${cam.position.y},${cam.position.z});\n/* preserveDrawingBuffer stays FALSE: it doubles the framebuffer and stops the\n driver discarding it after compositing. capture() re-renders synchronously\n immediately before toDataURL(), which reads valid pixels without it. */\nconst renderer=new THREE.WebGLRenderer({antialias:true,preserveDrawingBuffer:false});\nrenderer.setPixelRatio(Math.min(devicePixelRatio,2));\ndocument.body.appendChild(renderer.domElement);\nconst controls=new OrbitControls(camera,renderer.domElement);\ncontrols.target.set(${cam.target.x},${cam.target.y},${cam.target.z});\ncontrols.enableDamping=true;\nconst light=new THREE.DirectionalLight(0xffffff,1.1);\nlight.position.set(2,4,3);scene.add(light);\nconst ambient=new THREE.AmbientLight(0xffffff,0.45);scene.add(ambient);\nconst ground=new THREE.Mesh(new THREE.CircleGeometry(4,48),new THREE.MeshStandardMaterial({color:0x2a2a30,roughness:0.9}));\nground.rotation.x=-Math.PI/2;scene.add(ground);\nconst grid=new THREE.GridHelper(8,16,0x4a4a55,0x34343c);grid.position.y=0.002;scene.add(grid);\nfunction fit(){const w=innerWidth,h=innerHeight;camera.aspect=w/Math.max(1,h);camera.updateProjectionMatrix();renderer.setSize(w,h,false);}\naddEventListener('resize',fit);fit();\nfunction post(type,payload){window.ReactNativeWebView&&window.ReactNativeWebView.postMessage(JSON.stringify({type,...payload}));}\n/* A generated model or world that will not load must say so, not draw nothing. */\nfunction failed(what){return ()=>post('loadError',{what});}\n/* The panorama rides an inside-out sphere rather than scene.background, so\n \"Turn the world\" is a plain rotation (three 0.160 has no backgroundRotation). */\nlet worldSphere=null;let worldRot=0;\nif(worldUrl){new THREE.TextureLoader().load(worldUrl,tex=>{\n tex.colorSpace=THREE.SRGBColorSpace;\n const geo=new THREE.SphereGeometry(90,64,32);geo.scale(-1,1,1);\n worldSphere=new THREE.Mesh(geo,new THREE.MeshBasicMaterial({map:tex}));\n worldSphere.rotation.y=worldRot;scene.add(worldSphere);\n const env=tex.clone();env.mapping=THREE.EquirectangularReflectionMapping;env.needsUpdate=true;scene.environment=env;\n},undefined,failed('world'));}\nfunction setWorld(w){\n worldRot=(w.rotationDeg||0)*D2R;if(worldSphere)worldSphere.rotation.y=worldRot;\n if(!worldUrl&&typeof w.background==='string'){try{scene.background=new THREE.Color(w.background);}catch(e){}}\n const g=w.showGround!==false;ground.visible=g;grid.visible=g;\n}\nlet gltfLoader=null;\nfunction loadGlb(url,ok,bad){\n (gltfLoader?Promise.resolve(gltfLoader):import('three/addons/loaders/GLTFLoader.js').then(({GLTFLoader})=>(gltfLoader=new GLTFLoader())))\n .then(l=>l.load(url,ok,undefined,bad)).catch(bad);\n}\nif(propUrl){\n if(/\\\\.glb($|\\\\?)/i.test(propUrl)){\n loadGlb(propUrl,g=>{const root=g.scene;root.position.set(0,0,0);scene.add(root);},failed('object'));\n } else {\n new THREE.TextureLoader().load(propUrl,tex=>{\n const aspect=tex.image.width/Math.max(1,tex.image.height);\n const w=1.2,h=w/aspect;\n const mesh=new THREE.Mesh(new THREE.PlaneGeometry(w,h),new THREE.MeshBasicMaterial({map:tex,transparent:true}));\n mesh.position.set(0,h/2,0);scene.add(mesh);\n },undefined,failed('object'));\n }\n}\n/* ── The set's objects ─────────────────────────────────────────────────── */\nconst live=new Map();\nfunction partGeometry(p){\n switch(p.shape){\n case 'box':return new THREE.BoxGeometry(p.a,p.b??p.a,p.c??p.a);\n case 'sphere':return new THREE.SphereGeometry(p.a,24,16);\n case 'cylinder':return new THREE.CylinderGeometry(p.a,p.a,p.b??1,24);\n case 'cone':return new THREE.ConeGeometry(p.a,p.b??1,24);\n case 'torus':return new THREE.TorusGeometry(p.a,p.b??0.1,12,32);\n case 'capsule':return new THREE.CapsuleGeometry(p.a,p.b??0.5,6,12);\n case 'plane':{const g=new THREE.PlaneGeometry(p.a,p.b??p.a);g.rotateX(-Math.PI/2);g.translate(0,0.003,0);return g;}\n default:return new THREE.BoxGeometry(0.3,0.3,0.3);\n }\n}\nfunction placeholder(holder,why){\n const box=new THREE.Mesh(new THREE.BoxGeometry(0.4,0.4,0.4),new THREE.MeshBasicMaterial({color:0xd97b3f,wireframe:true}));\n box.position.y=0.2;holder.add(box);\n if(why)post('objectError',{id:holder.userData.id,why});\n}\nfunction buildKit(o,holder){\n const e=KIT[o.kitId];\n if(!e){placeholder(holder,'unknown kit '+o.kitId);return;}\n for(const p of e.parts){\n const m=new THREE.Mesh(partGeometry(p),new THREE.MeshStandardMaterial({color:p.color||o.color||e.color,roughness:0.8}));\n if(p.offset)m.position.set(p.offset[0],p.offset[1],p.offset[2]);\n if(p.rotate)m.rotation.set(p.rotate[0]*D2R,p.rotate[1]*D2R,p.rotate[2]*D2R);\n holder.add(m);\n }\n}\nfunction buildMesh(o,holder){\n if(!o.modelUrl){placeholder(holder,'no model');return;}\n loadGlb(o.modelUrl,g=>{\n const root=g.scene;\n const box=new THREE.Box3().setFromObject(root);const size=box.getSize(new THREE.Vector3());\n const k=size.y>0?MESH_H/size.y:1;root.scale.setScalar(k);\n const c=box.getCenter(new THREE.Vector3());root.position.set(-c.x*k,-box.min.y*k,-c.z*k);\n holder.add(root);\n },()=>{placeholder(holder,'the model would not load');post('loadError',{what:'object'});});\n}\nfunction buildImage(o,holder){\n if(!o.imageUrl){placeholder(holder,'no image');return;}\n new THREE.TextureLoader().load(o.imageUrl,tex=>{\n const w=o.imageWidthM||1,h=w*tex.image.height/Math.max(1,tex.image.width);\n const m=new THREE.Mesh(new THREE.PlaneGeometry(w,h),new THREE.MeshBasicMaterial({map:tex,transparent:true,side:THREE.DoubleSide}));\n m.position.y=h/2;holder.add(m);\n },undefined,()=>{placeholder(holder,'the image would not load');post('loadError',{what:'object'});});\n}\nconst sigOf=o=>[o.source,o.kitId||o.modelUrl||o.imageUrl||'',o.color||'',o.imageWidthM||''].join('|');\nfunction place(holder,o){\n if(o.position)holder.position.set(o.position.x,o.position.y,o.position.z);\n if(o.rotation)holder.rotation.set(o.rotation.x*D2R,o.rotation.y*D2R,o.rotation.z*D2R);\n if(o.scale)holder.scale.set(o.scale.x,o.scale.y,o.scale.z);\n if(typeof o.hidden==='boolean')holder.visible=!o.hidden;\n}\nfunction addObject(o){\n const prev=live.get(o.id);\n if(prev&&prev.sig===sigOf(o)){place(prev.holder,o);return;}\n if(prev)scene.remove(prev.holder);\n const holder=new THREE.Group();holder.userData.id=o.id;\n if(o.source==='kit')buildKit(o,holder);else if(o.source==='mesh')buildMesh(o,holder);else buildImage(o,holder);\n place(holder,o);scene.add(holder);live.set(o.id,{holder,sig:sigOf(o)});\n}\nfunction removeObject(id){const rec=live.get(id);if(rec){scene.remove(rec.holder);live.delete(id);}}\nfunction syncObjects(list){\n const keep=new Set(list.map(o=>o.id));\n for(const id of [...live.keys()])if(!keep.has(id))removeObject(id);\n list.forEach(addObject);\n}\nfunction setLight(l){\n const az=l.keyAzimuthDeg*D2R,el=l.keyElevationDeg*D2R;\n light.position.set(Math.sin(az)*Math.cos(el)*6,Math.sin(el)*6,Math.cos(az)*Math.cos(el)*6);\n light.intensity=l.keyIntensity*0.42;ambient.intensity=l.ambientIntensity*0.82;\n}\nfunction frameObject(id){\n const rec=live.get(id);if(!rec)return;\n const box=new THREE.Box3().setFromObject(rec.holder);if(box.isEmpty())return;\n const c=box.getCenter(new THREE.Vector3());const r=Math.max(0.15,box.getSize(new THREE.Vector3()).length()/2);\n const dir=camera.position.clone().sub(controls.target).normalize();\n controls.target.copy(c);camera.position.copy(c.clone().add(dir.multiplyScalar(r*3)));controls.update();\n}\nfunction tick(){controls.update();renderer.render(scene,camera);requestAnimationFrame(tick);}tick();\nfunction capture(){renderer.render(scene,camera);return renderer.domElement.toDataURL('image/jpeg',0.92);}\nfunction onMessage(ev){\n let msg={};try{msg=JSON.parse(ev.data);}catch(e){return;}\n if(msg.type==='capture'){post('frame',{dataUrl:capture()});}\n if(msg.type==='setCamera'&&msg.camera){\n const c=msg.camera;camera.position.set(c.position.x,c.position.y,c.position.z);\n if(c.fov){camera.fov=c.fov;camera.updateProjectionMatrix();}\n controls.target.set(c.target.x,c.target.y,c.target.z);controls.update();\n }\n if(msg.type==='objects'&&Array.isArray(msg.objects))syncObjects(msg.objects);\n if(msg.type==='addObject'&&msg.object)addObject(msg.object);\n if(msg.type==='moveObject'&&msg.object){const rec=live.get(msg.object.id);if(rec)place(rec.holder,msg.object);}\n if(msg.type==='removeObject'&&msg.id)removeObject(msg.id);\n if(msg.type==='setLight'&&msg.lighting)setLight(msg.lighting);\n if(msg.type==='setWorld'&&msg.world)setWorld(msg.world);\n if(msg.type==='frameObject'&&msg.id)frameObject(msg.id);\n}\naddEventListener('message',onMessage);\ndocument.addEventListener('message',onMessage);\npost('ready',{});\n</script></body></html>`;\n}\n\nexport interface SetViewportApi {\n capture: () => void;\n setCamera: (c: SetCamera) => void;\n addObject: (object: SetObject) => void;\n moveObject: (object: SetObject) => void;\n removeObject: (id: string) => void;\n syncObjects: (objects: SetObject[]) => void;\n setLight: (lighting: SetLighting) => void;\n setWorld: (world: ViewportWorld) => void;\n frameObject: (id: string) => void;\n}\n\nexport function SetViewportWebView({\n worldUrl,\n propUrl,\n camera,\n objects,\n lighting,\n world,\n onFrame,\n onLoadError,\n webRef,\n}: {\n worldUrl?: string;\n propUrl?: string;\n camera: SetCamera;\n /** The set's objects; the page is kept in step with every change. */\n objects?: SetObject[];\n lighting?: SetLighting;\n /** Backdrop colour, panorama turn and ground toggle (the World panel). */\n world?: ViewportWorld;\n onFrame?: (dataUrl: string) => void;\n /** The world backdrop or the 3D object failed to load in the viewport. */\n onLoadError?: (what: 'world' | 'object') => void;\n webRef?: React.MutableRefObject<SetViewportApi | null>;\n}) {\n const WebView = loadWebView();\n const ref = useRef<{ injectJavaScript?: (js: string) => void } | null>(null);\n // The page is built once per world/prop; later camera moves are messages, not reloads.\n const cameraRef = useRef(camera);\n cameraRef.current = camera;\n const objectsRef = useRef(objects);\n objectsRef.current = objects;\n const lightingRef = useRef(lighting);\n lightingRef.current = lighting;\n const worldRef = useRef(world);\n worldRef.current = world;\n const html = useMemo(\n () => setViewportHtml({ worldUrl, meshOrImageUrl: propUrl, camera: cameraRef.current }),\n [worldUrl, propUrl],\n );\n /**\n * A live WebGL context with its own three.js runtime is the single most\n * expensive thing this app can hold. It rebuilds from `html` on return, so\n * release it once the viewport is off-screen or the app is backgrounded.\n */\n const shouldRender = useWebViewRetention({ releaseOnBlur: true });\n\n const send = (msg: SetViewportMessage) => ref.current?.injectJavaScript?.(viewportMessageScript(msg));\n\n if (webRef) {\n webRef.current = {\n capture: () => send({ type: 'capture' }),\n setCamera: (c) => send({ type: 'setCamera', camera: c }),\n addObject: (object) => send({ type: 'addObject', object }),\n moveObject: (object) =>\n send({\n type: 'moveObject',\n object: {\n id: object.id,\n position: object.position,\n rotation: object.rotation,\n scale: object.scale,\n hidden: Boolean(object.hidden),\n },\n }),\n removeObject: (id) => send({ type: 'removeObject', id }),\n syncObjects: (list) => send({ type: 'objects', objects: list }),\n setLight: (l) => send({ type: 'setLight', lighting: l }),\n setWorld: (w) => send({ type: 'setWorld', world: w }),\n frameObject: (id) => send({ type: 'frameObject', id }),\n };\n }\n\n useEffect(() => {\n if (objects) send({ type: 'objects', objects });\n }, [objects]);\n useEffect(() => {\n if (lighting) send({ type: 'setLight', lighting });\n }, [lighting]);\n useEffect(() => {\n if (world) send({ type: 'setWorld', world });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [world?.rotationDeg, world?.background, world?.showGround]);\n const firstCamera = useRef(true);\n useEffect(() => {\n if (firstCamera.current) {\n firstCamera.current = false;\n return;\n }\n send({ type: 'setCamera', camera });\n }, [camera]);\n\n if (!WebView || !shouldRender) return <View style={styles.fallback} />;\n\n return (\n <WebView\n ref={(node: { injectJavaScript?: (js: string) => void } | null) => {\n ref.current = node;\n }}\n originWhitelist={['*']}\n source={{ html }}\n style={styles.view}\n onMessage={(event: { nativeEvent: { data: string } }) => {\n try {\n const msg = JSON.parse(event.nativeEvent.data) as {\n type?: string;\n dataUrl?: string;\n what?: string;\n };\n if (msg.type === 'frame' && msg.dataUrl) onFrame?.(msg.dataUrl);\n if (msg.type === 'loadError') onLoadError?.(msg.what === 'world' ? 'world' : 'object');\n if (msg.type === 'ready') {\n // A fresh page (first load, a new world, a return from the background) starts empty.\n send({ type: 'setLight', lighting: lightingRef.current ?? DEFAULT_LIGHTING });\n if (worldRef.current) send({ type: 'setWorld', world: worldRef.current });\n if (objectsRef.current?.length) send({ type: 'objects', objects: objectsRef.current });\n send({ type: 'setCamera', camera: cameraRef.current });\n }\n } catch {\n /* ignore */\n }\n }}\n allowFileAccess\n mixedContentMode=\"always\"\n />\n );\n}\n\nconst styles = StyleSheet.create({\n view: { flex: 1, backgroundColor: '#0B0B0E', minHeight: 220 },\n fallback: { flex: 1, minHeight: 220, backgroundColor: '#0B0B0E' },\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {BRAIN_SMART_MODEL,brainChat}from'../../videoEditor/agent/brainClient.js';import {buildSetSystemPrompt}from'./prompt.js';import {SET_AGENT_TOOLS,executeSetTool}from'./tools.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {BRAIN_SMART_MODEL,BrainSignInRequiredError,brainChat}from'../../videoEditor/agent/brainClient.js';import {buildSetSystemPrompt}from'./prompt.js';import {SET_AGENT_TOOLS,executeSetTool}from'./tools.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -54,7 +54,9 @@ async function runSetTurn(args) {
|
|
|
54
54
|
onStep
|
|
55
55
|
} = args;
|
|
56
56
|
const chat = (_a = args.chat) != null ? _a : ((req) => {
|
|
57
|
-
|
|
57
|
+
var _a2;
|
|
58
|
+
if (!((_a2 = args.token) == null ? void 0 : _a2.trim())) throw new BrainSignInRequiredError();
|
|
59
|
+
if (!args.agentEndpoint) throw new Error("The set agent needs a signed-in session.");
|
|
58
60
|
return brainChat(__spreadProps(__spreadValues({}, req), {
|
|
59
61
|
token: args.token,
|
|
60
62
|
agentEndpoint: args.agentEndpoint
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setTurn.js","sources":["../../../../../src/features/canvas/set/agent/setTurn.ts"],"sourcesContent":["/**\n * One turn of the set agent - twin of web `editors/set-editor/agent/setTurn.ts`\n * on the native brain lane (`videoEditor/agent/brainClient`, the same gateway\n * the cut agent uses): the model reads the set and the conversation, calls\n * tools until the shot is blocked, then says what it built.\n *\n * Each tool call commits through `ctx.commit`, so the stage changes as the\n * agent works and the person can take over by hand the moment it is done.\n */\nimport {\n BRAIN_SMART_MODEL,\n brainChat,\n type BrainMessage,\n type BrainReply,\n type BrainTool,\n type BrainToolCall,\n} from '../../videoEditor/agent/brainClient';\nimport { buildSetSystemPrompt } from './prompt';\nimport { SET_AGENT_TOOLS, executeSetTool, type SetAgentContext, type ToolOutcome } from './tools';\n\n/** A line of the set prompt's transcript. Session state - not part of the set. */\nexport interface SetChatMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\n/** A brain message that can carry the assistant's tool calls (OpenAI wire shape). */\nexport type SetTurnMessage = BrainMessage & { tool_calls?: BrainToolCall[] };\n\n/** The transport, minus auth - the gateway by default, a script in tests. */\nexport type SetTurnChat = (req: {\n messages: SetTurnMessage[];\n tools?: BrainTool[];\n model: string;\n}) => Promise<BrainReply>;\n\nexport interface SetTurnStep {\n label: string;\n detail?: string;\n}\n\nexport interface SetTurnResult {\n text: string;\n steps: SetTurnStep[];\n}\n\nexport interface SetTurnArgs {\n history: readonly SetChatMessage[];\n userText: string;\n ctx: SetAgentContext;\n /** Required unless `chat` is given. */\n token?: string;\n agentEndpoint?: string;\n chat?: SetTurnChat;\n model?: string;\n tools?: BrainTool[];\n execute?: (name: string, args: unknown, ctx: SetAgentContext) => Promise<ToolOutcome>;\n maxRounds?: number;\n historyLimit?: number;\n onStatus?: (text: string) => void;\n onStep?: (step: SetTurnStep) => void;\n}\n\nconst DEFAULT_HISTORY = 12;\nconst DEFAULT_ROUNDS = 12;\nconst WRAP_UP =\n 'Stop calling tools now. In two plain sentences, tell the user what the set holds and what is still missing.';\nconst EXHAUSTED = 'I ran out of steps before finishing; the stage holds what was blocked so far.';\n\n/** The last turns of the transcript as chat messages, oldest first. */\nexport function historyToMessages(history: readonly SetChatMessage[], limit = DEFAULT_HISTORY): BrainMessage[] {\n const out: BrainMessage[] = [];\n for (const m of history.slice(-limit)) {\n const content = m.content.trim();\n if (content) out.push({ role: m.role, content });\n }\n return out;\n}\n\nfunction parseArgs(raw: string | undefined): unknown {\n try {\n return JSON.parse(raw || '{}');\n } catch {\n return {};\n }\n}\n\nexport async function runSetTurn(args: SetTurnArgs): Promise<SetTurnResult> {\n const {\n history,\n userText,\n ctx,\n model = BRAIN_SMART_MODEL,\n tools = SET_AGENT_TOOLS,\n execute = executeSetTool,\n maxRounds = DEFAULT_ROUNDS,\n historyLimit = DEFAULT_HISTORY,\n onStatus,\n onStep,\n } = args;\n const chat: SetTurnChat =\n args.chat ??\n ((req) => {\n if (!args.token
|
|
1
|
+
{"version":3,"file":"setTurn.js","sources":["../../../../../src/features/canvas/set/agent/setTurn.ts"],"sourcesContent":["/**\n * One turn of the set agent - twin of web `editors/set-editor/agent/setTurn.ts`\n * on the native brain lane (`videoEditor/agent/brainClient`, the same gateway\n * the cut agent uses): the model reads the set and the conversation, calls\n * tools until the shot is blocked, then says what it built.\n *\n * Each tool call commits through `ctx.commit`, so the stage changes as the\n * agent works and the person can take over by hand the moment it is done.\n */\nimport {\n BRAIN_SMART_MODEL,\n BrainSignInRequiredError,\n brainChat,\n type BrainMessage,\n type BrainReply,\n type BrainTool,\n type BrainToolCall,\n} from '../../videoEditor/agent/brainClient';\nimport { buildSetSystemPrompt } from './prompt';\nimport { SET_AGENT_TOOLS, executeSetTool, type SetAgentContext, type ToolOutcome } from './tools';\n\n/** A line of the set prompt's transcript. Session state - not part of the set. */\nexport interface SetChatMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\n/** A brain message that can carry the assistant's tool calls (OpenAI wire shape). */\nexport type SetTurnMessage = BrainMessage & { tool_calls?: BrainToolCall[] };\n\n/** The transport, minus auth - the gateway by default, a script in tests. */\nexport type SetTurnChat = (req: {\n messages: SetTurnMessage[];\n tools?: BrainTool[];\n model: string;\n}) => Promise<BrainReply>;\n\nexport interface SetTurnStep {\n label: string;\n detail?: string;\n}\n\nexport interface SetTurnResult {\n text: string;\n steps: SetTurnStep[];\n}\n\nexport interface SetTurnArgs {\n history: readonly SetChatMessage[];\n userText: string;\n ctx: SetAgentContext;\n /** Required unless `chat` is given. */\n token?: string;\n agentEndpoint?: string;\n chat?: SetTurnChat;\n model?: string;\n tools?: BrainTool[];\n execute?: (name: string, args: unknown, ctx: SetAgentContext) => Promise<ToolOutcome>;\n maxRounds?: number;\n historyLimit?: number;\n onStatus?: (text: string) => void;\n onStep?: (step: SetTurnStep) => void;\n}\n\nconst DEFAULT_HISTORY = 12;\nconst DEFAULT_ROUNDS = 12;\nconst WRAP_UP =\n 'Stop calling tools now. In two plain sentences, tell the user what the set holds and what is still missing.';\nconst EXHAUSTED = 'I ran out of steps before finishing; the stage holds what was blocked so far.';\n\n/** The last turns of the transcript as chat messages, oldest first. */\nexport function historyToMessages(history: readonly SetChatMessage[], limit = DEFAULT_HISTORY): BrainMessage[] {\n const out: BrainMessage[] = [];\n for (const m of history.slice(-limit)) {\n const content = m.content.trim();\n if (content) out.push({ role: m.role, content });\n }\n return out;\n}\n\nfunction parseArgs(raw: string | undefined): unknown {\n try {\n return JSON.parse(raw || '{}');\n } catch {\n return {};\n }\n}\n\nexport async function runSetTurn(args: SetTurnArgs): Promise<SetTurnResult> {\n const {\n history,\n userText,\n ctx,\n model = BRAIN_SMART_MODEL,\n tools = SET_AGENT_TOOLS,\n execute = executeSetTool,\n maxRounds = DEFAULT_ROUNDS,\n historyLimit = DEFAULT_HISTORY,\n onStatus,\n onStep,\n } = args;\n const chat: SetTurnChat =\n args.chat ??\n ((req) => {\n if (!args.token?.trim()) throw new BrainSignInRequiredError();\n if (!args.agentEndpoint) throw new Error('The set agent needs a signed-in session.');\n return brainChat({ ...req, token: args.token, agentEndpoint: args.agentEndpoint });\n });\n\n const steps: SetTurnStep[] = [];\n const messages: SetTurnMessage[] = [\n { role: 'system', content: buildSetSystemPrompt(ctx.project(), { stills: ctx.stills }) },\n ...historyToMessages(history, historyLimit),\n { role: 'user', content: userText },\n ];\n\n for (let round = 0; round < maxRounds; round += 1) {\n if (ctx.signal?.aborted) throw Object.assign(new Error('Stopped'), { name: 'AbortError' });\n onStatus?.(round === 0 ? 'Reading the brief…' : 'Blocking the set…');\n const reply = await chat({ messages, tools, model });\n if (!reply.tool_calls?.length) return { text: reply.content.trim() || 'Done.', steps };\n\n messages.push({ role: 'assistant', content: reply.content || '', tool_calls: reply.tool_calls });\n for (const call of reply.tool_calls) {\n onStatus?.(call.function.name.replace(/_/g, ' '));\n const outcome = await execute(call.function.name, parseArgs(call.function.arguments), ctx);\n const step = { label: outcome.label, ...(outcome.detail ? { detail: outcome.detail } : {}) };\n steps.push(step);\n onStep?.(step);\n messages.push({ role: 'tool', tool_call_id: call.id, name: call.function.name, content: outcome.result });\n }\n }\n\n // Out of rounds: one last call without tools so the reply says what is there.\n try {\n const reply = await chat({ messages: [...messages, { role: 'user', content: WRAP_UP }], model });\n return { text: reply.content.trim() || EXHAUSTED, steps };\n } catch {\n return { text: EXHAUSTED, steps };\n }\n}\n"],"names":["_a"],"mappings":";;;;;;;;;;;;;;;;;;;AAsDA,MAAM,eAAkB,GAAA,EAAA;AACxB,MAAM,cAAiB,GAAA,EAAA;AACvB,MAAM,OAAU,GAAA,6GAAA;AAChB,MAAM,SAAY,GAAA,+EAAA;AAGF,SAAA,iBAAA,CAAkB,OAAoC,EAAA,KAAA,GAAQ,eAAiC,EAAA;AAC7G,EAAA,MAAM,MAAsB,EAAC;AAC7B,EAAA,KAAA,MAAW,CAAK,IAAA,OAAA,CAAQ,KAAM,CAAA,CAAC,KAAK,CAAG,EAAA;AACrC,IAAM,MAAA,OAAA,GAAU,CAAE,CAAA,OAAA,CAAQ,IAAK,EAAA;AAC/B,IAAI,IAAA,OAAA,MAAa,IAAK,CAAA;AAAA,MACpB,MAAM,CAAE,CAAA,IAAA;AAAA,MACR;AAAA,KACD,CAAA;AAAA;AAEH,EAAO,OAAA,GAAA;AACT;AACA,SAAS,UAAU,GAAkC,EAAA;AACnD,EAAI,IAAA;AACF,IAAO,OAAA,IAAA,CAAK,KAAM,CAAA,GAAA,IAAO,IAAI,CAAA;AAAA,GACvB,CAAA,OAAA,CAAA,EAAA;AACN,IAAA,OAAO,EAAC;AAAA;AAEZ;AACA,eAAsB,WAAW,IAA2C,EAAA;AA9E5E,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA+EE,EAAM,MAAA;AAAA,IACJ,OAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAA;AAAA,IACA,KAAQ,GAAA,iBAAA;AAAA,IACR,KAAQ,GAAA,eAAA;AAAA,IACR,OAAU,GAAA,cAAA;AAAA,IACV,SAAY,GAAA,cAAA;AAAA,IACZ,YAAe,GAAA,eAAA;AAAA,IACf,QAAA;AAAA,IACA;AAAA,GACE,GAAA,IAAA;AACJ,EAAA,MAAM,IAAoB,GAAA,CAAA,EAAA,GAAA,IAAA,CAAK,IAAL,KAAA,IAAA,GAAA,EAAA,IAAc,CAAO,GAAA,KAAA;AA3FjD,IAAAA,IAAAA,GAAAA;AA4FI,IAAI,IAAA,EAAA,CAACA,MAAA,IAAK,CAAA,KAAA,KAAL,gBAAAA,GAAY,CAAA,IAAA,EAAA,CAAA,EAAc,MAAA,IAAI,wBAAyB,EAAA;AAC5D,IAAA,IAAI,CAAC,IAAK,CAAA,aAAA,EAAqB,MAAA,IAAI,MAAM,0CAA0C,CAAA;AACnF,IAAO,OAAA,SAAA,CAAU,iCACZ,GADY,CAAA,EAAA;AAAA,MAEf,OAAO,IAAK,CAAA,KAAA;AAAA,MACZ,eAAe,IAAK,CAAA;AAAA,KACrB,CAAA,CAAA;AAAA,GACH,CAAA;AACA,EAAA,MAAM,QAAuB,EAAC;AAC9B,EAAA,MAAM,WAA6B,CAAC;AAAA,IAClC,IAAM,EAAA,QAAA;AAAA,IACN,OAAS,EAAA,oBAAA,CAAqB,GAAI,CAAA,OAAA,EAAW,EAAA;AAAA,MAC3C,QAAQ,GAAI,CAAA;AAAA,KACb;AAAA,GACA,EAAA,GAAG,iBAAkB,CAAA,OAAA,EAAS,YAAY,CAAG,EAAA;AAAA,IAC9C,IAAM,EAAA,MAAA;AAAA,IACN,OAAS,EAAA;AAAA,GACV,CAAA;AACD,EAAA,KAAA,IAAS,KAAQ,GAAA,CAAA,EAAG,KAAQ,GAAA,SAAA,EAAW,SAAS,CAAG,EAAA;AACjD,IAAI,IAAA,CAAA,EAAA,GAAA,GAAA,CAAI,MAAJ,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAY,OAAS,EAAA,MAAM,OAAO,MAAO,CAAA,IAAI,KAAM,CAAA,SAAS,CAAG,EAAA;AAAA,MACjE,IAAM,EAAA;AAAA,KACP,CAAA;AACD,IAAW,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAA,KAAA,KAAU,IAAI,yBAAuB,GAAA,wBAAA,CAAA;AAChD,IAAM,MAAA,KAAA,GAAQ,MAAM,IAAK,CAAA;AAAA,MACvB,QAAA;AAAA,MACA,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,IAAI,EAAC,CAAA,EAAA,GAAA,KAAA,CAAM,UAAN,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAkB,SAAe,OAAA;AAAA,MACpC,IAAM,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,EAAU,IAAA,OAAA;AAAA,MAC9B;AAAA,KACF;AACA,IAAA,QAAA,CAAS,IAAK,CAAA;AAAA,MACZ,IAAM,EAAA,WAAA;AAAA,MACN,OAAA,EAAS,MAAM,OAAW,IAAA,EAAA;AAAA,MAC1B,YAAY,KAAM,CAAA;AAAA,KACnB,CAAA;AACD,IAAW,KAAA,MAAA,IAAA,IAAQ,MAAM,UAAY,EAAA;AACnC,MAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAW,IAAK,CAAA,QAAA,CAAS,IAAK,CAAA,OAAA,CAAQ,MAAM,GAAG,CAAA,CAAA;AAC/C,MAAM,MAAA,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAK,CAAA,QAAA,CAAS,IAAM,EAAA,SAAA,CAAU,IAAK,CAAA,QAAA,CAAS,SAAS,CAAA,EAAG,GAAG,CAAA;AACzF,MAAA,MAAM,IAAO,GAAA,cAAA,CAAA;AAAA,QACX,OAAO,OAAQ,CAAA;AAAA,OAAA,EACX,QAAQ,MAAS,GAAA;AAAA,QACnB,QAAQ,OAAQ,CAAA;AAAA,UACd,EAAC,CAAA;AAEP,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AACf,MAAS,MAAA,IAAA,IAAA,GAAA,MAAA,GAAA,MAAA,CAAA,IAAA,CAAA;AACT,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,IAAM,EAAA,MAAA;AAAA,QACN,cAAc,IAAK,CAAA,EAAA;AAAA,QACnB,IAAA,EAAM,KAAK,QAAS,CAAA,IAAA;AAAA,QACpB,SAAS,OAAQ,CAAA;AAAA,OAClB,CAAA;AAAA;AACH;AAIF,EAAI,IAAA;AACF,IAAM,MAAA,KAAA,GAAQ,MAAM,IAAK,CAAA;AAAA,MACvB,QAAA,EAAU,CAAC,GAAG,QAAU,EAAA;AAAA,QACtB,IAAM,EAAA,MAAA;AAAA,QACN,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,MACD;AAAA,KACD,CAAA;AACD,IAAO,OAAA;AAAA,MACL,IAAM,EAAA,KAAA,CAAM,OAAQ,CAAA,IAAA,EAAU,IAAA,SAAA;AAAA,MAC9B;AAAA,KACF;AAAA,GACM,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA;AAAA,MACL,IAAM,EAAA,SAAA;AAAA,MACN;AAAA,KACF;AAAA;AAEJ"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {buildVideoGenerateParams}from'../generationModels.js';import {DEFAULT_LIGHTING}from'./setProject.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
const LENSES = [18, 24, 28, 35, 50, 85, 135];
|
|
21
|
+
const WORLD_PRESETS = [{
|
|
22
|
+
label: "Studio",
|
|
23
|
+
prompt: "a clean photographic studio, seamless grey cyclorama, soft overhead light"
|
|
24
|
+
}, {
|
|
25
|
+
label: "Golden hour",
|
|
26
|
+
prompt: "an open field at golden hour, low sun, long shadows, scattered cloud"
|
|
27
|
+
}, {
|
|
28
|
+
label: "Neon street",
|
|
29
|
+
prompt: "a rain-slicked city street at night, neon signage, wet asphalt reflections"
|
|
30
|
+
}, {
|
|
31
|
+
label: "Desert",
|
|
32
|
+
prompt: "a wide desert canyon at midday, red rock walls, hard clear light"
|
|
33
|
+
}, {
|
|
34
|
+
label: "Warehouse",
|
|
35
|
+
prompt: "a disused concrete warehouse, high windows, dusty shafts of daylight"
|
|
36
|
+
}, {
|
|
37
|
+
label: "Forest",
|
|
38
|
+
prompt: "a temperate forest clearing, dappled light through the canopy, morning mist"
|
|
39
|
+
}];
|
|
40
|
+
const BUILD_SUGGESTIONS = [{
|
|
41
|
+
label: "Block a scene",
|
|
42
|
+
text: "Block a small cafe interior: a table by a window, two people seated across it, a counter behind them. Shoot it at seated height on a 35mm lens."
|
|
43
|
+
}, {
|
|
44
|
+
label: "Product shot",
|
|
45
|
+
text: "Set up a product shot: one hero object on a table at 50mm, 1.4m out, soft key from camera left, plain backdrop and nothing else in frame."
|
|
46
|
+
}, {
|
|
47
|
+
label: "Second angle",
|
|
48
|
+
text: "Keep everything where it is and move the camera round to the other side of the subject, same lens."
|
|
49
|
+
}, {
|
|
50
|
+
label: "Light it warmer",
|
|
51
|
+
text: "Bring the key light down low for long shadows and warm it up, like late afternoon."
|
|
52
|
+
}];
|
|
53
|
+
const BACKDROP_COLORS = ["#1a1a1e", "#0b0b0e", "#3a3a42", "#d9d9de", "#f2efe9", "#20304a", "#3a2a20"];
|
|
54
|
+
const DEFAULT_MOTION = "Gentle camera drift, subtle natural movement, no cuts.";
|
|
55
|
+
function animateRenderParams(opts) {
|
|
56
|
+
return buildVideoGenerateParams({
|
|
57
|
+
prompt: opts.motion.trim() || DEFAULT_MOTION,
|
|
58
|
+
aspectRatio: opts.aspect,
|
|
59
|
+
referenceImageUrl: opts.stillUrl,
|
|
60
|
+
durationSeconds: 5
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function withAxis(v, axis, value) {
|
|
64
|
+
return __spreadProps(__spreadValues({}, v), {
|
|
65
|
+
[axis]: value
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function patchWorld(project, patch) {
|
|
69
|
+
return __spreadProps(__spreadValues({}, project), {
|
|
70
|
+
world: __spreadValues(__spreadValues({}, project.world), patch)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function patchLighting(project, patch) {
|
|
74
|
+
var _a;
|
|
75
|
+
return __spreadProps(__spreadValues({}, project), {
|
|
76
|
+
lighting: __spreadValues(__spreadValues({}, (_a = project.lighting) != null ? _a : DEFAULT_LIGHTING), patch)
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function viewportWorld(world) {
|
|
80
|
+
return {
|
|
81
|
+
rotationDeg: world.rotationDeg,
|
|
82
|
+
background: world.background,
|
|
83
|
+
showGround: world.showGround
|
|
84
|
+
};
|
|
85
|
+
}export{BACKDROP_COLORS,BUILD_SUGGESTIONS,DEFAULT_MOTION,LENSES,WORLD_PRESETS,animateRenderParams,patchLighting,patchWorld,viewportWorld,withAxis};//# sourceMappingURL=setPresets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setPresets.js","sources":["../../../../src/features/canvas/set/setPresets.ts"],"sourcesContent":["/**\n * The Set studio's fixed choices, twinned from the web panels:\n * LENSES RenderPanel.tsx (lens picker)\n * WORLD_PRESETS WorldPanel.tsx (panorama starting points)\n * BUILD_SUGGESTIONS BuildPanel.tsx (set agent prompt chips)\n * plus the pure helpers the native studio uses to apply them.\n */\nimport { buildVideoGenerateParams } from '../generationModels';\nimport { DEFAULT_LIGHTING, type SetLighting, type SetProject, type SetWorld, type Vec3 } from './setProject';\n\n/** Lenses a director would actually call for, widest first. */\nexport const LENSES = [18, 24, 28, 35, 50, 85, 135] as const;\n\n/** Starting points that read well as panoramas - open, with a clear horizon. */\nexport const WORLD_PRESETS: ReadonlyArray<{ label: string; prompt: string }> = [\n { label: 'Studio', prompt: 'a clean photographic studio, seamless grey cyclorama, soft overhead light' },\n { label: 'Golden hour', prompt: 'an open field at golden hour, low sun, long shadows, scattered cloud' },\n { label: 'Neon street', prompt: 'a rain-slicked city street at night, neon signage, wet asphalt reflections' },\n { label: 'Desert', prompt: 'a wide desert canyon at midday, red rock walls, hard clear light' },\n { label: 'Warehouse', prompt: 'a disused concrete warehouse, high windows, dusty shafts of daylight' },\n { label: 'Forest', prompt: 'a temperate forest clearing, dappled light through the canopy, morning mist' },\n];\n\n/** The set agent's starter prompts. */\nexport const BUILD_SUGGESTIONS: ReadonlyArray<{ label: string; text: string }> = [\n {\n label: 'Block a scene',\n text: 'Block a small cafe interior: a table by a window, two people seated across it, a counter behind them. Shoot it at seated height on a 35mm lens.',\n },\n {\n label: 'Product shot',\n text: 'Set up a product shot: one hero object on a table at 50mm, 1.4m out, soft key from camera left, plain backdrop and nothing else in frame.',\n },\n {\n label: 'Second angle',\n text: 'Keep everything where it is and move the camera round to the other side of the subject, same lens.',\n },\n {\n label: 'Light it warmer',\n text: 'Bring the key light down low for long shadows and warm it up, like late afternoon.',\n },\n];\n\n/** Backdrop colours for a set with no generated world (web uses a free colour input). */\nexport const BACKDROP_COLORS = ['#1a1a1e', '#0b0b0e', '#3a3a42', '#d9d9de', '#f2efe9', '#20304a', '#3a2a20'] as const;\n\n/** What the video model is asked when the motion box is left empty (web RenderPanel animate). */\nexport const DEFAULT_MOTION = 'Gentle camera drift, subtle natural movement, no cuts.';\n\n/** Animate a rendered still: the still is the first frame, the motion is the video model's. */\nexport function animateRenderParams(opts: {\n stillUrl: string;\n motion: string;\n aspect: string;\n}): Record<string, unknown> {\n return buildVideoGenerateParams({\n prompt: opts.motion.trim() || DEFAULT_MOTION,\n aspectRatio: opts.aspect,\n referenceImageUrl: opts.stillUrl,\n durationSeconds: 5,\n });\n}\n\n/** One field of a Vec3 changed - the patch a numeric inspector field makes. */\nexport function withAxis(v: Vec3, axis: keyof Vec3, value: number): Vec3 {\n return { ...v, [axis]: value };\n}\n\n/** Merge a world patch (backdrop, turn, ground, or the panorama itself). */\nexport function patchWorld(project: SetProject, patch: Partial<SetWorld>): SetProject {\n return { ...project, world: { ...project.world, ...patch } };\n}\n\nexport function patchLighting(project: SetProject, patch: Partial<SetLighting>): SetProject {\n return { ...project, lighting: { ...(project.lighting ?? DEFAULT_LIGHTING), ...patch } };\n}\n\n/** The world fields the viewport page draws (sent as one `setWorld` message). */\nexport function viewportWorld(world: SetWorld): { rotationDeg: number; background: string; showGround: boolean } {\n return { rotationDeg: world.rotationDeg, background: world.background, showGround: world.showGround };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAWa,MAAA,MAAA,GAAS,CAAC,EAAI,EAAA,EAAA,EAAI,IAAI,EAAI,EAAA,EAAA,EAAI,IAAI,GAAG;AAG3C,MAAM,gBAGR,CAAC;AAAA,EACJ,KAAO,EAAA,QAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,aAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,aAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,QAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,WAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,QAAA;AAAA,EACP,MAAQ,EAAA;AACV,CAAC;AAGM,MAAM,oBAGR,CAAC;AAAA,EACJ,KAAO,EAAA,eAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,cAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,cAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAG,EAAA;AAAA,EACD,KAAO,EAAA,iBAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAC;AAGY,MAAA,eAAA,GAAkB,CAAC,SAAW,EAAA,SAAA,EAAW,WAAW,SAAW,EAAA,SAAA,EAAW,WAAW,SAAS;AAGpG,MAAM,cAAiB,GAAA;AAGvB,SAAS,oBAAoB,IAIR,EAAA;AAC1B,EAAA,OAAO,wBAAyB,CAAA;AAAA,IAC9B,MAAQ,EAAA,IAAA,CAAK,MAAO,CAAA,IAAA,EAAU,IAAA,cAAA;AAAA,IAC9B,aAAa,IAAK,CAAA,MAAA;AAAA,IAClB,mBAAmB,IAAK,CAAA,QAAA;AAAA,IACxB,eAAiB,EAAA;AAAA,GAClB,CAAA;AACH;AAGgB,SAAA,QAAA,CAAS,CAAS,EAAA,IAAA,EAAkB,KAAqB,EAAA;AACvE,EAAA,OAAO,iCACF,CADE,CAAA,EAAA;AAAA,IAEL,CAAC,IAAI,GAAG;AAAA,GACV,CAAA;AACF;AAGgB,SAAA,UAAA,CAAW,SAAqB,KAAsC,EAAA;AACpF,EAAA,OAAO,iCACF,OADE,CAAA,EAAA;AAAA,IAEL,KAAA,EAAO,cACF,CAAA,cAAA,CAAA,EAAA,EAAA,OAAA,CAAQ,KACR,CAAA,EAAA,KAAA;AAAA,GAEP,CAAA;AACF;AACgB,SAAA,aAAA,CAAc,SAAqB,KAAyC,EAAA;AA7F5F,EAAA,IAAA,EAAA;AA8FE,EAAA,OAAO,iCACF,OADE,CAAA,EAAA;AAAA,IAEL,QAAU,EAAA,cAAA,CAAA,cAAA,CAAA,EAAA,EAAA,CACJ,EAAQ,GAAA,OAAA,CAAA,QAAA,KAAR,YAAoB,gBACrB,CAAA,EAAA,KAAA;AAAA,GAEP,CAAA;AACF;AAGO,SAAS,cAAc,KAI5B,EAAA;AACA,EAAO,OAAA;AAAA,IACL,aAAa,KAAM,CAAA,WAAA;AAAA,IACnB,YAAY,KAAM,CAAA,UAAA;AAAA,IAClB,YAAY,KAAM,CAAA;AAAA,GACpB;AACF"}
|
|
@@ -37,6 +37,9 @@ const newObjectId = () => `so-${Date.now().toString(36)}-${objectSeq++}`;
|
|
|
37
37
|
function focalLengthFromFov(fovDeg) {
|
|
38
38
|
return Math.round(24 / 2 / Math.tan(fovDeg * Math.PI / 360));
|
|
39
39
|
}
|
|
40
|
+
function fovFromFocalLength(mm) {
|
|
41
|
+
return 2 * Math.atan(24 / 2 / Math.max(1, mm)) * 180 / Math.PI;
|
|
42
|
+
}
|
|
40
43
|
const lightingOf = (project) => {
|
|
41
44
|
var _a;
|
|
42
45
|
return (_a = project.lighting) != null ? _a : DEFAULT_LIGHTING;
|
|
@@ -60,4 +63,4 @@ function newSet(title = "Untitled set") {
|
|
|
60
63
|
lighting: __spreadValues({}, DEFAULT_LIGHTING),
|
|
61
64
|
aspect: "16:9"
|
|
62
65
|
};
|
|
63
|
-
}export{DEFAULT_CAMERA,DEFAULT_LIGHTING,MESH_TARGET_HEIGHT_M,SET_ASPECTS,focalLengthFromFov,lightingOf,newObjectId,newSet,vec3};//# sourceMappingURL=setProject.js.map
|
|
66
|
+
}export{DEFAULT_CAMERA,DEFAULT_LIGHTING,MESH_TARGET_HEIGHT_M,SET_ASPECTS,focalLengthFromFov,fovFromFocalLength,lightingOf,newObjectId,newSet,vec3};//# sourceMappingURL=setProject.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setProject.js","sources":["../../../../src/features/canvas/set/setProject.ts"],"sourcesContent":["/**\n * SetProject types for native set studio + cameraPath
|
|
1
|
+
{"version":3,"file":"setProject.js","sources":["../../../../src/features/canvas/set/setProject.ts"],"sourcesContent":["/**\n * SetProject types for native set studio + cameraPath - twin of web\n * `editors/set-editor/types.ts` (plain JSON; the WebView stage is rebuilt from it).\n */\nexport interface Vec3 {\n x: number;\n y: number;\n z: number;\n}\n\nexport const vec3 = (x = 0, y = 0, z = 0): Vec3 => ({ x, y, z });\n\nexport interface SetCamera {\n position: Vec3;\n target: Vec3;\n fov: number;\n}\n\nexport interface SetWorld {\n imageUrl?: string;\n prompt?: string;\n model?: string;\n rotationDeg: number;\n background: string;\n showGround: boolean;\n}\n\nexport interface SetObject {\n id: string;\n name: string;\n source: 'kit' | 'mesh' | 'image';\n /** Supply-library entry id when `source` is 'kit'. */\n kitId?: string;\n modelUrl?: string;\n imageUrl?: string;\n /** Width in metres of an image plane; its height follows the image's aspect. */\n imageWidthM?: number;\n billboard?: boolean;\n previewUrl?: string;\n /** The image this object was generated from, if any. */\n sourceImageUrl?: string;\n position: Vec3;\n /** Euler angles in degrees. */\n rotation: Vec3;\n scale: Vec3;\n /** Tint for kit primitives; ignored for textured meshes. */\n color?: string;\n hidden?: boolean;\n locked?: boolean;\n}\n\nexport interface SetLighting {\n keyAzimuthDeg: number;\n keyElevationDeg: number;\n keyIntensity: number;\n ambientIntensity: number;\n}\n\nexport interface SetProject {\n version: 1;\n id: string;\n title: string;\n objects: SetObject[];\n world: SetWorld;\n camera: SetCamera;\n /** Optional on native so sets saved before lighting existed still open. */\n lighting?: SetLighting;\n aspect: string;\n}\n\nexport const DEFAULT_CAMERA: SetCamera = {\n position: vec3(0, 1.4, 3.2),\n target: vec3(0, 0.9, 0),\n fov: 35,\n};\n\nexport const DEFAULT_LIGHTING: SetLighting = {\n keyAzimuthDeg: 135,\n keyElevationDeg: 42,\n keyIntensity: 2.6,\n ambientIntensity: 0.55,\n};\n\n/** Height a generated GLB is normalised to before its own scale (web MESH_TARGET_HEIGHT_M). */\nexport const MESH_TARGET_HEIGHT_M = 1.2;\n\n/** Aspects the render can be framed to. */\nexport const SET_ASPECTS = ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'] as const;\n\nlet objectSeq = 0;\n\n/** Unique per object - `Date.now()` alone collides when two land in one tick. */\nexport const newObjectId = (): string => `so-${Date.now().toString(36)}-${objectSeq++}`;\n\n/** The 35mm-equivalent focal length for a vertical FOV. */\nexport function focalLengthFromFov(fovDeg: number): number {\n return Math.round(24 / 2 / Math.tan((fovDeg * Math.PI) / 360));\n}\n\n/** The vertical FOV for a 35mm-equivalent focal length (inverse of focalLengthFromFov). */\nexport function fovFromFocalLength(mm: number): number {\n return (2 * Math.atan(24 / 2 / Math.max(1, mm)) * 180) / Math.PI;\n}\n\nexport const lightingOf = (project: Pick<SetProject, 'lighting'>): SetLighting => project.lighting ?? DEFAULT_LIGHTING;\n\nexport function newSet(title = 'Untitled set'): SetProject {\n return {\n version: 1,\n id: `set-${Date.now().toString(36)}`,\n title,\n objects: [],\n world: { rotationDeg: 0, background: '#1a1a1e', showGround: true },\n camera: {\n position: { ...DEFAULT_CAMERA.position },\n target: { ...DEFAULT_CAMERA.target },\n fov: DEFAULT_CAMERA.fov,\n },\n lighting: { ...DEFAULT_LIGHTING },\n aspect: '16:9',\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AASO,MAAM,OAAO,CAAC,CAAA,GAAI,GAAG,CAAI,GAAA,CAAA,EAAG,IAAI,CAAa,MAAA;AAAA,EAClD,CAAA;AAAA,EACA,CAAA;AAAA,EACA;AACF,CAAA;AAsDO,MAAM,cAA4B,GAAA;AAAA,EACvC,QAAU,EAAA,IAAA,CAAK,CAAG,EAAA,GAAA,EAAK,GAAG,CAAA;AAAA,EAC1B,MAAQ,EAAA,IAAA,CAAK,CAAG,EAAA,GAAA,EAAK,CAAC,CAAA;AAAA,EACtB,GAAK,EAAA;AACP;AACO,MAAM,gBAAgC,GAAA;AAAA,EAC3C,aAAe,EAAA,GAAA;AAAA,EACf,eAAiB,EAAA,EAAA;AAAA,EACjB,YAAc,EAAA,GAAA;AAAA,EACd,gBAAkB,EAAA;AACpB;AAGO,MAAM,oBAAuB,GAAA;AAG7B,MAAM,cAAc,CAAC,MAAA,EAAQ,QAAQ,KAAO,EAAA,KAAA,EAAO,OAAO,MAAM;AACvE,IAAI,SAAY,GAAA,CAAA;AAGH,MAAA,WAAA,GAAc,MAAc,CAAA,GAAA,EAAM,IAAK,CAAA,GAAA,GAAM,QAAS,CAAA,EAAE,CAAC,CAAA,CAAA,EAAI,SAAW,EAAA,CAAA;AAG9E,SAAS,mBAAmB,MAAwB,EAAA;AACzD,EAAO,OAAA,IAAA,CAAK,KAAM,CAAA,EAAA,GAAK,CAAI,GAAA,IAAA,CAAK,IAAI,MAAS,GAAA,IAAA,CAAK,EAAK,GAAA,GAAG,CAAC,CAAA;AAC7D;AAGO,SAAS,mBAAmB,EAAoB,EAAA;AACrD,EAAA,OAAO,CAAI,GAAA,IAAA,CAAK,IAAK,CAAA,EAAA,GAAK,CAAI,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,EAAE,CAAC,CAAI,GAAA,GAAA,GAAM,IAAK,CAAA,EAAA;AAC9D;AACa,MAAA,UAAA,GAAa,CAAC,OAAoD,KAAA;AAlG/E,EAAA,IAAA,EAAA;AAkGkF,EAAA,OAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,aAAR,IAAoB,GAAA,EAAA,GAAA,gBAAA;AAAA;AACtF,SAAA,MAAA,CAAO,QAAQ,cAA4B,EAAA;AACzD,EAAO,OAAA;AAAA,IACL,OAAS,EAAA,CAAA;AAAA,IACT,IAAI,CAAO,IAAA,EAAA,IAAA,CAAK,KAAM,CAAA,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA;AAAA,IAClC,KAAA;AAAA,IACA,SAAS,EAAC;AAAA,IACV,KAAO,EAAA;AAAA,MACL,WAAa,EAAA,CAAA;AAAA,MACb,UAAY,EAAA,SAAA;AAAA,MACZ,UAAY,EAAA;AAAA,KACd;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,QAAA,EAAU,mBACL,cAAe,CAAA,QAAA,CAAA;AAAA,MAEpB,MAAA,EAAQ,mBACH,cAAe,CAAA,MAAA,CAAA;AAAA,MAEpB,KAAK,cAAe,CAAA;AAAA,KACtB;AAAA,IACA,UAAU,cACL,CAAA,EAAA,EAAA,gBAAA,CAAA;AAAA,IAEL,MAAQ,EAAA;AAAA,GACV;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {gql}from'@apollo/client/index.js';import {STUDIO_TEMPLATE_PAGE_SIZE,playableTemplatePreviewUrl}from'./canvasChatTemplates.js';import {isInVideoTemplate}from'./templateImport/invideoNative.js';import {renderConfigLinks}from'./templateImport/renderConfig.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {gql}from'@apollo/client/index.js';import {STUDIO_TEMPLATE_PAGE_SIZE,playableTemplatePreviewUrl}from'./canvasChatTemplates.js';import {isInVideoTemplate}from'./templateImport/invideoNative.js';import {renderConfigLinks}from'./templateImport/renderConfig.js';import {rankedCatalogSearch}from'./rankedCatalogSearch.js';export{POPULAR_OFFSET,fetchCatalogRead}from'./rankedCatalogSearch.js';import {parseTemplateQuery,TEMPLATE_CATEGORY_WORDS}from'./templateSearch.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
3
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
4
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +14,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
+
var _a;
|
|
17
18
|
const STUDIO_CATALOG_GROUP = "video-studio";
|
|
18
19
|
const STUDIO_CATALOG_PREFIX = "video-studio-";
|
|
19
20
|
const STUDIO_CATALOG_QUERY = gql`
|
|
@@ -118,12 +119,12 @@ function catalogRowToStudioTemplate(row) {
|
|
|
118
119
|
}
|
|
119
120
|
function studioTemplatesToCatalogNodes(rows) {
|
|
120
121
|
return rows.map((row) => {
|
|
121
|
-
var
|
|
122
|
+
var _a2, _b, _c;
|
|
122
123
|
return {
|
|
123
124
|
__typename: "FormTemplateSubmission",
|
|
124
125
|
id: row.id,
|
|
125
126
|
name: row.id.startsWith(STUDIO_CATALOG_PREFIX) ? row.id : `${STUDIO_CATALOG_PREFIX}${row.id}`,
|
|
126
|
-
description: (
|
|
127
|
+
description: (_a2 = row.description) != null ? _a2 : null,
|
|
127
128
|
category: (_b = row.category) != null ? _b : null,
|
|
128
129
|
tags: (_c = row.tags) != null ? _c : null,
|
|
129
130
|
formData: {
|
|
@@ -139,4 +140,58 @@ function studioTemplatesToCatalogNodes(rows) {
|
|
|
139
140
|
}
|
|
140
141
|
};
|
|
141
142
|
});
|
|
142
|
-
}
|
|
143
|
+
}
|
|
144
|
+
const STUDIO_CATEGORY_WORDS = (_a = TEMPLATE_CATEGORY_WORDS.videoGeneration) != null ? _a : ["video"];
|
|
145
|
+
function isRankedStudioSearch(search) {
|
|
146
|
+
return !parseTemplateQuery(search != null ? search : "", {
|
|
147
|
+
categoryWords: STUDIO_CATEGORY_WORDS
|
|
148
|
+
}).empty;
|
|
149
|
+
}
|
|
150
|
+
function apolloCatalogRead(client) {
|
|
151
|
+
const documents = /* @__PURE__ */ new Map();
|
|
152
|
+
return async (variables, query) => {
|
|
153
|
+
var _a2, _b;
|
|
154
|
+
let document = documents.get(query);
|
|
155
|
+
if (!document) {
|
|
156
|
+
document = gql(query);
|
|
157
|
+
documents.set(query, document);
|
|
158
|
+
}
|
|
159
|
+
const result = await client.query({
|
|
160
|
+
query: document,
|
|
161
|
+
variables,
|
|
162
|
+
fetchPolicy: "network-only",
|
|
163
|
+
errorPolicy: "all"
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
data: (_a2 = result.data) != null ? _a2 : null,
|
|
167
|
+
errors: (_b = result.errors) != null ? _b : null
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
async function rankedStudioCatalogPage(search, offset, read, limit = STUDIO_TEMPLATE_PAGE_SIZE) {
|
|
172
|
+
const page = await rankedCatalogSearch({
|
|
173
|
+
group: STUDIO_CATALOG_GROUP,
|
|
174
|
+
query: search,
|
|
175
|
+
limit,
|
|
176
|
+
offset,
|
|
177
|
+
read,
|
|
178
|
+
categoryWords: STUDIO_CATEGORY_WORDS,
|
|
179
|
+
accept: (row) => catalogRowToStudioTemplate(row) !== null
|
|
180
|
+
});
|
|
181
|
+
const rows = [];
|
|
182
|
+
const matches = [];
|
|
183
|
+
for (const {
|
|
184
|
+
row,
|
|
185
|
+
match
|
|
186
|
+
} of page.rows) {
|
|
187
|
+
const template = catalogRowToStudioTemplate(row);
|
|
188
|
+
if (!template) continue;
|
|
189
|
+
rows.push(template);
|
|
190
|
+
matches.push(match);
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
rows,
|
|
194
|
+
matches,
|
|
195
|
+
next: page.next
|
|
196
|
+
};
|
|
197
|
+
}export{PUBLISHED_STATUS,STUDIO_CATALOG_GROUP,STUDIO_CATALOG_PREFIX,STUDIO_CATALOG_QUERY,STUDIO_CATEGORY_WORDS,STUDIO_TEMPLATE_PAGE_SIZE,TEMPLATE_CATEGORY_WORDS,apolloCatalogRead,catalogRowToStudioTemplate,catalogSearch,isRankedStudioSearch,parseTemplateQuery,rankedCatalogSearch,rankedStudioCatalogPage,studioCatalogFilter,studioTemplatesToCatalogNodes};//# sourceMappingURL=studioCatalog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"studioCatalog.js","sources":["../../../src/features/canvas/studioCatalog.ts"],"sourcesContent":["/**\n * Video-studio marketplace rows — same GraphQL field as browser `/c/new`\n * (`formTemplateSubmissions`, group `video-studio`). Apollo typePolicies key by\n * group + search and merge pages by offset so leaving Canvas and coming back\n * is cache-first, not a connector round-trip.\n */\nimport { gql } from '@apollo/client';\nimport type { CanvasPromptTemplate } from './canvasChatTemplates';\nimport { STUDIO_TEMPLATE_PAGE_SIZE, playableTemplatePreviewUrl } from './canvasChatTemplates';\nimport { isInVideoTemplate } from './templateImport/invideoNative';\nimport { renderConfigLinks } from './templateImport/renderConfig';\n\nexport const STUDIO_CATALOG_GROUP = 'video-studio';\nexport const STUDIO_CATALOG_PREFIX = 'video-studio-';\nexport { STUDIO_TEMPLATE_PAGE_SIZE };\n\nexport const STUDIO_CATALOG_QUERY = gql`\n query StudioCatalogTemplates($filter: FormTemplateSubmissionFilter) {\n formTemplateSubmissions(filter: $filter) {\n nodes {\n id\n name\n description\n category\n tags\n formData\n }\n }\n }\n`;\n\nexport interface StudioCatalogRow {\n id?: string | null;\n name?: string | null;\n description?: string | null;\n category?: string | null;\n tags?: Array<string | null> | null;\n formData?: unknown;\n}\n\nexport interface StudioCatalogFilter {\n group: string;\n status: typeof PUBLISHED_STATUS;\n limit: number;\n offset: number;\n search?: string;\n}\n\n/** Only published rows reach a page: never a draft (surface-kit `catalogRead`). */\nexport const PUBLISHED_STATUS = 'published';\n\n/**\n * Search words as the backend resolver matches them (surface-kit\n * `catalogSearch`): it matches ONE regex against the slugged row name, so\n * words join with '-' (\"real estate\" found 0, \"real-estate\" 191) and only\n * letters/digits survive (\"c++\" or \"(\" broke the regex).\n */\nexport function catalogSearch(query: string | undefined): string | undefined {\n const words = (query ?? '').split(NON_WORD).filter(Boolean);\n return words.length ? words.join('-') : undefined;\n}\n\nconst NON_WORD: RegExp = (() => {\n try {\n return new RegExp('[^\\\\p{L}\\\\p{N}]+', 'u');\n } catch {\n // Engines without Unicode property escapes: ASCII plus Latin-1 letters.\n return /[^A-Za-z0-9\\u00C0-\\u024F]+/;\n }\n})();\n\nexport function studioCatalogFilter(\n search: string,\n offset = 0,\n limit = STUDIO_TEMPLATE_PAGE_SIZE,\n): StudioCatalogFilter {\n const term = catalogSearch(search);\n return {\n group: STUDIO_CATALOG_GROUP,\n status: PUBLISHED_STATUS,\n limit,\n offset,\n ...(term ? { search: term } : {}),\n };\n}\n\nfunction str(value: unknown): string {\n return typeof value === 'string' ? value.trim() : '';\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n}\n\nfunction parseFormData(value: unknown): Record<string, unknown> {\n if (typeof value === 'string') {\n try {\n return record(JSON.parse(value));\n } catch {\n return {};\n }\n }\n return record(value);\n}\n\nfunction clipSrcs(formData: Record<string, unknown>): string[] {\n const composition = record(formData.composition);\n const direct = Array.isArray(composition.clips) ? composition.clips : [];\n const nested = Array.isArray(composition.tracks)\n ? composition.tracks.flatMap((track) => {\n const clips = record(track).clips;\n return Array.isArray(clips) ? clips : [];\n })\n : [];\n return [...direct, ...nested].map((clip) => str(record(clip).src)).filter(Boolean);\n}\n\nexport function catalogRowToStudioTemplate(row: StudioCatalogRow): CanvasPromptTemplate | null {\n const formData = parseFormData(row.formData);\n const details = record(formData.generationDetails);\n const generation = record(formData.generation);\n const name = str(row.name);\n const id = name.startsWith(STUDIO_CATALOG_PREFIX) ? name.slice(STUDIO_CATALOG_PREFIX.length) : name || str(row.id);\n const title = str(details.title) || name || str(row.id);\n const prompt = str(generation.prompt) || str(row.description) || title;\n if (!id || !title) return null;\n\n const renderConfigRaw = formData.renderConfig;\n const renderConfig =\n typeof renderConfigRaw === 'string'\n ? (() => {\n try {\n return record(JSON.parse(renderConfigRaw));\n } catch {\n return {};\n }\n })()\n : record(renderConfigRaw);\n const usableConfig =\n Object.keys(renderConfig).length > 0 && isInVideoTemplate(renderConfig) ? renderConfig : undefined;\n const links = usableConfig ? undefined : renderConfigLinks(renderConfig);\n\n return {\n id,\n kind: 'video',\n title,\n description: str(details.summary) || str(row.description) || undefined,\n cover: str(details.previewUrl) || str(details.cover) || undefined,\n coverVideo: playableTemplatePreviewUrl(\n str(details.previewVideoUrl),\n str(formData.coverVideo),\n str(generation.coverVideo),\n str(generation.videoUrl),\n ...clipSrcs(formData),\n ),\n aspect: str(details.aspect) || str(generation.aspectRatio) || str(formData.aspect) || undefined,\n prompt,\n category: str(row.category) || undefined,\n tags: Array.isArray(row.tags) ? row.tags.filter((tag): tag is string => typeof tag === 'string') : undefined,\n ...(usableConfig ? { renderConfig: usableConfig } : {}),\n ...(links\n ? {\n configUrls: links.configUrls,\n ...(links.defaultAspect ? { defaultAspect: links.defaultAspect } : {}),\n }\n : {}),\n };\n}\n\nexport function studioTemplatesToCatalogNodes(rows: readonly CanvasPromptTemplate[]): StudioCatalogRow[] {\n return rows.map((row) => ({\n __typename: 'FormTemplateSubmission',\n id: row.id,\n name: row.id.startsWith(STUDIO_CATALOG_PREFIX) ? row.id : `${STUDIO_CATALOG_PREFIX}${row.id}`,\n description: row.description ?? null,\n category: row.category ?? null,\n tags: row.tags ?? null,\n formData: {\n generationDetails: {\n title: row.title,\n summary: row.description,\n previewUrl: row.cover,\n previewVideoUrl: row.coverVideo,\n },\n generation: { prompt: row.prompt },\n },\n }));\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"studioCatalog.js","sources":["../../../src/features/canvas/studioCatalog.ts"],"sourcesContent":["/**\n * Video-studio marketplace rows — same GraphQL field as browser `/c/new`\n * (`formTemplateSubmissions`, group `video-studio`). Apollo typePolicies key by\n * group + search and merge pages by offset so leaving Canvas and coming back\n * is cache-first, not a connector round-trip.\n */\nimport { gql } from '@apollo/client';\nimport type { CanvasPromptTemplate } from './canvasChatTemplates';\nimport { STUDIO_TEMPLATE_PAGE_SIZE, playableTemplatePreviewUrl } from './canvasChatTemplates';\nimport { isInVideoTemplate } from './templateImport/invideoNative';\nimport { renderConfigLinks } from './templateImport/renderConfig';\nimport { rankedCatalogSearch, type CatalogGraphqlAnswer, type CatalogGraphqlRead } from './rankedCatalogSearch';\nimport { parseTemplateQuery, TEMPLATE_CATEGORY_WORDS, type TemplateMatch } from './templateSearch';\n\nexport const STUDIO_CATALOG_GROUP = 'video-studio';\nexport const STUDIO_CATALOG_PREFIX = 'video-studio-';\nexport { STUDIO_TEMPLATE_PAGE_SIZE };\n\nexport const STUDIO_CATALOG_QUERY = gql`\n query StudioCatalogTemplates($filter: FormTemplateSubmissionFilter) {\n formTemplateSubmissions(filter: $filter) {\n nodes {\n id\n name\n description\n category\n tags\n formData\n }\n }\n }\n`;\n\nexport interface StudioCatalogRow {\n id?: string | null;\n name?: string | null;\n description?: string | null;\n category?: string | null;\n tags?: Array<string | null> | null;\n formData?: unknown;\n}\n\nexport interface StudioCatalogFilter {\n group: string;\n status: typeof PUBLISHED_STATUS;\n limit: number;\n offset: number;\n search?: string;\n}\n\n/** Only published rows reach a page: never a draft (surface-kit `catalogRead`). */\nexport const PUBLISHED_STATUS = 'published';\n\n/**\n * Search words as the backend resolver matches them (surface-kit\n * `catalogSearch`): it matches ONE regex against the slugged row name, so\n * words join with '-' (\"real estate\" found 0, \"real-estate\" 191) and only\n * letters/digits survive (\"c++\" or \"(\" broke the regex).\n */\nexport function catalogSearch(query: string | undefined): string | undefined {\n const words = (query ?? '').split(NON_WORD).filter(Boolean);\n return words.length ? words.join('-') : undefined;\n}\n\nconst NON_WORD: RegExp = (() => {\n try {\n return new RegExp('[^\\\\p{L}\\\\p{N}]+', 'u');\n } catch {\n // Engines without Unicode property escapes: ASCII plus Latin-1 letters.\n return /[^A-Za-z0-9\\u00C0-\\u024F]+/;\n }\n})();\n\nexport function studioCatalogFilter(\n search: string,\n offset = 0,\n limit = STUDIO_TEMPLATE_PAGE_SIZE,\n): StudioCatalogFilter {\n const term = catalogSearch(search);\n return {\n group: STUDIO_CATALOG_GROUP,\n status: PUBLISHED_STATUS,\n limit,\n offset,\n ...(term ? { search: term } : {}),\n };\n}\n\nfunction str(value: unknown): string {\n return typeof value === 'string' ? value.trim() : '';\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n}\n\nfunction parseFormData(value: unknown): Record<string, unknown> {\n if (typeof value === 'string') {\n try {\n return record(JSON.parse(value));\n } catch {\n return {};\n }\n }\n return record(value);\n}\n\nfunction clipSrcs(formData: Record<string, unknown>): string[] {\n const composition = record(formData.composition);\n const direct = Array.isArray(composition.clips) ? composition.clips : [];\n const nested = Array.isArray(composition.tracks)\n ? composition.tracks.flatMap((track) => {\n const clips = record(track).clips;\n return Array.isArray(clips) ? clips : [];\n })\n : [];\n return [...direct, ...nested].map((clip) => str(record(clip).src)).filter(Boolean);\n}\n\nexport function catalogRowToStudioTemplate(row: StudioCatalogRow): CanvasPromptTemplate | null {\n const formData = parseFormData(row.formData);\n const details = record(formData.generationDetails);\n const generation = record(formData.generation);\n const name = str(row.name);\n const id = name.startsWith(STUDIO_CATALOG_PREFIX) ? name.slice(STUDIO_CATALOG_PREFIX.length) : name || str(row.id);\n const title = str(details.title) || name || str(row.id);\n const prompt = str(generation.prompt) || str(row.description) || title;\n if (!id || !title) return null;\n\n const renderConfigRaw = formData.renderConfig;\n const renderConfig =\n typeof renderConfigRaw === 'string'\n ? (() => {\n try {\n return record(JSON.parse(renderConfigRaw));\n } catch {\n return {};\n }\n })()\n : record(renderConfigRaw);\n const usableConfig =\n Object.keys(renderConfig).length > 0 && isInVideoTemplate(renderConfig) ? renderConfig : undefined;\n const links = usableConfig ? undefined : renderConfigLinks(renderConfig);\n\n return {\n id,\n kind: 'video',\n title,\n description: str(details.summary) || str(row.description) || undefined,\n cover: str(details.previewUrl) || str(details.cover) || undefined,\n coverVideo: playableTemplatePreviewUrl(\n str(details.previewVideoUrl),\n str(formData.coverVideo),\n str(generation.coverVideo),\n str(generation.videoUrl),\n ...clipSrcs(formData),\n ),\n aspect: str(details.aspect) || str(generation.aspectRatio) || str(formData.aspect) || undefined,\n prompt,\n category: str(row.category) || undefined,\n tags: Array.isArray(row.tags) ? row.tags.filter((tag): tag is string => typeof tag === 'string') : undefined,\n ...(usableConfig ? { renderConfig: usableConfig } : {}),\n ...(links\n ? {\n configUrls: links.configUrls,\n ...(links.defaultAspect ? { defaultAspect: links.defaultAspect } : {}),\n }\n : {}),\n };\n}\n\nexport function studioTemplatesToCatalogNodes(rows: readonly CanvasPromptTemplate[]): StudioCatalogRow[] {\n return rows.map((row) => ({\n __typename: 'FormTemplateSubmission',\n id: row.id,\n name: row.id.startsWith(STUDIO_CATALOG_PREFIX) ? row.id : `${STUDIO_CATALOG_PREFIX}${row.id}`,\n description: row.description ?? null,\n category: row.category ?? null,\n tags: row.tags ?? null,\n formData: {\n generationDetails: {\n title: row.title,\n summary: row.description,\n previewUrl: row.cover,\n previewVideoUrl: row.coverVideo,\n },\n generation: { prompt: row.prompt },\n },\n }));\n}\n\n// ─── Ranked search ──────────────────────────────────────────────────────────\n// The backend search keeps only rows holding EVERY word, unranked (\"clean modern\n// fancy\" found 0). A typed search goes through the ranked search instead\n// (./rankedCatalogSearch); no search keeps the plain `studioCatalogFilter` paging.\n\nexport {\n rankedCatalogSearch,\n fetchCatalogRead,\n clearRankedCatalogSearchCache,\n POPULAR_OFFSET,\n type CatalogGraphqlRead,\n type CatalogGraphqlAnswer,\n type RankedCatalogPage,\n type RankedCatalogRow,\n type RankedCatalogSearchParams,\n} from './rankedCatalogSearch';\nexport { parseTemplateQuery, TEMPLATE_CATEGORY_WORDS, type TemplateMatch, type TemplateQuery } from './templateSearch';\n\n/** Words that name the video catalog: \"video templates\" inside it is no search. */\nexport const STUDIO_CATEGORY_WORDS: readonly string[] = TEMPLATE_CATEGORY_WORDS.videoGeneration ?? ['video'];\n\n/** True when `search` holds a word worth ranking (not empty, not only filler or \"video\"). */\nexport function isRankedStudioSearch(search: string | undefined): boolean {\n return !parseTemplateQuery(search ?? '', { categoryWords: STUDIO_CATEGORY_WORDS }).empty;\n}\n\n/** Host Apollo client, as far as a catalog read needs it. */\nexport interface CatalogApolloClient {\n query: (options: any) => Promise<{ data?: unknown; errors?: ReadonlyArray<{ message?: string }> }>;\n}\n\n/** A `CatalogGraphqlRead` over the host Apollo client (network-only: ranked reads are not cached by Apollo). */\nexport function apolloCatalogRead(client: CatalogApolloClient): CatalogGraphqlRead {\n const documents = new Map<string, ReturnType<typeof gql>>();\n return async (variables, query) => {\n let document = documents.get(query);\n if (!document) {\n document = gql(query);\n documents.set(query, document);\n }\n const result = await client.query({\n query: document,\n variables,\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n });\n return {\n data: (result.data ?? null) as CatalogGraphqlAnswer['data'],\n errors: result.errors ?? null,\n };\n };\n}\n\n/** One ranked page of the video-studio catalog, as templates, with where the next page starts. */\nexport async function rankedStudioCatalogPage(\n search: string,\n offset: number,\n read: CatalogGraphqlRead,\n limit = STUDIO_TEMPLATE_PAGE_SIZE,\n): Promise<{ rows: CanvasPromptTemplate[]; matches: TemplateMatch[]; next: number | null }> {\n const page = await rankedCatalogSearch({\n group: STUDIO_CATALOG_GROUP,\n query: search,\n limit,\n offset,\n read,\n categoryWords: STUDIO_CATEGORY_WORDS,\n accept: (row) => catalogRowToStudioTemplate(row as StudioCatalogRow) !== null,\n });\n const rows: CanvasPromptTemplate[] = [];\n const matches: TemplateMatch[] = [];\n for (const { row, match } of page.rows) {\n const template = catalogRowToStudioTemplate(row as StudioCatalogRow);\n if (!template) continue;\n rows.push(template);\n matches.push(match);\n }\n return { rows, matches, next: page.next };\n}\n"],"names":["_a"],"mappings":";;;;;;;;;;;;;;;;AAAA,IAAA,EAAA;AAaO,MAAM,oBAAuB,GAAA;AAC7B,MAAM,qBAAwB,GAAA;AAE9B,MAAM,oBAAuB,GAAA,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+B7B,MAAM,gBAAmB,GAAA;AAQzB,SAAS,cAAc,KAA+C,EAAA;AAC3E,EAAA,MAAM,SAAS,KAAS,IAAA,IAAA,GAAA,KAAA,GAAA,EAAA,EAAI,MAAM,QAAQ,CAAA,CAAE,OAAO,OAAO,CAAA;AAC1D,EAAA,OAAO,KAAM,CAAA,MAAA,GAAS,KAAM,CAAA,IAAA,CAAK,GAAG,CAAI,GAAA,MAAA;AAC1C;AACA,MAAM,YAAoB,MAAM;AAC9B,EAAI,IAAA;AACF,IAAO,OAAA,IAAI,MAAO,CAAA,kBAAA,EAAoB,GAAG,CAAA;AAAA,GACnC,CAAA,OAAA,CAAA,EAAA;AAEN,IAAO,OAAA,4BAAA;AAAA;AAEX,CAAG,GAAA;AACI,SAAS,mBAAoB,CAAA,MAAA,EAAgB,MAAS,GAAA,CAAA,EAAG,QAAQ,yBAAgD,EAAA;AACtH,EAAM,MAAA,IAAA,GAAO,cAAc,MAAM,CAAA;AACjC,EAAO,OAAA,cAAA,CAAA;AAAA,IACL,KAAO,EAAA,oBAAA;AAAA,IACP,MAAQ,EAAA,gBAAA;AAAA,IACR,KAAA;AAAA,IACA;AAAA,GAAA,EACI,IAAO,GAAA;AAAA,IACT,MAAQ,EAAA;AAAA,MACN,EAAC,CAAA;AAET;AACA,SAAS,IAAI,KAAwB,EAAA;AACnC,EAAA,OAAO,OAAO,KAAA,KAAU,QAAW,GAAA,KAAA,CAAM,MAAS,GAAA,EAAA;AACpD;AACA,SAAS,OAAO,KAAyC,EAAA;AACvD,EAAO,OAAA,KAAA,IAAS,OAAO,KAAA,KAAU,QAAY,IAAA,CAAC,MAAM,OAAQ,CAAA,KAAK,CAAI,GAAA,KAAA,GAAmC,EAAC;AAC3G;AACA,SAAS,cAAc,KAAyC,EAAA;AAC9D,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAI,IAAA;AACF,MAAA,OAAO,MAAO,CAAA,IAAA,CAAK,KAAM,CAAA,KAAK,CAAC,CAAA;AAAA,KACzB,CAAA,OAAA,CAAA,EAAA;AACN,MAAA,OAAO,EAAC;AAAA;AACV;AAEF,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB;AACA,SAAS,SAAS,QAA6C,EAAA;AAC7D,EAAM,MAAA,WAAA,GAAc,MAAO,CAAA,QAAA,CAAS,WAAW,CAAA;AAC/C,EAAM,MAAA,MAAA,GAAS,MAAM,OAAQ,CAAA,WAAA,CAAY,KAAK,CAAI,GAAA,WAAA,CAAY,QAAQ,EAAC;AACvE,EAAM,MAAA,MAAA,GAAS,MAAM,OAAQ,CAAA,WAAA,CAAY,MAAM,CAAI,GAAA,WAAA,CAAY,MAAO,CAAA,OAAA,CAAQ,CAAS,KAAA,KAAA;AACrF,IAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,KAAK,CAAE,CAAA,KAAA;AAC5B,IAAA,OAAO,KAAM,CAAA,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,EAAC;AAAA,GACxC,IAAI,EAAC;AACN,EAAA,OAAO,CAAC,GAAG,MAAA,EAAQ,GAAG,MAAM,EAAE,GAAI,CAAA,CAAA,IAAA,KAAQ,GAAI,CAAA,MAAA,CAAO,IAAI,CAAE,CAAA,GAAG,CAAC,CAAA,CAAE,OAAO,OAAO,CAAA;AACjF;AACO,SAAS,2BAA2B,GAAoD,EAAA;AAC7F,EAAM,MAAA,QAAA,GAAW,aAAc,CAAA,GAAA,CAAI,QAAQ,CAAA;AAC3C,EAAM,MAAA,OAAA,GAAU,MAAO,CAAA,QAAA,CAAS,iBAAiB,CAAA;AACjD,EAAM,MAAA,UAAA,GAAa,MAAO,CAAA,QAAA,CAAS,UAAU,CAAA;AAC7C,EAAM,MAAA,IAAA,GAAO,GAAI,CAAA,GAAA,CAAI,IAAI,CAAA;AACzB,EAAA,MAAM,EAAK,GAAA,IAAA,CAAK,UAAW,CAAA,qBAAqB,CAAI,GAAA,IAAA,CAAK,KAAM,CAAA,qBAAA,CAAsB,MAAM,CAAA,GAAI,IAAQ,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACjH,EAAM,MAAA,KAAA,GAAQ,IAAI,OAAQ,CAAA,KAAK,KAAK,IAAQ,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACtD,EAAM,MAAA,MAAA,GAAS,IAAI,UAAW,CAAA,MAAM,KAAK,GAAI,CAAA,GAAA,CAAI,WAAW,CAAK,IAAA,KAAA;AACjE,EAAA,IAAI,CAAC,EAAA,IAAM,CAAC,KAAA,EAAc,OAAA,IAAA;AAC1B,EAAA,MAAM,kBAAkB,QAAS,CAAA,YAAA;AACjC,EAAA,MAAM,YAAe,GAAA,OAAO,eAAoB,KAAA,QAAA,GAAA,CAAY,MAAM;AAChE,IAAI,IAAA;AACF,MAAA,OAAO,MAAO,CAAA,IAAA,CAAK,KAAM,CAAA,eAAe,CAAC,CAAA;AAAA,KACnC,CAAA,OAAA,CAAA,EAAA;AACN,MAAA,OAAO,EAAC;AAAA;AACV,GACF,GAAO,GAAA,MAAA,CAAO,eAAe,CAAA;AAC7B,EAAM,MAAA,YAAA,GAAe,MAAO,CAAA,IAAA,CAAK,YAAY,CAAA,CAAE,SAAS,CAAK,IAAA,iBAAA,CAAkB,YAAY,CAAA,GAAI,YAAe,GAAA,MAAA;AAC9G,EAAA,MAAM,KAAQ,GAAA,YAAA,GAAe,MAAY,GAAA,iBAAA,CAAkB,YAAY,CAAA;AACvE,EAAO,OAAA,cAAA,CAAA,cAAA,CAAA;AAAA,IACL,EAAA;AAAA,IACA,IAAM,EAAA,OAAA;AAAA,IACN,KAAA;AAAA,IACA,WAAA,EAAa,IAAI,OAAQ,CAAA,OAAO,KAAK,GAAI,CAAA,GAAA,CAAI,WAAW,CAAK,IAAA,MAAA;AAAA,IAC7D,KAAA,EAAO,IAAI,OAAQ,CAAA,UAAU,KAAK,GAAI,CAAA,OAAA,CAAQ,KAAK,CAAK,IAAA,MAAA;AAAA,IACxD,UAAA,EAAY,2BAA2B,GAAI,CAAA,OAAA,CAAQ,eAAe,CAAG,EAAA,GAAA,CAAI,SAAS,UAAU,CAAA,EAAG,IAAI,UAAW,CAAA,UAAU,GAAG,GAAI,CAAA,UAAA,CAAW,QAAQ,CAAG,EAAA,GAAG,QAAS,CAAA,QAAQ,CAAC,CAAA;AAAA,IAC1K,MAAQ,EAAA,GAAA,CAAI,OAAQ,CAAA,MAAM,CAAK,IAAA,GAAA,CAAI,UAAW,CAAA,WAAW,CAAK,IAAA,GAAA,CAAI,QAAS,CAAA,MAAM,CAAK,IAAA,MAAA;AAAA,IACtF,MAAA;AAAA,IACA,QAAU,EAAA,GAAA,CAAI,GAAI,CAAA,QAAQ,CAAK,IAAA,MAAA;AAAA,IAC/B,IAAM,EAAA,KAAA,CAAM,OAAQ,CAAA,GAAA,CAAI,IAAI,CAAI,GAAA,GAAA,CAAI,IAAK,CAAA,MAAA,CAAO,CAAC,GAAA,KAAuB,OAAO,GAAA,KAAQ,QAAQ,CAAI,GAAA;AAAA,GAAA,EAC/F,YAAe,GAAA;AAAA,IACjB,YAAc,EAAA;AAAA,GAChB,GAAI,EAAC,CAAA,EACD,KAAQ,GAAA,cAAA,CAAA;AAAA,IACV,YAAY,KAAM,CAAA;AAAA,GAAA,EACd,MAAM,aAAgB,GAAA;AAAA,IACxB,eAAe,KAAM,CAAA;AAAA,GACvB,GAAI,EAAC,CAAA,GACH,EAAC,CAAA;AAET;AACO,SAAS,8BAA8B,IAA2D,EAAA;AACvG,EAAO,OAAA,IAAA,CAAK,IAAI,CAAI,GAAA,KAAA;AAlJtB,IAAA,IAAAA,GAAA,EAAA,EAAA,EAAA,EAAA;AAkJ0B,IAAA,OAAA;AAAA,MACtB,UAAY,EAAA,wBAAA;AAAA,MACZ,IAAI,GAAI,CAAA,EAAA;AAAA,MACR,IAAM,EAAA,GAAA,CAAI,EAAG,CAAA,UAAA,CAAW,qBAAqB,CAAA,GAAI,GAAI,CAAA,EAAA,GAAK,CAAG,EAAA,qBAAqB,CAAG,EAAA,GAAA,CAAI,EAAE,CAAA,CAAA;AAAA,MAC3F,WAAaA,EAAAA,CAAAA,GAAAA,GAAA,GAAI,CAAA,WAAA,KAAJ,OAAAA,GAAmB,GAAA,IAAA;AAAA,MAChC,QAAA,EAAA,CAAU,EAAI,GAAA,GAAA,CAAA,QAAA,KAAJ,IAAgB,GAAA,EAAA,GAAA,IAAA;AAAA,MAC1B,IAAA,EAAA,CAAM,EAAI,GAAA,GAAA,CAAA,IAAA,KAAJ,IAAY,GAAA,EAAA,GAAA,IAAA;AAAA,MAClB,QAAU,EAAA;AAAA,QACR,iBAAmB,EAAA;AAAA,UACjB,OAAO,GAAI,CAAA,KAAA;AAAA,UACX,SAAS,GAAI,CAAA,WAAA;AAAA,UACb,YAAY,GAAI,CAAA,KAAA;AAAA,UAChB,iBAAiB,GAAI,CAAA;AAAA,SACvB;AAAA,QACA,UAAY,EAAA;AAAA,UACV,QAAQ,GAAI,CAAA;AAAA;AACd;AACF,KACF;AAAA,GAAE,CAAA;AACJ;AAWO,MAAM,qBAA2C,GAAA,CAAA,EAAA,GAAA,uBAAA,CAAwB,eAAxB,KAAA,IAAA,GAAA,EAAA,GAA2C,CAAC,OAAO;AAGpG,SAAS,qBAAqB,MAAqC,EAAA;AACxE,EAAO,OAAA,CAAC,kBAAmB,CAAA,MAAA,IAAA,IAAA,GAAA,MAAA,GAAU,EAAI,EAAA;AAAA,IACvC,aAAe,EAAA;AAAA,GAChB,CAAE,CAAA,KAAA;AACL;AAaO,SAAS,kBAAkB,MAAiD,EAAA;AACjF,EAAM,MAAA,SAAA,uBAAgB,GAAoC,EAAA;AAC1D,EAAO,OAAA,OAAO,WAAW,KAAU,KAAA;AAtMrC,IAAA,IAAAA,GAAA,EAAA,EAAA;AAuMI,IAAI,IAAA,QAAA,GAAW,SAAU,CAAA,GAAA,CAAI,KAAK,CAAA;AAClC,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,QAAA,GAAW,IAAI,KAAK,CAAA;AACpB,MAAU,SAAA,CAAA,GAAA,CAAI,OAAO,QAAQ,CAAA;AAAA;AAE/B,IAAM,MAAA,MAAA,GAAS,MAAM,MAAA,CAAO,KAAM,CAAA;AAAA,MAChC,KAAO,EAAA,QAAA;AAAA,MACP,SAAA;AAAA,MACA,WAAa,EAAA,cAAA;AAAA,MACb,WAAa,EAAA;AAAA,KACd,CAAA;AACD,IAAO,OAAA;AAAA,MACL,IAAOA,EAAAA,CAAAA,GAAAA,GAAA,MAAO,CAAA,IAAA,KAAP,OAAAA,GAAe,GAAA,IAAA;AAAA,MACtB,MAAA,EAAA,CAAQ,EAAO,GAAA,MAAA,CAAA,MAAA,KAAP,IAAiB,GAAA,EAAA,GAAA;AAAA,KAC3B;AAAA,GACF;AACF;AAGA,eAAsB,uBAAwB,CAAA,MAAA,EAAgB,MAAgB,EAAA,IAAA,EAA0B,QAAQ,yBAI7G,EAAA;AACD,EAAM,MAAA,IAAA,GAAO,MAAM,mBAAoB,CAAA;AAAA,IACrC,KAAO,EAAA,oBAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,KAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA,aAAe,EAAA,qBAAA;AAAA,IACf,MAAQ,EAAA,CAAA,GAAA,KAAO,0BAA2B,CAAA,GAAuB,CAAM,KAAA;AAAA,GACxE,CAAA;AACD,EAAA,MAAM,OAA+B,EAAC;AACtC,EAAA,MAAM,UAA2B,EAAC;AAClC,EAAW,KAAA,MAAA;AAAA,IACT,GAAA;AAAA,IACA;AAAA,GACF,IAAK,KAAK,IAAM,EAAA;AACd,IAAM,MAAA,QAAA,GAAW,2BAA2B,GAAuB,CAAA;AACnE,IAAA,IAAI,CAAC,QAAU,EAAA;AACf,IAAA,IAAA,CAAK,KAAK,QAAQ,CAAA;AAClB,IAAA,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA;AAEpB,EAAO,OAAA;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAM,IAAK,CAAA;AAAA,GACb;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {deriveBackendGraphqlUrl}from'./videoEditor/remoteMediaClient.js';import {studioCatalogFilter,STUDIO_CATALOG_QUERY,catalogRowToStudioTemplate}from'./studioCatalog.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {deriveBackendGraphqlUrl}from'./videoEditor/remoteMediaClient.js';import {isRankedStudioSearch,apolloCatalogRead,rankedStudioCatalogPage,studioCatalogFilter,STUDIO_CATALOG_QUERY,catalogRowToStudioTemplate}from'./studioCatalog.js';import {fetchCatalogRead}from'./rankedCatalogSearch.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
3
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
4
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -38,9 +38,8 @@ function normalize(raw) {
|
|
|
38
38
|
hasMore: Boolean(body.hasMore)
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
function
|
|
42
|
-
|
|
43
|
-
const looks = (nodes != null ? nodes : []).map(catalogRowToStudioTemplate).filter((row) => row !== null && Boolean(row.prompt)).map((row) => ({
|
|
41
|
+
function looksFromTemplates(rows) {
|
|
42
|
+
return rows.filter((row) => row !== null && Boolean(row.prompt)).map((row) => ({
|
|
44
43
|
id: row.id,
|
|
45
44
|
name: row.title,
|
|
46
45
|
description: row.description || "",
|
|
@@ -51,11 +50,24 @@ function looksFromCatalogNodes(nodes, pageSize) {
|
|
|
51
50
|
category: row.category || "",
|
|
52
51
|
tags: row.tags || []
|
|
53
52
|
}));
|
|
53
|
+
}
|
|
54
|
+
function looksFromCatalogNodes(nodes, pageSize) {
|
|
55
|
+
var _a;
|
|
56
|
+
const looks = looksFromTemplates((nodes != null ? nodes : []).map(catalogRowToStudioTemplate));
|
|
54
57
|
return {
|
|
55
58
|
looks,
|
|
56
59
|
hasMore: ((_a = nodes == null ? void 0 : nodes.length) != null ? _a : 0) >= pageSize
|
|
57
60
|
};
|
|
58
61
|
}
|
|
62
|
+
async function listRanked(read, params) {
|
|
63
|
+
const page = await rankedStudioCatalogPage(params.query, params.offset, read, params.limit);
|
|
64
|
+
return __spreadValues({
|
|
65
|
+
looks: looksFromTemplates(page.rows),
|
|
66
|
+
hasMore: page.next !== null
|
|
67
|
+
}, page.next !== null ? {
|
|
68
|
+
next: page.next
|
|
69
|
+
} : {});
|
|
70
|
+
}
|
|
59
71
|
async function listViaCatalog(client, params) {
|
|
60
72
|
var _a, _b, _c, _d;
|
|
61
73
|
const limit = (_a = params.limit) != null ? _a : LOOKS_PAGE_SIZE;
|
|
@@ -108,6 +120,21 @@ async function listStudioLooks(run, params = {}, options = {}) {
|
|
|
108
120
|
const offset = (_b = params.offset) != null ? _b : 0;
|
|
109
121
|
const query = (_c = params.query) == null ? void 0 : _c.trim();
|
|
110
122
|
const graphqlUrl = opts.indexUrl ? deriveBackendGraphqlUrl(opts.indexUrl) : null;
|
|
123
|
+
if (query && isRankedStudioSearch(query)) {
|
|
124
|
+
const reads = [];
|
|
125
|
+
if (opts.token && graphqlUrl) reads.push(fetchCatalogRead(graphqlUrl, opts.token));
|
|
126
|
+
if (opts.client) reads.push(apolloCatalogRead(opts.client));
|
|
127
|
+
for (const read of reads) {
|
|
128
|
+
try {
|
|
129
|
+
return await listRanked(read, {
|
|
130
|
+
query,
|
|
131
|
+
offset,
|
|
132
|
+
limit
|
|
133
|
+
});
|
|
134
|
+
} catch (e) {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
111
138
|
if (opts.token && graphqlUrl) {
|
|
112
139
|
try {
|
|
113
140
|
return await listViaBackendFetch(graphqlUrl, opts.token, {
|