@volter/editor-core 0.5.57
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/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE PAGE'S OWN DEATH CERTIFICATE — one latch, read by everything that would
|
|
3
|
+
* otherwise let a dead page keep impersonating a live editor.
|
|
4
|
+
*
|
|
5
|
+
* A vgai editor page is a client-side SPA. When its session ends — gracefully
|
|
6
|
+
* (`vgai close` pushes `tab-close`) or ungracefully (the process was killed, or
|
|
7
|
+
* a DIFFERENT server took the port) — the page keeps running: it keeps its
|
|
8
|
+
* control channel's reconnect loop, keeps POSTing state snapshots, and keeps
|
|
9
|
+
* executing relayed commands. Measured during a live debugging session: pages
|
|
10
|
+
* from earlier crashed/replaced sessions ("corpse pages") kept answering
|
|
11
|
+
* probes, so an attach or a `vgai status` read could land on a page whose
|
|
12
|
+
* server was gone or replaced, and nothing on that page said so.
|
|
13
|
+
*
|
|
14
|
+
* Both halves of the detection ALREADY existed and neither was wired to
|
|
15
|
+
* anything but a notice:
|
|
16
|
+
* - graceful: `tab-lifecycle-client.ts` handles the server's `tab-close` push;
|
|
17
|
+
* - ungraceful: `EditorLeaseGuard`/`editor-lease.ts` void the supervised lease
|
|
18
|
+
* (`server-gone` / `taken-over`).
|
|
19
|
+
* This module is the ONE state both write to, and the one thing the command
|
|
20
|
+
* listener reads before it runs anything.
|
|
21
|
+
*
|
|
22
|
+
* ## Why a latch and not a per-caller check
|
|
23
|
+
*
|
|
24
|
+
* The bijection (`server/tab-lifecycle.ts`) is the server's account of which
|
|
25
|
+
* tab is real, and it is the mechanism the owner invariant names. A corpse page
|
|
26
|
+
* must therefore not merely stay quiet — it must LEAVE that account. So
|
|
27
|
+
* `markSessionEnded` is what the command listener subscribes to in order to
|
|
28
|
+
* report its listener DETACHED (`POST /__editor/command-listener`, the same
|
|
29
|
+
* fact `server/server-utils.ts`'s `commandListenerHealth` already prints per
|
|
30
|
+
* tab as `not attached`). The server's own tab table then names the page as
|
|
31
|
+
* unresponsive instead of blessing it — integrating with the bijection rather
|
|
32
|
+
* than growing a second notion of tab liveness beside it.
|
|
33
|
+
*
|
|
34
|
+
* ## Why it can be cleared
|
|
35
|
+
*
|
|
36
|
+
* Not every void is final. `editor-lease.ts`'s `decideLeaseRecovery` has a
|
|
37
|
+
* `resume` branch: the SAME process answers again, so it was never gone and the
|
|
38
|
+
* page is not stale. That branch calls {@link clearSessionEnded}. The two
|
|
39
|
+
* TERMINAL reasons (`taken-over`, and the server's own `tab-close`) never
|
|
40
|
+
* clear — a tab that yielded to a live window must never come back to fight it.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** Why this page's session is over, in the vocabulary its detector already
|
|
44
|
+
* uses (`editor-lease.ts`'s `LeaseVoidReason`, plus the graceful push). */
|
|
45
|
+
export type SessionEndReason = 'server-gone' | 'taken-over' | 'session-closed';
|
|
46
|
+
|
|
47
|
+
export interface SessionEndedState {
|
|
48
|
+
readonly reason: SessionEndReason;
|
|
49
|
+
/** When this page decided it. Every refusal quotes the age, because "this
|
|
50
|
+
* page is dead" without a time is the same unfalsifiable present-tense claim
|
|
51
|
+
* the status age-stamp exists to kill. */
|
|
52
|
+
readonly at: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let ended: SessionEndedState | null = null;
|
|
56
|
+
const listeners = new Set<(state: SessionEndedState | null) => void>();
|
|
57
|
+
|
|
58
|
+
function publish(): void {
|
|
59
|
+
for (const listener of [...listeners]) listener(ended);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The state, or `null` while this page still believes it is live. */
|
|
63
|
+
export function sessionEndedState(): SessionEndedState | null {
|
|
64
|
+
return ended;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Record the death. Idempotent per reason, and a TERMINAL reason is never
|
|
68
|
+
* overwritten by a later recoverable one. */
|
|
69
|
+
export function markSessionEnded(reason: SessionEndReason, at: number = Date.now()): void {
|
|
70
|
+
if (ended !== null && ended.reason !== 'server-gone') return;
|
|
71
|
+
if (ended !== null && ended.reason === reason) return;
|
|
72
|
+
ended = { reason, at };
|
|
73
|
+
publish();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The `resume` branch: the same process answered again, so nothing here is
|
|
77
|
+
* stale. Only ever legitimate after a `server-gone` void. */
|
|
78
|
+
export function clearSessionEnded(): void {
|
|
79
|
+
if (ended === null || ended.reason !== 'server-gone') return;
|
|
80
|
+
ended = null;
|
|
81
|
+
publish();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Subscribe to transitions. Returns an unsubscribe. */
|
|
85
|
+
export function onSessionEndedChange(
|
|
86
|
+
listener: (state: SessionEndedState | null) => void,
|
|
87
|
+
): () => void {
|
|
88
|
+
listeners.add(listener);
|
|
89
|
+
return () => {
|
|
90
|
+
listeners.delete(listener);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The refusal a dead page answers control traffic with — a message that NAMES
|
|
96
|
+
* the state, its age, and the one thing that fixes it, so a caller never has to
|
|
97
|
+
* infer "corpse" from a plausible-looking answer.
|
|
98
|
+
*
|
|
99
|
+
* Pure over the state (no globals, no clock of its own) so the wording is
|
|
100
|
+
* testable without a browser.
|
|
101
|
+
*/
|
|
102
|
+
export function sessionEndedRefusal(
|
|
103
|
+
state: SessionEndedState,
|
|
104
|
+
commandType: string,
|
|
105
|
+
now: number = Date.now(),
|
|
106
|
+
): string {
|
|
107
|
+
const age = `${Math.max(0, Math.round((now - state.at) / 1000))}s ago`;
|
|
108
|
+
const what =
|
|
109
|
+
state.reason === 'taken-over'
|
|
110
|
+
? `a DIFFERENT editor session took this port ${age}; this page yielded to it`
|
|
111
|
+
: state.reason === 'session-closed'
|
|
112
|
+
? `this page's editor session was closed ${age}`
|
|
113
|
+
: `this page's editor server stopped ${age}`;
|
|
114
|
+
return (
|
|
115
|
+
`refused "${commandType}": this editor page is a TOMBSTONE — ${what}. ` +
|
|
116
|
+
'Nothing it reports is live state and nothing it does is saved. ' +
|
|
117
|
+
'Run `volter-editor edit <project>` to open the session again; that reuses the live ' +
|
|
118
|
+
'server and its one tab.'
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Test seam: forget everything this page decided. */
|
|
123
|
+
export function resetSessionTombstone(): void {
|
|
124
|
+
ended = null;
|
|
125
|
+
listeners.clear();
|
|
126
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHERE THE SETTINGS ARE: `IConfigurationService`, through a provider the
|
|
3
|
+
* contribution installs here.
|
|
4
|
+
*
|
|
5
|
+
* Every setting is one dotted `vgai.*` name per LEAF of the settings document,
|
|
6
|
+
* and the prefix is part of the key everywhere — in `EditorHost.settings`, in
|
|
7
|
+
* `.vscode/settings.json`, in the Settings editor and in what a probe prints.
|
|
8
|
+
* The table is DERIVED, never written: `@volter/editor-project/settings/keys` walks the
|
|
9
|
+
* JSON Schema Zod itself produces, which is the same derivation
|
|
10
|
+
* `npm run generate-schema` commits.
|
|
11
|
+
*
|
|
12
|
+
* The ADAPTER layer — the one thing that service does not already have — is
|
|
13
|
+
* its own MEMORY target, which the platform merges ABOVE user; what puts the
|
|
14
|
+
* PROJECT back above the adapter is an INSPECT GATE, re-evaluated on every
|
|
15
|
+
* configuration change. See docs/CODE-OSS.md §The settings, under the frame.
|
|
16
|
+
*
|
|
17
|
+
* IT ARRIVES AFTER THE MOUNT, for the same reason the file provider does, and
|
|
18
|
+
* a reader falls back to the store's own layers until it lands — which is why
|
|
19
|
+
* a preference gesture made too early cannot write a `.vgai/settings.json` the
|
|
20
|
+
* workbench knows nothing about.
|
|
21
|
+
*
|
|
22
|
+
* A provider's own change stream is subscribed HERE rather than by each
|
|
23
|
+
* reader, so `subscribeSettingsProvider` is the one notification every consumer
|
|
24
|
+
* of the store already listens to.
|
|
25
|
+
*/
|
|
26
|
+
import type {
|
|
27
|
+
EditorHostSettingsInspection,
|
|
28
|
+
EditorHostSettingsProvider,
|
|
29
|
+
} from '@volter/editor-sdk/host';
|
|
30
|
+
|
|
31
|
+
export type SettingsProvider = EditorHostSettingsProvider;
|
|
32
|
+
export type SettingsInspection = EditorHostSettingsInspection;
|
|
33
|
+
|
|
34
|
+
let provider: SettingsProvider | null = null;
|
|
35
|
+
const listeners = new Set<() => void>();
|
|
36
|
+
let stopProvider: (() => void) | null = null;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Is the provider installed? False until it lands — later than the mount,
|
|
40
|
+
* because a `ServicesAccessor` is valid only for a command's synchronous part,
|
|
41
|
+
* so the contribution hands the provider over after the editor is running. In
|
|
42
|
+
* that window a reader falls back to the store's own layers, which is why a
|
|
43
|
+
* preference gesture made too early does not write a settings file the
|
|
44
|
+
* workbench knows nothing about.
|
|
45
|
+
*/
|
|
46
|
+
export function settingsProviderInstalled(): boolean {
|
|
47
|
+
return provider !== null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The installed provider, or `null` before it lands. */
|
|
51
|
+
export function settingsProvider(): SettingsProvider | null {
|
|
52
|
+
return provider;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Install the configuration service the settings read and write through, or
|
|
57
|
+
* `null` to withdraw it — the service is the workbench's, and a workbench that
|
|
58
|
+
* went away takes it with it.
|
|
59
|
+
*
|
|
60
|
+
* A provider's own change stream is subscribed HERE rather than by each
|
|
61
|
+
* reader, so `subscribeSettingsProvider` is the one notification every consumer
|
|
62
|
+
* of the store already listens to — an adapter value clearing because a
|
|
63
|
+
* project value appeared reaches the palette the same way a settings file
|
|
64
|
+
* reload does.
|
|
65
|
+
*/
|
|
66
|
+
export function setSettingsProvider(next: SettingsProvider | null): void {
|
|
67
|
+
if (provider === next) return;
|
|
68
|
+
stopProvider?.();
|
|
69
|
+
stopProvider = null;
|
|
70
|
+
provider = next;
|
|
71
|
+
if (provider) stopProvider = provider.subscribe(() => announce());
|
|
72
|
+
announce();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function announce(): void {
|
|
76
|
+
for (const listener of listeners) listener();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function subscribeSettingsProvider(listener: () => void): () => void {
|
|
80
|
+
listeners.add(listener);
|
|
81
|
+
return () => listeners.delete(listener);
|
|
82
|
+
}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SETTINGS STORE — the shared layers, loaded once and read
|
|
3
|
+
* synchronously everywhere (ARCHITECTURE-CORE §Editor chrome, "Settings have
|
|
4
|
+
* four layers with named homes"):
|
|
5
|
+
*
|
|
6
|
+
* user ~/.vgai/settings.json every project, this person
|
|
7
|
+
* adapter <project>/vgai.adapter.ts this project's own CODE
|
|
8
|
+
* project <project>/.vgai/settings.json this project, everyone (committed)
|
|
9
|
+
*
|
|
10
|
+
* `effectiveSettings()` is project over adapter over user, key by key.
|
|
11
|
+
*
|
|
12
|
+
* THE ADAPTER LAYER is the project's look and bindings as the adapter
|
|
13
|
+
* DECLARES them — `editor: { style: blenderStyle, keymap: blenderKeymap }`,
|
|
14
|
+
* imported objects, not a file the host parses (ARCHITECTURE-CORE §Adapters
|
|
15
|
+
* and contributions are code, not configs). It sits above the USER layer
|
|
16
|
+
* because it is a fact about THIS project and the user layer is one person's
|
|
17
|
+
* cross-project default: a skew's Blender greys must not be undone by the
|
|
18
|
+
* graphite a game project left in `~/.vgai/settings.json`. It sits below the
|
|
19
|
+
* PROJECT layer because that file is this project's own explicit override, so
|
|
20
|
+
* an appearance gesture still lands somewhere that wins. Appearance and
|
|
21
|
+
* keymap choices write WHERE THE KEY IS DECLARED (`updatePreferenceSettings`):
|
|
22
|
+
* the user layer, or the project layer when the project's own file carries
|
|
23
|
+
* that key (a models scaffold declares its look, the way a repo's
|
|
24
|
+
* `.vscode/settings.json` does) — so the gesture edits the file that wins;
|
|
25
|
+
* the device preview frame is a project fact and writes the PROJECT layer. The other two layers — the project-LOCAL document
|
|
26
|
+
* (`project-local-state.ts`, git-ignored) and the built-in defaults every
|
|
27
|
+
* consumer carries — never pass through here.
|
|
28
|
+
*
|
|
29
|
+
* Boot awaits `preloadSettings()` before the first paint (`main.tsx`,
|
|
30
|
+
* before React mounts), so a consumer's first synchronous read already sees
|
|
31
|
+
* the person's palette; the project layer reloads whenever the active
|
|
32
|
+
* project changes. A file that does not parse is reported to the editor
|
|
33
|
+
* console by path — an unresolved condition, so `vgai console` carries it —
|
|
34
|
+
* and that layer reads as empty until it is fixed.
|
|
35
|
+
*
|
|
36
|
+
* ## UNDER THE CODE-OSS FRAME THIS MODULE IS THE FALLBACK, not the truth
|
|
37
|
+
*
|
|
38
|
+
* ARCHITECTURE-CORE §The core is Code-OSS, U7: the frame's
|
|
39
|
+
* `IConfigurationService` is the settings, and the same three layers are its
|
|
40
|
+
* USER target, its MEMORY target (the adapter's declaration, gated by
|
|
41
|
+
* `inspect` on the workspace value) and `.vscode/settings.json`. When
|
|
42
|
+
* `settings/settings-provider.ts` reports a frame provider, every one of the
|
|
43
|
+
* four layer views below is composed FROM IT, per key, through
|
|
44
|
+
* `@volter/editor-project/settings/keys`'s table — so nothing that reads this module
|
|
45
|
+
* changes shape, and `theme-preference.ts`, `workspace-regions.ts`,
|
|
46
|
+
* `keymap-presets.ts` and `device-preview.ts` go on reading a nested
|
|
47
|
+
* `EditorSettings` document exactly as they always did. The file layers are
|
|
48
|
+
* still loaded, because they are what answers in the window before the
|
|
49
|
+
* provider arrives and in every standalone session.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
import type { EditorHostSettingsInspection, EditorHostSettingsTarget } from '@volter/editor-sdk/host';
|
|
53
|
+
import { flattenSettings, settingsFromEntries, settingsKeys } from '@volter/editor-project/settings/keys';
|
|
54
|
+
import { type EditorSettings, mergeEditorSettings } from '@volter/editor-project/settings/schema';
|
|
55
|
+
import { activeProjectKey, getCurrentProject, onProjectChange } from './active-project';
|
|
56
|
+
import {
|
|
57
|
+
adapterEditorConfiguration,
|
|
58
|
+
subscribeAdapterEditorConfiguration,
|
|
59
|
+
} from './adapter-editor-config';
|
|
60
|
+
import { loadSettingsLayer, type SettingsLayer, saveSettingsLayer } from './api/settings';
|
|
61
|
+
import { editorConsole } from './editor-console';
|
|
62
|
+
import { settingsProvider, subscribeSettingsProvider } from './settings/settings-provider';
|
|
63
|
+
|
|
64
|
+
type Listener = () => void;
|
|
65
|
+
|
|
66
|
+
let user: EditorSettings = {};
|
|
67
|
+
let project: EditorSettings = {};
|
|
68
|
+
let adapter: EditorSettings = {};
|
|
69
|
+
let effective: EditorSettings = {};
|
|
70
|
+
let userLoaded = false;
|
|
71
|
+
let projectLoadedFor: string | null = null;
|
|
72
|
+
let userLoading: Promise<void> | null = null;
|
|
73
|
+
let projectLoading: Promise<void> | null = null;
|
|
74
|
+
const listeners = new Set<Listener>();
|
|
75
|
+
|
|
76
|
+
function projectKey(): string {
|
|
77
|
+
return activeProjectKey();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The adapter's declared look and bindings, in the settings document's shape.
|
|
82
|
+
* The style object carries the ids the registries resolve; the objects
|
|
83
|
+
* themselves are registered by the package's own contributions, so a project
|
|
84
|
+
* that declares the look without the package simply resolves to the editor's
|
|
85
|
+
* defaults.
|
|
86
|
+
*
|
|
87
|
+
* This is the DECLARATION, read straight off the adapter, and it is what the
|
|
88
|
+
* frame's bridge hands the configuration service to write into its MEMORY
|
|
89
|
+
* target — so the frame never has a second notion of what the adapter said.
|
|
90
|
+
*/
|
|
91
|
+
export function declaredAdapterSettings(): EditorSettings {
|
|
92
|
+
const editor = adapterEditorConfiguration();
|
|
93
|
+
const style = editor.style;
|
|
94
|
+
const layer: Record<string, unknown> = {};
|
|
95
|
+
if (style) {
|
|
96
|
+
const appearance: Record<string, unknown> = {
|
|
97
|
+
palette: style.paletteId,
|
|
98
|
+
material: style.materialId,
|
|
99
|
+
};
|
|
100
|
+
const icons = style.iconSetId ?? style.icons?.id;
|
|
101
|
+
if (icons !== undefined) appearance['icons'] = icons;
|
|
102
|
+
if (style.regions !== undefined) appearance['regions'] = style.regions;
|
|
103
|
+
layer['appearance'] = appearance;
|
|
104
|
+
}
|
|
105
|
+
if (editor.keymap) layer['keymap'] = editor.keymap.id;
|
|
106
|
+
return layer as EditorSettings;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** The adapter layer AS IT IS IN FORCE — the declaration standalone, the
|
|
110
|
+
* configuration service's MEMORY target under the frame (where a project
|
|
111
|
+
* value for a key has already cleared it). Standalone it is read LIVE rather
|
|
112
|
+
* than from the cache below, so a reader that runs before the first
|
|
113
|
+
* `recompute()` sees the adapter's declaration and not an empty layer. */
|
|
114
|
+
export function adapterSettings(): EditorSettings {
|
|
115
|
+
return settingsProvider() ? adapter : declaredAdapterSettings();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The adapter's declaration as dotted `vgai.*` keys — what the frame writes
|
|
119
|
+
* to the MEMORY target. */
|
|
120
|
+
export function declaredAdapterSettingEntries(): ReadonlyMap<string, unknown> {
|
|
121
|
+
return flattenSettings(declaredAdapterSettings());
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function recompute(): void {
|
|
125
|
+
const provider = settingsProvider();
|
|
126
|
+
if (provider) {
|
|
127
|
+
// THE FRAME'S LAYERS, one key at a time. `inspect` is the only door that
|
|
128
|
+
// separates them — the effective value alone cannot say whether a gesture
|
|
129
|
+
// on this key will stick, and `keymap-presets.ts` and `device-preview.ts`
|
|
130
|
+
// both ask exactly that.
|
|
131
|
+
const users: [string, unknown][] = [];
|
|
132
|
+
const adapters: [string, unknown][] = [];
|
|
133
|
+
const projects: [string, unknown][] = [];
|
|
134
|
+
const effectives: [string, unknown][] = [];
|
|
135
|
+
for (const { key } of settingsKeys()) {
|
|
136
|
+
const layered = provider.inspect(key);
|
|
137
|
+
users.push([key, layered.user]);
|
|
138
|
+
adapters.push([key, layered.adapter]);
|
|
139
|
+
projects.push([key, layered.project]);
|
|
140
|
+
effectives.push([key, layered.effective]);
|
|
141
|
+
}
|
|
142
|
+
user = settingsFromEntries(users);
|
|
143
|
+
adapter = settingsFromEntries(adapters);
|
|
144
|
+
project = settingsFromEntries(projects);
|
|
145
|
+
effective = settingsFromEntries(effectives);
|
|
146
|
+
} else {
|
|
147
|
+
adapter = {};
|
|
148
|
+
effective = mergeEditorSettings(mergeEditorSettings(user, declaredAdapterSettings()), project);
|
|
149
|
+
}
|
|
150
|
+
for (const listener of listeners) listener();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function report(layer: SettingsLayer, path: string | null, issues: readonly string[]): void {
|
|
154
|
+
if (issues.length === 0) return;
|
|
155
|
+
editorConsole.warn(
|
|
156
|
+
`${layer} settings ${path ?? ''} did not parse and is ignored — ${issues.join('; ')}`,
|
|
157
|
+
'settings',
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function loadUser(): Promise<void> {
|
|
162
|
+
if (userLoaded) return Promise.resolve();
|
|
163
|
+
userLoading ??= loadSettingsLayer('user')
|
|
164
|
+
.then((read) => {
|
|
165
|
+
user = read.settings;
|
|
166
|
+
report('user', read.path, read.issues);
|
|
167
|
+
})
|
|
168
|
+
.catch(() => {
|
|
169
|
+
user = {};
|
|
170
|
+
})
|
|
171
|
+
.finally(() => {
|
|
172
|
+
userLoaded = true;
|
|
173
|
+
userLoading = null;
|
|
174
|
+
});
|
|
175
|
+
return userLoading;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function loadProject(): Promise<void> {
|
|
179
|
+
const key = projectKey();
|
|
180
|
+
if (projectLoadedFor === key) return Promise.resolve();
|
|
181
|
+
// In flight for another project: this one loads after it, never joins it.
|
|
182
|
+
if (projectLoading) return projectLoading.then(() => loadProject());
|
|
183
|
+
if (!getCurrentProject()) {
|
|
184
|
+
project = {};
|
|
185
|
+
projectLoadedFor = key;
|
|
186
|
+
return Promise.resolve();
|
|
187
|
+
}
|
|
188
|
+
projectLoading = loadSettingsLayer('project')
|
|
189
|
+
.then((read) => {
|
|
190
|
+
project = read.settings;
|
|
191
|
+
report('project', read.path, read.issues);
|
|
192
|
+
})
|
|
193
|
+
.catch(() => {
|
|
194
|
+
project = {};
|
|
195
|
+
})
|
|
196
|
+
.finally(() => {
|
|
197
|
+
projectLoadedFor = key;
|
|
198
|
+
projectLoading = null;
|
|
199
|
+
});
|
|
200
|
+
return projectLoading;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Load both layers (memoized per layer; the project layer per project) and
|
|
204
|
+
* publish. Idempotent — every boot seam may await it. */
|
|
205
|
+
export function preloadSettings(): Promise<void> {
|
|
206
|
+
return Promise.all([loadUser(), loadProject()]).then(recompute);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Project over adapter over user. */
|
|
210
|
+
export function effectiveSettings(): EditorSettings {
|
|
211
|
+
return effective;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function userSettings(): EditorSettings {
|
|
215
|
+
return user;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function projectSettings(): EditorSettings {
|
|
219
|
+
return project;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Every layer's own value for one `vgai.*` key, plus the effective one —
|
|
223
|
+
* the door's `inspect`, answered from whichever side owns the settings. */
|
|
224
|
+
export function inspectSetting(key: string): EditorHostSettingsInspection {
|
|
225
|
+
const provider = settingsProvider();
|
|
226
|
+
if (provider) return provider.inspect(key);
|
|
227
|
+
const read = (document: EditorSettings): unknown => flattenSettings(document).get(key);
|
|
228
|
+
return {
|
|
229
|
+
// The standalone layers are FILES; nothing under them carries a built-in
|
|
230
|
+
// value, so answering anything here would be a fabricated layer.
|
|
231
|
+
default: undefined,
|
|
232
|
+
user: read(user),
|
|
233
|
+
adapter: read(adapterSettings()),
|
|
234
|
+
project: read(project),
|
|
235
|
+
effective: read(effective),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** The effective value of one `vgai.*` key. */
|
|
240
|
+
export function getSetting(key: string): unknown {
|
|
241
|
+
const provider = settingsProvider();
|
|
242
|
+
return provider ? provider.get(key) : flattenSettings(effective).get(key);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Which layer a gesture on this key must land in for it to stick: the project
|
|
247
|
+
* when this project's ADAPTER or its own settings already declare the key,
|
|
248
|
+
* the user layer otherwise.
|
|
249
|
+
*
|
|
250
|
+
* One rule, one implementation, both shapes — writing `appearance` to the
|
|
251
|
+
* user layer in a project whose adapter declares a style is a gesture that
|
|
252
|
+
* silently does nothing, and that is as true of the configuration service's
|
|
253
|
+
* MEMORY target as it is of `.vgai/settings.json`.
|
|
254
|
+
*/
|
|
255
|
+
function targetFor(key: string): EditorHostSettingsTarget {
|
|
256
|
+
if (!getCurrentProject()) return 'user';
|
|
257
|
+
const layered = inspectSetting(key);
|
|
258
|
+
return layered.adapter !== undefined || layered.project !== undefined ? 'project' : 'user';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Write a set of `vgai.*` keys, grouped so each LAYER is written once.
|
|
263
|
+
*
|
|
264
|
+
* The grouping is not a micro-optimisation: standalone, a layer write is a
|
|
265
|
+
* whole-document POST, so a two-key patch sent as two writes is two POSTs of
|
|
266
|
+
* two different documents racing each other on the server's side — the same
|
|
267
|
+
* "one document, one writer" reasoning `project-local-state.ts`'s header
|
|
268
|
+
* gives for its sections.
|
|
269
|
+
*/
|
|
270
|
+
function applySettings(
|
|
271
|
+
entries: Iterable<readonly [string, unknown]>,
|
|
272
|
+
forced?: EditorHostSettingsTarget,
|
|
273
|
+
): void {
|
|
274
|
+
const toUser: (readonly [string, unknown])[] = [];
|
|
275
|
+
const toProject: (readonly [string, unknown])[] = [];
|
|
276
|
+
for (const entry of entries) {
|
|
277
|
+
const target = forced ?? targetFor(entry[0]);
|
|
278
|
+
(target === 'project' ? toProject : toUser).push(entry);
|
|
279
|
+
}
|
|
280
|
+
const provider = settingsProvider();
|
|
281
|
+
if (provider) {
|
|
282
|
+
for (const [key, value] of toUser) provider.set(key, value, 'user');
|
|
283
|
+
for (const [key, value] of toProject) provider.set(key, value, 'project');
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (toUser.length > 0) writeUserLayer(settingsFromEntries(toUser));
|
|
287
|
+
if (toProject.length > 0) writeProjectLayer(settingsFromEntries(toProject));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Write one `vgai.*` key. With no target, {@link targetFor} picks the layer
|
|
291
|
+
* that wins. */
|
|
292
|
+
export function setSetting(key: string, value: unknown, target?: EditorHostSettingsTarget): void {
|
|
293
|
+
applySettings([[key, value]], target);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Merge `patch` into the USER layer and write `~/.vgai/settings.json`. */
|
|
297
|
+
function writeUserLayer(patch: EditorSettings): void {
|
|
298
|
+
user = mergeEditorSettings(user, patch);
|
|
299
|
+
recompute();
|
|
300
|
+
void saveSettingsLayer('user', user).catch((cause: unknown) => {
|
|
301
|
+
editorConsole.error(`Could not save user settings: ${(cause as Error).message}`, 'settings');
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Merge a PREFERENCE patch where each key lands WHERE IT WINS — see
|
|
307
|
+
* {@link targetFor}. The patch is a nested document because that is the shape
|
|
308
|
+
* every caller already holds; it is flattened to keys here, which is the one
|
|
309
|
+
* place the two spellings meet.
|
|
310
|
+
*/
|
|
311
|
+
export function updatePreferenceSettings(patch: EditorSettings): void {
|
|
312
|
+
applySettings(flattenSettings(patch));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Merge `patch` into the PROJECT layer. */
|
|
316
|
+
export function updateProjectSettings(patch: EditorSettings): void {
|
|
317
|
+
if (!getCurrentProject()) return;
|
|
318
|
+
applySettings(flattenSettings(patch), 'project');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function writeProjectLayer(patch: EditorSettings): void {
|
|
322
|
+
if (!getCurrentProject()) return;
|
|
323
|
+
project = mergeEditorSettings(project, patch);
|
|
324
|
+
recompute();
|
|
325
|
+
void saveSettingsLayer('project', project).catch((cause: unknown) => {
|
|
326
|
+
editorConsole.error(`Could not save project settings: ${(cause as Error).message}`, 'settings');
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export function subscribeSettings(listener: Listener): () => void {
|
|
331
|
+
listeners.add(listener);
|
|
332
|
+
return () => listeners.delete(listener);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
onProjectChange(() => {
|
|
336
|
+
void loadProject().then(recompute);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// The adapter layer changes when a project's adapter module loads or unloads.
|
|
340
|
+
subscribeAdapterEditorConfiguration(recompute);
|
|
341
|
+
|
|
342
|
+
// And under the frame, when the configuration service says any layer moved —
|
|
343
|
+
// including the MEMORY value the frame clears the instant a project value for
|
|
344
|
+
// that key appears, which is what puts the project back above the adapter.
|
|
345
|
+
subscribeSettingsProvider(recompute);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A SHARED VIEW LINK, restored once the session's own restore has settled.
|
|
3
|
+
*
|
|
4
|
+
* `editorViewFromUrl` reads the view a share link carries; presenting it has
|
|
5
|
+
* to wait for the workspace's documents, or the presentation lands on a
|
|
6
|
+
* document that is about to be replaced. It lives beside the editor rather
|
|
7
|
+
* than inside a layout because there is exactly ONE layout host now
|
|
8
|
+
* (`frame/bridge.tsx`) and a hook a layout owns is a hook one layout can
|
|
9
|
+
* forget: this is the session's behaviour, called from the one workspace that
|
|
10
|
+
* exists.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { editorViewFromUrl } from '@volter/editor-sdk';
|
|
14
|
+
import { useEffect } from 'react';
|
|
15
|
+
import { activeProjectKey } from './active-project';
|
|
16
|
+
import { editorConsole } from './editor-console';
|
|
17
|
+
import type { EditorShellStore } from './editor-shell-store';
|
|
18
|
+
import { presentEditorView } from './editor-view-presentation';
|
|
19
|
+
import { waitForWorkspaceStateRestore } from './workspace-state-persistence';
|
|
20
|
+
|
|
21
|
+
export function useSharedViewRestore(store: EditorShellStore): void {
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const view = editorViewFromUrl(window.location.href);
|
|
24
|
+
if (!view) return;
|
|
25
|
+
let disposed = false;
|
|
26
|
+
const project = activeProjectKey();
|
|
27
|
+
const current = () => !disposed && activeProjectKey() === project;
|
|
28
|
+
void waitForWorkspaceStateRestore()
|
|
29
|
+
.then(() => {
|
|
30
|
+
if (current()) return presentEditorView(store, view, { updateUrl: false, origin: 'link' });
|
|
31
|
+
})
|
|
32
|
+
.catch((error) => {
|
|
33
|
+
editorConsole.error(
|
|
34
|
+
`Could not restore shared editor view: ${error instanceof Error ? error.message : String(error)}`,
|
|
35
|
+
'editor',
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
disposed = true;
|
|
40
|
+
};
|
|
41
|
+
}, [store]);
|
|
42
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE SHELL STORE, as the lanes that run something reach it. The store is
|
|
3
|
+
* created once per project session (`EditorContext.tsx`); the door is
|
|
4
|
+
* installed at boot before any store exists, and Play, ingest and the module
|
|
5
|
+
* lane bind themselves to the store on its ARRIVAL rather than being bound by
|
|
6
|
+
* the workspace panel that happens to mount first (until 2026-09-17 both
|
|
7
|
+
* `the world root's stage` and `NonThreeAuthoringBootstrap` named Play and ingest to
|
|
8
|
+
* hand them the store). A leaf module with no imports, so a lane may subscribe
|
|
9
|
+
* at its own module load without an import cycle.
|
|
10
|
+
*/
|
|
11
|
+
import type { EditorShellStore } from './editor-shell-store';
|
|
12
|
+
|
|
13
|
+
let shellStore: EditorShellStore | null = null;
|
|
14
|
+
const arrivals = new Set<(store: EditorShellStore) => void>();
|
|
15
|
+
const changeListeners = new Set<() => void>();
|
|
16
|
+
|
|
17
|
+
/** `EditorContext.tsx` registers the store it created. */
|
|
18
|
+
export function registerShellStoreForHost(store: EditorShellStore): void {
|
|
19
|
+
shellStore = store;
|
|
20
|
+
for (const listener of arrivals) listener(store);
|
|
21
|
+
for (const listener of changeListeners) listener();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The current store, or null before a project session opens. */
|
|
25
|
+
export function shellStoreForHost(): EditorShellStore | null {
|
|
26
|
+
return shellStore;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Runs on every store arrival — at once, when one is already registered. */
|
|
30
|
+
export function onShellStore(listener: (store: EditorShellStore) => void): () => void {
|
|
31
|
+
arrivals.add(listener);
|
|
32
|
+
if (shellStore) listener(shellStore);
|
|
33
|
+
return () => {
|
|
34
|
+
arrivals.delete(listener);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Fires when the store is (re)registered; the door's `session.subscribe`
|
|
39
|
+
* composes this with the store's own subscription. */
|
|
40
|
+
export function onShellStoreChange(listener: () => void): () => void {
|
|
41
|
+
changeListeners.add(listener);
|
|
42
|
+
return () => {
|
|
43
|
+
changeListeners.delete(listener);
|
|
44
|
+
};
|
|
45
|
+
}
|