From bb2c99749ac8eda51df6f458a7344504f166aa15 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Thu, 13 Nov 2025 17:12:07 +0800 Subject: [PATCH 1/6] refactor: load extensions dynamically according to the configuration file --- src/components/load3d/Load3DControls.vue | 2 +- .../load3d/controls/CameraControls.vue | 2 +- .../load3d/controls/LightControls.vue | 2 +- .../load3d/controls/ModelControls.vue | 2 +- .../load3d/controls/SceneControls.vue | 2 +- .../controls/viewer/ViewerCameraControls.vue | 2 +- .../controls/viewer/ViewerModelControls.vue | 2 +- src/composables/useLoad3d.ts | 6 +- src/composables/useLoad3dDrag.ts | 2 +- src/composables/useLoad3dViewer.ts | 6 +- .../clipspace/index.ts} | 6 +- .../cloudBadges/comfy.ext.config.ts | 5 ++ .../cloudBadges/index.ts} | 0 .../comfy.ext.config.ts | 5 ++ .../cloudFeedbackTopbarButton/index.ts} | 0 .../cloudRemoteConfig/comfy.ext.config.ts | 5 ++ .../cloudRemoteConfig/index.ts} | 0 .../cloudSessionCookie/comfy.ext.config.ts | 5 ++ .../cloudSessionCookie/index.ts} | 0 .../cloudSubscription/comfy.ext.config.ts | 7 +++ .../cloudSubscription/index.ts} | 0 .../contextMenuFilter/index.ts} | 2 +- .../dynamicPrompts/index.ts} | 0 .../editAttention/index.ts} | 2 +- .../electronAdapter/index.ts} | 0 .../groupNode/index.ts} | 8 +-- .../groupNodeManage}/groupNodeManage.css | 0 .../groupNodeManage/index.ts} | 10 ++-- .../groupOptions/index.ts} | 2 +- .../load3d/AnimationManager.ts | 2 +- .../{ => extensions}/load3d/CameraManager.ts | 0 .../load3d/ControlsManager.ts | 0 .../{ => extensions}/load3d/EventManager.ts | 0 .../load3d/LightingManager.ts | 0 .../load3d/Load3DConfiguration.ts | 6 +- .../core/{ => extensions}/load3d/Load3d.ts | 0 .../{ => extensions}/load3d/Load3dUtils.ts | 0 .../{ => extensions}/load3d/LoaderManager.ts | 0 .../{ => extensions}/load3d/ModelExporter.ts | 0 .../{ => extensions}/load3d/NodeStorage.ts | 0 .../load3d/RecordingManager.ts | 0 .../{ => extensions}/load3d/SceneManager.ts | 0 .../load3d/SceneModelManager.ts | 0 .../load3d/ViewHelperManager.ts | 0 .../load3d/exportMenuHelper.ts | 2 +- .../{load3d.ts => extensions/load3d/index.ts} | 6 +- .../{ => extensions}/load3d/interfaces.ts | 0 .../maskeditor/CanvasHistory.ts | 0 .../maskeditor/MaskEditorDialog.ts | 6 +- .../{ => extensions}/maskeditor/constants.ts | 0 .../maskeditor/index.ts} | 12 ++-- .../maskeditor/managers/KeyboardManager.ts | 0 .../maskeditor/managers/MessageBroker.ts | 0 .../maskeditor/managers/PanAndZoomManager.ts | 0 .../maskeditor/managers/ToolManager.ts | 0 .../maskeditor/managers/UIManager.ts | 0 .../maskeditor/managers/index.ts | 0 .../{ => extensions}/maskeditor/styles.ts | 0 .../maskeditor/tools/BrushTool.ts | 0 .../maskeditor/tools/ColorSelectTool.ts | 0 .../maskeditor/tools/PaintBucketTool.ts | 0 .../maskeditor/tools/index.ts | 0 .../core/{ => extensions}/maskeditor/types.ts | 0 .../maskeditor/utils/brushCache.ts | 0 .../maskeditor/utils/canvas.ts | 0 .../maskeditor/utils/clipspace.ts | 0 .../maskeditor/utils/image.ts | 0 .../maskeditor/utils/index.ts | 0 .../utils/maskEditorLayerFilenames.ts | 0 .../matchType/index.ts} | 0 .../nodeTemplates/index.ts} | 8 +-- .../noteNode/index.ts} | 4 +- .../previewAny/index.ts} | 0 .../rerouteNode/index.ts} | 4 +- .../saveImageExtraOutput/index.ts} | 2 +- .../saveMesh/index.ts} | 4 +- .../selectionBorder/index.ts} | 0 .../simpleTouchSupport/index.ts} | 2 +- .../slotDefaults/index.ts} | 4 +- .../uploadAudio/index.ts} | 4 +- .../uploadImage/index.ts} | 2 +- .../webcamCapture/index.ts} | 4 +- .../widgetInputs/index.ts} | 0 src/extensions/core/index.ts | 45 ++++---------- src/extensions/core/maskEditorOld.ts | 2 +- src/extensions/dispatch.ts | 32 ++++++++++ src/extensions/types.ts | 30 ++++++++++ src/extensions/utils.ts | 59 +++++++++++++++++++ src/renderer/utils/nodeTypeGuards.ts | 2 +- src/services/extensionService.ts | 3 +- src/services/load3dService.ts | 2 +- src/utils/executableGroupNodeChildDTO.ts | 2 +- tests-ui/tests/composables/useLoad3d.test.ts | 8 +-- .../tests/composables/useLoad3dViewer.test.ts | 8 +-- tests-ui/tests/maskeditor.test.ts | 2 +- .../utils/executableGroupNodeChildDTO.test.ts | 2 +- 96 files changed, 240 insertions(+), 114 deletions(-) rename src/extensions/core/{clipspace.ts => extensions/clipspace/index.ts} (97%) create mode 100644 src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts rename src/extensions/core/{cloudBadges.ts => extensions/cloudBadges/index.ts} (100%) create mode 100644 src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts rename src/extensions/core/{cloudFeedbackTopbarButton.ts => extensions/cloudFeedbackTopbarButton/index.ts} (100%) create mode 100644 src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts rename src/extensions/core/{cloudRemoteConfig.ts => extensions/cloudRemoteConfig/index.ts} (100%) create mode 100644 src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts rename src/extensions/core/{cloudSessionCookie.ts => extensions/cloudSessionCookie/index.ts} (100%) create mode 100644 src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts rename src/extensions/core/{cloudSubscription.ts => extensions/cloudSubscription/index.ts} (100%) rename src/extensions/core/{contextMenuFilter.ts => extensions/contextMenuFilter/index.ts} (99%) rename src/extensions/core/{dynamicPrompts.ts => extensions/dynamicPrompts/index.ts} (100%) rename src/extensions/core/{editAttention.ts => extensions/editAttention/index.ts} (99%) rename src/extensions/core/{electronAdapter.ts => extensions/electronAdapter/index.ts} (100%) rename src/extensions/core/{groupNode.ts => extensions/groupNode/index.ts} (99%) rename src/extensions/core/{ => extensions/groupNodeManage}/groupNodeManage.css (100%) rename src/extensions/core/{groupNodeManage.ts => extensions/groupNodeManage/index.ts} (98%) rename src/extensions/core/{groupOptions.ts => extensions/groupOptions/index.ts} (99%) rename src/extensions/core/{ => extensions}/load3d/AnimationManager.ts (98%) rename src/extensions/core/{ => extensions}/load3d/CameraManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/ControlsManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/EventManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/LightingManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/Load3DConfiguration.ts (97%) rename src/extensions/core/{ => extensions}/load3d/Load3d.ts (100%) rename src/extensions/core/{ => extensions}/load3d/Load3dUtils.ts (100%) rename src/extensions/core/{ => extensions}/load3d/LoaderManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/ModelExporter.ts (100%) rename src/extensions/core/{ => extensions}/load3d/NodeStorage.ts (100%) rename src/extensions/core/{ => extensions}/load3d/RecordingManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/SceneManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/SceneModelManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/ViewHelperManager.ts (100%) rename src/extensions/core/{ => extensions}/load3d/exportMenuHelper.ts (97%) rename src/extensions/core/{load3d.ts => extensions/load3d/index.ts} (98%) rename src/extensions/core/{ => extensions}/load3d/interfaces.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/CanvasHistory.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/MaskEditorDialog.ts (98%) rename src/extensions/core/{ => extensions}/maskeditor/constants.ts (100%) rename src/extensions/core/{maskeditor.ts => extensions/maskeditor/index.ts} (93%) rename src/extensions/core/{ => extensions}/maskeditor/managers/KeyboardManager.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/managers/MessageBroker.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/managers/PanAndZoomManager.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/managers/ToolManager.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/managers/UIManager.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/managers/index.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/styles.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/tools/BrushTool.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/tools/ColorSelectTool.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/tools/PaintBucketTool.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/tools/index.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/types.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/utils/brushCache.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/utils/canvas.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/utils/clipspace.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/utils/image.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/utils/index.ts (100%) rename src/extensions/core/{ => extensions}/maskeditor/utils/maskEditorLayerFilenames.ts (100%) rename src/extensions/core/{matchType.ts => extensions/matchType/index.ts} (100%) rename src/extensions/core/{nodeTemplates.ts => extensions/nodeTemplates/index.ts} (98%) rename src/extensions/core/{noteNode.ts => extensions/noteNode/index.ts} (95%) rename src/extensions/core/{previewAny.ts => extensions/previewAny/index.ts} (100%) rename src/extensions/core/{rerouteNode.ts => extensions/rerouteNode/index.ts} (99%) rename src/extensions/core/{saveImageExtraOutput.ts => extensions/saveImageExtraOutput/index.ts} (97%) rename src/extensions/core/{saveMesh.ts => extensions/saveMesh/index.ts} (93%) rename src/extensions/core/{selectionBorder.ts => extensions/selectionBorder/index.ts} (100%) rename src/extensions/core/{simpleTouchSupport.ts => extensions/simpleTouchSupport/index.ts} (99%) rename src/extensions/core/{slotDefaults.ts => extensions/slotDefaults/index.ts} (97%) rename src/extensions/core/{uploadAudio.ts => extensions/uploadAudio/index.ts} (99%) rename src/extensions/core/{uploadImage.ts => extensions/uploadImage/index.ts} (96%) rename src/extensions/core/{webcamCapture.ts => extensions/webcamCapture/index.ts} (98%) rename src/extensions/core/{widgetInputs.ts => extensions/widgetInputs/index.ts} (100%) create mode 100644 src/extensions/dispatch.ts create mode 100644 src/extensions/types.ts create mode 100644 src/extensions/utils.ts diff --git a/src/components/load3d/Load3DControls.vue b/src/components/load3d/Load3DControls.vue index d587d79d8e..ad7f910b19 100644 --- a/src/components/load3d/Load3DControls.vue +++ b/src/components/load3d/Load3DControls.vue @@ -88,7 +88,7 @@ import type { LightConfig, ModelConfig, SceneConfig -} from '@/extensions/core/load3d/interfaces' +} from '@/extensions/core/extensions/load3d/interfaces' const sceneConfig = defineModel('sceneConfig') const modelConfig = defineModel('modelConfig') diff --git a/src/components/load3d/controls/CameraControls.vue b/src/components/load3d/controls/CameraControls.vue index fb2d153b7f..2e9ff7d889 100644 --- a/src/components/load3d/controls/CameraControls.vue +++ b/src/components/load3d/controls/CameraControls.vue @@ -22,7 +22,7 @@ import Button from 'primevue/button' import { computed } from 'vue' import PopupSlider from '@/components/load3d/controls/PopupSlider.vue' -import type { CameraType } from '@/extensions/core/load3d/interfaces' +import type { CameraType } from '@/extensions/core/extensions/load3d/interfaces' const cameraType = defineModel('cameraType') const fov = defineModel('fov') diff --git a/src/components/load3d/controls/LightControls.vue b/src/components/load3d/controls/LightControls.vue index 1c662af859..f90381e2f2 100644 --- a/src/components/load3d/controls/LightControls.vue +++ b/src/components/load3d/controls/LightControls.vue @@ -35,7 +35,7 @@ import Button from 'primevue/button' import Slider from 'primevue/slider' import { computed, onMounted, onUnmounted, ref } from 'vue' -import type { MaterialMode } from '@/extensions/core/load3d/interfaces' +import type { MaterialMode } from '@/extensions/core/extensions/load3d/interfaces' import { useSettingStore } from '@/platform/settings/settingStore' const lightIntensity = defineModel('lightIntensity') diff --git a/src/components/load3d/controls/ModelControls.vue b/src/components/load3d/controls/ModelControls.vue index eae0092e9a..755e939687 100644 --- a/src/components/load3d/controls/ModelControls.vue +++ b/src/components/load3d/controls/ModelControls.vue @@ -68,7 +68,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue' import type { MaterialMode, UpDirection -} from '@/extensions/core/load3d/interfaces' +} from '@/extensions/core/extensions/load3d/interfaces' import { t } from '@/i18n' const materialMode = defineModel('materialMode') diff --git a/src/components/load3d/controls/SceneControls.vue b/src/components/load3d/controls/SceneControls.vue index 62c57efb8e..91d2fad9ae 100644 --- a/src/components/load3d/controls/SceneControls.vue +++ b/src/components/load3d/controls/SceneControls.vue @@ -95,7 +95,7 @@ import Button from 'primevue/button' import { computed, ref } from 'vue' import PopupSlider from '@/components/load3d/controls/PopupSlider.vue' -import type { BackgroundRenderModeType } from '@/extensions/core/load3d/interfaces' +import type { BackgroundRenderModeType } from '@/extensions/core/extensions/load3d/interfaces' const emit = defineEmits<{ (e: 'updateBackgroundImage', file: File | null): void diff --git a/src/components/load3d/controls/viewer/ViewerCameraControls.vue b/src/components/load3d/controls/viewer/ViewerCameraControls.vue index d675ab77a4..360ce3fc3e 100644 --- a/src/components/load3d/controls/viewer/ViewerCameraControls.vue +++ b/src/components/load3d/controls/viewer/ViewerCameraControls.vue @@ -31,7 +31,7 @@ import Select from 'primevue/select' import Slider from 'primevue/slider' import { computed } from 'vue' -import type { CameraType } from '@/extensions/core/load3d/interfaces' +import type { CameraType } from '@/extensions/core/extensions/load3d/interfaces' import { t } from '@/i18n' const cameras = [ diff --git a/src/components/load3d/controls/viewer/ViewerModelControls.vue b/src/components/load3d/controls/viewer/ViewerModelControls.vue index 24ba788084..962568751e 100644 --- a/src/components/load3d/controls/viewer/ViewerModelControls.vue +++ b/src/components/load3d/controls/viewer/ViewerModelControls.vue @@ -29,7 +29,7 @@ import { computed } from 'vue' import type { MaterialMode, UpDirection -} from '@/extensions/core/load3d/interfaces' +} from '@/extensions/core/extensions/load3d/interfaces' import { t } from '@/i18n' const upDirection = defineModel('upDirection') diff --git a/src/composables/useLoad3d.ts b/src/composables/useLoad3d.ts index 30cfd0cf13..bed6e0c23f 100644 --- a/src/composables/useLoad3d.ts +++ b/src/composables/useLoad3d.ts @@ -2,8 +2,8 @@ import { toRef } from '@vueuse/core' import type { MaybeRef } from '@vueuse/core' import { nextTick, ref, toRaw, watch } from 'vue' -import Load3d from '@/extensions/core/load3d/Load3d' -import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' +import Load3d from '@/extensions/core/extensions/load3d/Load3d' +import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils' import type { AnimationItem, CameraConfig, @@ -13,7 +13,7 @@ import type { ModelConfig, SceneConfig, UpDirection -} from '@/extensions/core/load3d/interfaces' +} from '@/extensions/core/extensions/load3d/interfaces' import { t } from '@/i18n' import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' import { useToastStore } from '@/platform/updates/common/toastStore' diff --git a/src/composables/useLoad3dDrag.ts b/src/composables/useLoad3dDrag.ts index d7d5ea7f03..4557e309f7 100644 --- a/src/composables/useLoad3dDrag.ts +++ b/src/composables/useLoad3dDrag.ts @@ -1,7 +1,7 @@ import { computed, ref, toValue } from 'vue' import type { MaybeRefOrGetter } from 'vue' -import { SUPPORTED_EXTENSIONS } from '@/extensions/core/load3d/interfaces' +import { SUPPORTED_EXTENSIONS } from '@/extensions/core/extensions/load3d/interfaces' import { t } from '@/i18n' import { useToastStore } from '@/platform/updates/common/toastStore' diff --git a/src/composables/useLoad3dViewer.ts b/src/composables/useLoad3dViewer.ts index 93364a8ca1..7ab9ddca11 100644 --- a/src/composables/useLoad3dViewer.ts +++ b/src/composables/useLoad3dViewer.ts @@ -1,13 +1,13 @@ import { ref, toRaw, watch } from 'vue' -import Load3d from '@/extensions/core/load3d/Load3d' -import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' +import Load3d from '@/extensions/core/extensions/load3d/Load3d' +import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils' import type { BackgroundRenderModeType, CameraType, MaterialMode, UpDirection -} from '@/extensions/core/load3d/interfaces' +} from '@/extensions/core/extensions/load3d/interfaces' import { t } from '@/i18n' import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' import { useToastStore } from '@/platform/updates/common/toastStore' diff --git a/src/extensions/core/clipspace.ts b/src/extensions/core/extensions/clipspace/index.ts similarity index 97% rename from src/extensions/core/clipspace.ts rename to src/extensions/core/extensions/clipspace/index.ts index bc644d8d76..dffa61bf84 100644 --- a/src/extensions/core/clipspace.ts +++ b/src/extensions/core/extensions/clipspace/index.ts @@ -1,6 +1,6 @@ -import { app } from '../../scripts/app' -import { ComfyApp } from '../../scripts/app' -import { $el, ComfyDialog } from '../../scripts/ui' +import { app } from '@/scripts/app' +import { ComfyApp } from '@/scripts/app' +import { $el, ComfyDialog } from '@/scripts/ui' export class ClipspaceDialog extends ComfyDialog { static items: Array< diff --git a/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts b/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts new file mode 100644 index 0000000000..e6cde655bf --- /dev/null +++ b/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts @@ -0,0 +1,5 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + comfyCloud: true, +}) diff --git a/src/extensions/core/cloudBadges.ts b/src/extensions/core/extensions/cloudBadges/index.ts similarity index 100% rename from src/extensions/core/cloudBadges.ts rename to src/extensions/core/extensions/cloudBadges/index.ts diff --git a/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts b/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts new file mode 100644 index 0000000000..e6cde655bf --- /dev/null +++ b/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts @@ -0,0 +1,5 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + comfyCloud: true, +}) diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/extensions/cloudFeedbackTopbarButton/index.ts similarity index 100% rename from src/extensions/core/cloudFeedbackTopbarButton.ts rename to src/extensions/core/extensions/cloudFeedbackTopbarButton/index.ts diff --git a/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts b/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts new file mode 100644 index 0000000000..e6cde655bf --- /dev/null +++ b/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts @@ -0,0 +1,5 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + comfyCloud: true, +}) diff --git a/src/extensions/core/cloudRemoteConfig.ts b/src/extensions/core/extensions/cloudRemoteConfig/index.ts similarity index 100% rename from src/extensions/core/cloudRemoteConfig.ts rename to src/extensions/core/extensions/cloudRemoteConfig/index.ts diff --git a/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts b/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts new file mode 100644 index 0000000000..e6cde655bf --- /dev/null +++ b/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts @@ -0,0 +1,5 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + comfyCloud: true, +}) diff --git a/src/extensions/core/cloudSessionCookie.ts b/src/extensions/core/extensions/cloudSessionCookie/index.ts similarity index 100% rename from src/extensions/core/cloudSessionCookie.ts rename to src/extensions/core/extensions/cloudSessionCookie/index.ts diff --git a/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts b/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts new file mode 100644 index 0000000000..059f2284f9 --- /dev/null +++ b/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts @@ -0,0 +1,7 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + comfyCloud: { + subscriptionRequired: true, + }, +}) diff --git a/src/extensions/core/cloudSubscription.ts b/src/extensions/core/extensions/cloudSubscription/index.ts similarity index 100% rename from src/extensions/core/cloudSubscription.ts rename to src/extensions/core/extensions/cloudSubscription/index.ts diff --git a/src/extensions/core/contextMenuFilter.ts b/src/extensions/core/extensions/contextMenuFilter/index.ts similarity index 99% rename from src/extensions/core/contextMenuFilter.ts rename to src/extensions/core/extensions/contextMenuFilter/index.ts index 5cb0e98c58..48b6cae6d5 100644 --- a/src/extensions/core/contextMenuFilter.ts +++ b/src/extensions/core/extensions/contextMenuFilter/index.ts @@ -4,7 +4,7 @@ import { isComboWidget } from '@/lib/litegraph/src/litegraph' -import { app } from '../../scripts/app' +import { app } from '@/scripts/app' // Adds filtering to combo context menus diff --git a/src/extensions/core/dynamicPrompts.ts b/src/extensions/core/extensions/dynamicPrompts/index.ts similarity index 100% rename from src/extensions/core/dynamicPrompts.ts rename to src/extensions/core/extensions/dynamicPrompts/index.ts diff --git a/src/extensions/core/editAttention.ts b/src/extensions/core/extensions/editAttention/index.ts similarity index 99% rename from src/extensions/core/editAttention.ts rename to src/extensions/core/extensions/editAttention/index.ts index 119b277587..5c5fcb6565 100644 --- a/src/extensions/core/editAttention.ts +++ b/src/extensions/core/extensions/editAttention/index.ts @@ -1,4 +1,4 @@ -import { app } from '../../scripts/app' +import { app } from '@/scripts/app' // Allows you to edit the attention weight by holding ctrl (or cmd) and using the up/down arrow keys diff --git a/src/extensions/core/electronAdapter.ts b/src/extensions/core/extensions/electronAdapter/index.ts similarity index 100% rename from src/extensions/core/electronAdapter.ts rename to src/extensions/core/extensions/electronAdapter/index.ts diff --git a/src/extensions/core/groupNode.ts b/src/extensions/core/extensions/groupNode/index.ts similarity index 99% rename from src/extensions/core/groupNode.ts rename to src/extensions/core/extensions/groupNode/index.ts index 5b4146c2d8..76e8ff7eef 100644 --- a/src/extensions/core/groupNode.ts +++ b/src/extensions/core/extensions/groupNode/index.ts @@ -25,10 +25,10 @@ import { ExecutableGroupNodeChildDTO } from '@/utils/executableGroupNodeChildDTO import { GROUP } from '@/utils/executableGroupNodeDto' import { deserialiseAndCreate, serialise } from '@/utils/vintageClipboard' -import { api } from '../../scripts/api' -import { app } from '../../scripts/app' -import { ManageGroupDialog } from './groupNodeManage' -import { mergeIfValid } from './widgetInputs' +import { api } from '@/scripts/api' +import { app } from '@/scripts/app' +import { ManageGroupDialog } from '../groupNodeManage' +import { mergeIfValid } from '../widgetInputs' type GroupNodeWorkflowData = { external: ComfyLink[] diff --git a/src/extensions/core/groupNodeManage.css b/src/extensions/core/extensions/groupNodeManage/groupNodeManage.css similarity index 100% rename from src/extensions/core/groupNodeManage.css rename to src/extensions/core/extensions/groupNodeManage/groupNodeManage.css diff --git a/src/extensions/core/groupNodeManage.ts b/src/extensions/core/extensions/groupNodeManage/index.ts similarity index 98% rename from src/extensions/core/groupNodeManage.ts rename to src/extensions/core/extensions/groupNodeManage/index.ts index 8e52ffccc3..de763df1d3 100644 --- a/src/extensions/core/groupNodeManage.ts +++ b/src/extensions/core/extensions/groupNodeManage/index.ts @@ -6,11 +6,11 @@ import { } from '@/lib/litegraph/src/litegraph' import { useToastStore } from '@/platform/updates/common/toastStore' -import { type ComfyApp, app } from '../../scripts/app' -import { $el } from '../../scripts/ui' -import { ComfyDialog } from '../../scripts/ui/dialog' -import { DraggableList } from '../../scripts/ui/draggableList' -import { GroupNodeConfig, GroupNodeHandler } from './groupNode' +import { type ComfyApp, app } from '@/scripts/app' +import { $el } from '@/scripts/ui' +import { ComfyDialog } from '@/scripts/ui/dialog' +import { DraggableList } from '@/scripts/ui/draggableList' +import { GroupNodeConfig, GroupNodeHandler } from '../groupNode' import './groupNodeManage.css' const ORDER: symbol = Symbol() diff --git a/src/extensions/core/groupOptions.ts b/src/extensions/core/extensions/groupOptions/index.ts similarity index 99% rename from src/extensions/core/groupOptions.ts rename to src/extensions/core/extensions/groupOptions/index.ts index 7e3240bcf7..5c95b509be 100644 --- a/src/extensions/core/groupOptions.ts +++ b/src/extensions/core/extensions/groupOptions/index.ts @@ -10,7 +10,7 @@ import { import { useSettingStore } from '@/platform/settings/settingStore' import type { ComfyExtension } from '@/types/comfy' -import { app } from '../../scripts/app' +import { app } from '@/scripts/app' function setNodeMode(node: LGraphNode, mode: number) { node.mode = mode diff --git a/src/extensions/core/load3d/AnimationManager.ts b/src/extensions/core/extensions/load3d/AnimationManager.ts similarity index 98% rename from src/extensions/core/load3d/AnimationManager.ts rename to src/extensions/core/extensions/load3d/AnimationManager.ts index a451da8cdc..6b79ac789c 100644 --- a/src/extensions/core/load3d/AnimationManager.ts +++ b/src/extensions/core/extensions/load3d/AnimationManager.ts @@ -4,7 +4,7 @@ import { type AnimationItem, type AnimationManagerInterface, type EventManagerInterface -} from '@/extensions/core/load3d/interfaces' +} from './interfaces' export class AnimationManager implements AnimationManagerInterface { currentAnimation: THREE.AnimationMixer | null = null diff --git a/src/extensions/core/load3d/CameraManager.ts b/src/extensions/core/extensions/load3d/CameraManager.ts similarity index 100% rename from src/extensions/core/load3d/CameraManager.ts rename to src/extensions/core/extensions/load3d/CameraManager.ts diff --git a/src/extensions/core/load3d/ControlsManager.ts b/src/extensions/core/extensions/load3d/ControlsManager.ts similarity index 100% rename from src/extensions/core/load3d/ControlsManager.ts rename to src/extensions/core/extensions/load3d/ControlsManager.ts diff --git a/src/extensions/core/load3d/EventManager.ts b/src/extensions/core/extensions/load3d/EventManager.ts similarity index 100% rename from src/extensions/core/load3d/EventManager.ts rename to src/extensions/core/extensions/load3d/EventManager.ts diff --git a/src/extensions/core/load3d/LightingManager.ts b/src/extensions/core/extensions/load3d/LightingManager.ts similarity index 100% rename from src/extensions/core/load3d/LightingManager.ts rename to src/extensions/core/extensions/load3d/LightingManager.ts diff --git a/src/extensions/core/load3d/Load3DConfiguration.ts b/src/extensions/core/extensions/load3d/Load3DConfiguration.ts similarity index 97% rename from src/extensions/core/load3d/Load3DConfiguration.ts rename to src/extensions/core/extensions/load3d/Load3DConfiguration.ts index a914de3883..e9c363ea26 100644 --- a/src/extensions/core/load3d/Load3DConfiguration.ts +++ b/src/extensions/core/extensions/load3d/Load3DConfiguration.ts @@ -1,11 +1,11 @@ -import Load3d from '@/extensions/core/load3d/Load3d' -import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' +import Load3d from './Load3d' +import Load3dUtils from './Load3dUtils' import type { CameraConfig, LightConfig, ModelConfig, SceneConfig -} from '@/extensions/core/load3d/interfaces' +} from './interfaces' import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets' import { useSettingStore } from '@/platform/settings/settingStore' import { api } from '@/scripts/api' diff --git a/src/extensions/core/load3d/Load3d.ts b/src/extensions/core/extensions/load3d/Load3d.ts similarity index 100% rename from src/extensions/core/load3d/Load3d.ts rename to src/extensions/core/extensions/load3d/Load3d.ts diff --git a/src/extensions/core/load3d/Load3dUtils.ts b/src/extensions/core/extensions/load3d/Load3dUtils.ts similarity index 100% rename from src/extensions/core/load3d/Load3dUtils.ts rename to src/extensions/core/extensions/load3d/Load3dUtils.ts diff --git a/src/extensions/core/load3d/LoaderManager.ts b/src/extensions/core/extensions/load3d/LoaderManager.ts similarity index 100% rename from src/extensions/core/load3d/LoaderManager.ts rename to src/extensions/core/extensions/load3d/LoaderManager.ts diff --git a/src/extensions/core/load3d/ModelExporter.ts b/src/extensions/core/extensions/load3d/ModelExporter.ts similarity index 100% rename from src/extensions/core/load3d/ModelExporter.ts rename to src/extensions/core/extensions/load3d/ModelExporter.ts diff --git a/src/extensions/core/load3d/NodeStorage.ts b/src/extensions/core/extensions/load3d/NodeStorage.ts similarity index 100% rename from src/extensions/core/load3d/NodeStorage.ts rename to src/extensions/core/extensions/load3d/NodeStorage.ts diff --git a/src/extensions/core/load3d/RecordingManager.ts b/src/extensions/core/extensions/load3d/RecordingManager.ts similarity index 100% rename from src/extensions/core/load3d/RecordingManager.ts rename to src/extensions/core/extensions/load3d/RecordingManager.ts diff --git a/src/extensions/core/load3d/SceneManager.ts b/src/extensions/core/extensions/load3d/SceneManager.ts similarity index 100% rename from src/extensions/core/load3d/SceneManager.ts rename to src/extensions/core/extensions/load3d/SceneManager.ts diff --git a/src/extensions/core/load3d/SceneModelManager.ts b/src/extensions/core/extensions/load3d/SceneModelManager.ts similarity index 100% rename from src/extensions/core/load3d/SceneModelManager.ts rename to src/extensions/core/extensions/load3d/SceneModelManager.ts diff --git a/src/extensions/core/load3d/ViewHelperManager.ts b/src/extensions/core/extensions/load3d/ViewHelperManager.ts similarity index 100% rename from src/extensions/core/load3d/ViewHelperManager.ts rename to src/extensions/core/extensions/load3d/ViewHelperManager.ts diff --git a/src/extensions/core/load3d/exportMenuHelper.ts b/src/extensions/core/extensions/load3d/exportMenuHelper.ts similarity index 97% rename from src/extensions/core/load3d/exportMenuHelper.ts rename to src/extensions/core/extensions/load3d/exportMenuHelper.ts index d87146cc3a..15aaae9f10 100644 --- a/src/extensions/core/load3d/exportMenuHelper.ts +++ b/src/extensions/core/extensions/load3d/exportMenuHelper.ts @@ -1,7 +1,7 @@ import { t } from '@/i18n' import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces' import { useToastStore } from '@/platform/updates/common/toastStore' -import Load3d from '@/extensions/core/load3d/Load3d' +import Load3d from './Load3d' import { LiteGraph } from '@/lib/litegraph/src/litegraph' const EXPORT_FORMATS = [ diff --git a/src/extensions/core/load3d.ts b/src/extensions/core/extensions/load3d/index.ts similarity index 98% rename from src/extensions/core/load3d.ts rename to src/extensions/core/extensions/load3d/index.ts index 143054c65c..7487b9299c 100644 --- a/src/extensions/core/load3d.ts +++ b/src/extensions/core/extensions/load3d/index.ts @@ -3,9 +3,9 @@ import { nextTick } from 'vue' import Load3D from '@/components/load3d/Load3D.vue' import Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue' import { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d' -import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper' -import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration' -import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' +import { createExportMenuItems } from './exportMenuHelper' +import Load3DConfiguration from './Load3DConfiguration' +import Load3dUtils from './Load3dUtils' import { t } from '@/i18n' import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces' diff --git a/src/extensions/core/load3d/interfaces.ts b/src/extensions/core/extensions/load3d/interfaces.ts similarity index 100% rename from src/extensions/core/load3d/interfaces.ts rename to src/extensions/core/extensions/load3d/interfaces.ts diff --git a/src/extensions/core/maskeditor/CanvasHistory.ts b/src/extensions/core/extensions/maskeditor/CanvasHistory.ts similarity index 100% rename from src/extensions/core/maskeditor/CanvasHistory.ts rename to src/extensions/core/extensions/maskeditor/CanvasHistory.ts diff --git a/src/extensions/core/maskeditor/MaskEditorDialog.ts b/src/extensions/core/extensions/maskeditor/MaskEditorDialog.ts similarity index 98% rename from src/extensions/core/maskeditor/MaskEditorDialog.ts rename to src/extensions/core/extensions/maskeditor/MaskEditorDialog.ts index 1362069aa5..b9d4d85d87 100644 --- a/src/extensions/core/maskeditor/MaskEditorDialog.ts +++ b/src/extensions/core/extensions/maskeditor/MaskEditorDialog.ts @@ -1,7 +1,7 @@ import { t } from '@/i18n' -import { api } from '../../../scripts/api' -import { ComfyApp } from '../../../scripts/app' -import { $el, ComfyDialog } from '../../../scripts/ui' +import { api } from '@/scripts/api' +import { ComfyApp } from '@/scripts/app' +import { $el, ComfyDialog } from '@/scripts/ui' import { ClipspaceDialog } from '../clipspace' import { imageLayerFilenamesByTimestamp } from './utils/maskEditorLayerFilenames' import { CanvasHistory } from './CanvasHistory' diff --git a/src/extensions/core/maskeditor/constants.ts b/src/extensions/core/extensions/maskeditor/constants.ts similarity index 100% rename from src/extensions/core/maskeditor/constants.ts rename to src/extensions/core/extensions/maskeditor/constants.ts diff --git a/src/extensions/core/maskeditor.ts b/src/extensions/core/extensions/maskeditor/index.ts similarity index 93% rename from src/extensions/core/maskeditor.ts rename to src/extensions/core/extensions/maskeditor/index.ts index dd51be475b..b280deb576 100644 --- a/src/extensions/core/maskeditor.ts +++ b/src/extensions/core/extensions/maskeditor/index.ts @@ -1,13 +1,13 @@ import _ from 'es-toolkit/compat' -import { app } from '../../scripts/app' -import { ComfyApp } from '../../scripts/app' -import { ClipspaceDialog } from './clipspace' -import { MaskEditorDialog } from './maskeditor/MaskEditorDialog' -import { MaskEditorDialogOld } from './maskEditorOld' +import { app } from '@/scripts/app' +import { ComfyApp } from '@/scripts/app' +import { ClipspaceDialog } from '../clipspace' +import { MaskEditorDialog } from './MaskEditorDialog' +import { MaskEditorDialogOld } from '../../maskEditorOld' // Import styles to inject into document -import './maskeditor/styles' +import './styles' // Function to open the mask editor function openMaskEditor(): void { diff --git a/src/extensions/core/maskeditor/managers/KeyboardManager.ts b/src/extensions/core/extensions/maskeditor/managers/KeyboardManager.ts similarity index 100% rename from src/extensions/core/maskeditor/managers/KeyboardManager.ts rename to src/extensions/core/extensions/maskeditor/managers/KeyboardManager.ts diff --git a/src/extensions/core/maskeditor/managers/MessageBroker.ts b/src/extensions/core/extensions/maskeditor/managers/MessageBroker.ts similarity index 100% rename from src/extensions/core/maskeditor/managers/MessageBroker.ts rename to src/extensions/core/extensions/maskeditor/managers/MessageBroker.ts diff --git a/src/extensions/core/maskeditor/managers/PanAndZoomManager.ts b/src/extensions/core/extensions/maskeditor/managers/PanAndZoomManager.ts similarity index 100% rename from src/extensions/core/maskeditor/managers/PanAndZoomManager.ts rename to src/extensions/core/extensions/maskeditor/managers/PanAndZoomManager.ts diff --git a/src/extensions/core/maskeditor/managers/ToolManager.ts b/src/extensions/core/extensions/maskeditor/managers/ToolManager.ts similarity index 100% rename from src/extensions/core/maskeditor/managers/ToolManager.ts rename to src/extensions/core/extensions/maskeditor/managers/ToolManager.ts diff --git a/src/extensions/core/maskeditor/managers/UIManager.ts b/src/extensions/core/extensions/maskeditor/managers/UIManager.ts similarity index 100% rename from src/extensions/core/maskeditor/managers/UIManager.ts rename to src/extensions/core/extensions/maskeditor/managers/UIManager.ts diff --git a/src/extensions/core/maskeditor/managers/index.ts b/src/extensions/core/extensions/maskeditor/managers/index.ts similarity index 100% rename from src/extensions/core/maskeditor/managers/index.ts rename to src/extensions/core/extensions/maskeditor/managers/index.ts diff --git a/src/extensions/core/maskeditor/styles.ts b/src/extensions/core/extensions/maskeditor/styles.ts similarity index 100% rename from src/extensions/core/maskeditor/styles.ts rename to src/extensions/core/extensions/maskeditor/styles.ts diff --git a/src/extensions/core/maskeditor/tools/BrushTool.ts b/src/extensions/core/extensions/maskeditor/tools/BrushTool.ts similarity index 100% rename from src/extensions/core/maskeditor/tools/BrushTool.ts rename to src/extensions/core/extensions/maskeditor/tools/BrushTool.ts diff --git a/src/extensions/core/maskeditor/tools/ColorSelectTool.ts b/src/extensions/core/extensions/maskeditor/tools/ColorSelectTool.ts similarity index 100% rename from src/extensions/core/maskeditor/tools/ColorSelectTool.ts rename to src/extensions/core/extensions/maskeditor/tools/ColorSelectTool.ts diff --git a/src/extensions/core/maskeditor/tools/PaintBucketTool.ts b/src/extensions/core/extensions/maskeditor/tools/PaintBucketTool.ts similarity index 100% rename from src/extensions/core/maskeditor/tools/PaintBucketTool.ts rename to src/extensions/core/extensions/maskeditor/tools/PaintBucketTool.ts diff --git a/src/extensions/core/maskeditor/tools/index.ts b/src/extensions/core/extensions/maskeditor/tools/index.ts similarity index 100% rename from src/extensions/core/maskeditor/tools/index.ts rename to src/extensions/core/extensions/maskeditor/tools/index.ts diff --git a/src/extensions/core/maskeditor/types.ts b/src/extensions/core/extensions/maskeditor/types.ts similarity index 100% rename from src/extensions/core/maskeditor/types.ts rename to src/extensions/core/extensions/maskeditor/types.ts diff --git a/src/extensions/core/maskeditor/utils/brushCache.ts b/src/extensions/core/extensions/maskeditor/utils/brushCache.ts similarity index 100% rename from src/extensions/core/maskeditor/utils/brushCache.ts rename to src/extensions/core/extensions/maskeditor/utils/brushCache.ts diff --git a/src/extensions/core/maskeditor/utils/canvas.ts b/src/extensions/core/extensions/maskeditor/utils/canvas.ts similarity index 100% rename from src/extensions/core/maskeditor/utils/canvas.ts rename to src/extensions/core/extensions/maskeditor/utils/canvas.ts diff --git a/src/extensions/core/maskeditor/utils/clipspace.ts b/src/extensions/core/extensions/maskeditor/utils/clipspace.ts similarity index 100% rename from src/extensions/core/maskeditor/utils/clipspace.ts rename to src/extensions/core/extensions/maskeditor/utils/clipspace.ts diff --git a/src/extensions/core/maskeditor/utils/image.ts b/src/extensions/core/extensions/maskeditor/utils/image.ts similarity index 100% rename from src/extensions/core/maskeditor/utils/image.ts rename to src/extensions/core/extensions/maskeditor/utils/image.ts diff --git a/src/extensions/core/maskeditor/utils/index.ts b/src/extensions/core/extensions/maskeditor/utils/index.ts similarity index 100% rename from src/extensions/core/maskeditor/utils/index.ts rename to src/extensions/core/extensions/maskeditor/utils/index.ts diff --git a/src/extensions/core/maskeditor/utils/maskEditorLayerFilenames.ts b/src/extensions/core/extensions/maskeditor/utils/maskEditorLayerFilenames.ts similarity index 100% rename from src/extensions/core/maskeditor/utils/maskEditorLayerFilenames.ts rename to src/extensions/core/extensions/maskeditor/utils/maskEditorLayerFilenames.ts diff --git a/src/extensions/core/matchType.ts b/src/extensions/core/extensions/matchType/index.ts similarity index 100% rename from src/extensions/core/matchType.ts rename to src/extensions/core/extensions/matchType/index.ts diff --git a/src/extensions/core/nodeTemplates.ts b/src/extensions/core/extensions/nodeTemplates/index.ts similarity index 98% rename from src/extensions/core/nodeTemplates.ts rename to src/extensions/core/extensions/nodeTemplates/index.ts index c16ebed72d..92f7627ba9 100644 --- a/src/extensions/core/nodeTemplates.ts +++ b/src/extensions/core/extensions/nodeTemplates/index.ts @@ -7,10 +7,10 @@ import { useDialogService } from '@/services/dialogService' import type { ComfyExtension } from '@/types/comfy' import { deserialiseAndCreate } from '@/utils/vintageClipboard' -import { api } from '../../scripts/api' -import { app } from '../../scripts/app' -import { $el, ComfyDialog } from '../../scripts/ui' -import { GroupNodeConfig, GroupNodeHandler } from './groupNode' +import { api } from '@/scripts/api' +import { app } from '@/scripts/app' +import { $el, ComfyDialog } from '@/scripts/ui' +import { GroupNodeConfig, GroupNodeHandler } from '../groupNode' // Adds the ability to save and add multiple nodes as a template // To save: diff --git a/src/extensions/core/noteNode.ts b/src/extensions/core/extensions/noteNode/index.ts similarity index 95% rename from src/extensions/core/noteNode.ts rename to src/extensions/core/extensions/noteNode/index.ts index 8b2d9ed992..5e5af5ca5c 100644 --- a/src/extensions/core/noteNode.ts +++ b/src/extensions/core/extensions/noteNode/index.ts @@ -1,8 +1,8 @@ import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph' import { LGraphNode } from '@/lib/litegraph/src/litegraph' -import { app } from '../../scripts/app' -import { ComfyWidgets } from '../../scripts/widgets' +import { app } from '@/scripts/app' +import { ComfyWidgets } from '@/scripts/widgets' // Node that add notes to your project diff --git a/src/extensions/core/previewAny.ts b/src/extensions/core/extensions/previewAny/index.ts similarity index 100% rename from src/extensions/core/previewAny.ts rename to src/extensions/core/extensions/previewAny/index.ts diff --git a/src/extensions/core/rerouteNode.ts b/src/extensions/core/extensions/rerouteNode/index.ts similarity index 99% rename from src/extensions/core/rerouteNode.ts rename to src/extensions/core/extensions/rerouteNode/index.ts index 44c3f3150f..f597b7a78c 100644 --- a/src/extensions/core/rerouteNode.ts +++ b/src/extensions/core/extensions/rerouteNode/index.ts @@ -6,8 +6,8 @@ import { } from '@/lib/litegraph/src/litegraph' import type { ISlotType } from '@/lib/litegraph/src/interfaces' -import { app } from '../../scripts/app' -import { getWidgetConfig, mergeIfValid, setWidgetConfig } from './widgetInputs' +import { app } from '@/scripts/app' +import { getWidgetConfig, mergeIfValid, setWidgetConfig } from '../widgetInputs' // Node that allows you to redirect connections for cleaner graphs diff --git a/src/extensions/core/saveImageExtraOutput.ts b/src/extensions/core/extensions/saveImageExtraOutput/index.ts similarity index 97% rename from src/extensions/core/saveImageExtraOutput.ts rename to src/extensions/core/extensions/saveImageExtraOutput/index.ts index f216f31a7d..313bac4381 100644 --- a/src/extensions/core/saveImageExtraOutput.ts +++ b/src/extensions/core/extensions/saveImageExtraOutput/index.ts @@ -1,6 +1,6 @@ import { applyTextReplacements } from '@/utils/searchAndReplace' -import { app } from '../../scripts/app' +import { app } from '@/scripts/app' const saveNodeTypes = new Set([ 'SaveImage', diff --git a/src/extensions/core/saveMesh.ts b/src/extensions/core/extensions/saveMesh/index.ts similarity index 93% rename from src/extensions/core/saveMesh.ts rename to src/extensions/core/extensions/saveMesh/index.ts index 0955fe4cc5..d16f4bcc14 100644 --- a/src/extensions/core/saveMesh.ts +++ b/src/extensions/core/extensions/saveMesh/index.ts @@ -2,8 +2,8 @@ import { nextTick } from 'vue' import Load3D from '@/components/load3d/Load3D.vue' import { useLoad3d } from '@/composables/useLoad3d' -import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper' -import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration' +import { createExportMenuItems } from '../load3d/exportMenuHelper' +import Load3DConfiguration from '../load3d/Load3DConfiguration' import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces' import { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' diff --git a/src/extensions/core/selectionBorder.ts b/src/extensions/core/extensions/selectionBorder/index.ts similarity index 100% rename from src/extensions/core/selectionBorder.ts rename to src/extensions/core/extensions/selectionBorder/index.ts diff --git a/src/extensions/core/simpleTouchSupport.ts b/src/extensions/core/extensions/simpleTouchSupport/index.ts similarity index 99% rename from src/extensions/core/simpleTouchSupport.ts rename to src/extensions/core/extensions/simpleTouchSupport/index.ts index c129711ec8..742d247352 100644 --- a/src/extensions/core/simpleTouchSupport.ts +++ b/src/extensions/core/extensions/simpleTouchSupport/index.ts @@ -1,6 +1,6 @@ import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph' -import { app } from '../../scripts/app' +import { app } from '@/scripts/app' let touchZooming = false let touchCount = 0 diff --git a/src/extensions/core/slotDefaults.ts b/src/extensions/core/extensions/slotDefaults/index.ts similarity index 97% rename from src/extensions/core/slotDefaults.ts rename to src/extensions/core/extensions/slotDefaults/index.ts index f7ca293a44..63d91f70ea 100644 --- a/src/extensions/core/slotDefaults.ts +++ b/src/extensions/core/extensions/slotDefaults/index.ts @@ -1,7 +1,7 @@ import { LiteGraph } from '@/lib/litegraph/src/litegraph' -import { app } from '../../scripts/app' -import { ComfyWidgets } from '../../scripts/widgets' +import { app } from '@/scripts/app' +import { ComfyWidgets } from '@/scripts/widgets' // Adds defaults for quickly adding nodes with middle click on the input/output diff --git a/src/extensions/core/uploadAudio.ts b/src/extensions/core/extensions/uploadAudio/index.ts similarity index 99% rename from src/extensions/core/uploadAudio.ts rename to src/extensions/core/extensions/uploadAudio/index.ts index dfefc88a0f..a6523b6e68 100644 --- a/src/extensions/core/uploadAudio.ts +++ b/src/extensions/core/extensions/uploadAudio/index.ts @@ -21,8 +21,8 @@ import { useAudioService } from '@/services/audioService' import { type NodeLocatorId } from '@/types' import { getNodeByLocatorId } from '@/utils/graphTraversalUtil' -import { api } from '../../scripts/api' -import { app } from '../../scripts/app' +import { api } from '@/scripts/api' +import { app } from '@/scripts/app' async function uploadFile( audioWidget: IStringWidget, diff --git a/src/extensions/core/uploadImage.ts b/src/extensions/core/extensions/uploadImage/index.ts similarity index 96% rename from src/extensions/core/uploadImage.ts rename to src/extensions/core/extensions/uploadImage/index.ts index 4cb910dae1..9849d393f7 100644 --- a/src/extensions/core/uploadImage.ts +++ b/src/extensions/core/extensions/uploadImage/index.ts @@ -4,7 +4,7 @@ import { isComboInputSpecV1 } from '@/schemas/nodeDefSchema' -import { app } from '../../scripts/app' +import { app } from '@/scripts/app' // Adds an upload button to the nodes diff --git a/src/extensions/core/webcamCapture.ts b/src/extensions/core/extensions/webcamCapture/index.ts similarity index 98% rename from src/extensions/core/webcamCapture.ts rename to src/extensions/core/extensions/webcamCapture/index.ts index f429ddda49..fee4562a59 100644 --- a/src/extensions/core/webcamCapture.ts +++ b/src/extensions/core/extensions/webcamCapture/index.ts @@ -1,8 +1,8 @@ import { t } from '@/i18n' import { useToastStore } from '@/platform/updates/common/toastStore' -import { api } from '../../scripts/api' -import { app } from '../../scripts/app' +import { api } from '@/scripts/api' +import { app } from '@/scripts/app' const WEBCAM_READY = Symbol() diff --git a/src/extensions/core/widgetInputs.ts b/src/extensions/core/extensions/widgetInputs/index.ts similarity index 100% rename from src/extensions/core/widgetInputs.ts rename to src/extensions/core/extensions/widgetInputs/index.ts diff --git a/src/extensions/core/index.ts b/src/extensions/core/index.ts index 4171dce89d..54d02399f1 100644 --- a/src/extensions/core/index.ts +++ b/src/extensions/core/index.ts @@ -1,38 +1,15 @@ -import { isCloud } from '@/platform/distribution/types' +import { dispatchComfyExtensions } from '../dispatch' -import './clipspace' -import './contextMenuFilter' -import './dynamicPrompts' -import './editAttention' -import './electronAdapter' -import './groupNode' -import './groupNodeManage' -import './groupOptions' -import './load3d' -import './maskeditor' -import './matchType' -import './nodeTemplates' -import './noteNode' -import './previewAny' -import './rerouteNode' -import './saveImageExtraOutput' -import './saveMesh' -import './selectionBorder' -import './simpleTouchSupport' -import './slotDefaults' -import './uploadAudio' -import './uploadImage' -import './webcamCapture' -import './widgetInputs' +export async function importExtensions() { + console.log('importExtensions running...') -// Cloud-only extensions - tree-shaken in OSS builds -if (isCloud) { - await import('./cloudRemoteConfig') - await import('./cloudBadges') - await import('./cloudSessionCookie') - await import('./cloudFeedbackTopbarButton') + const extConfigs = import.meta.glob(`./extensions/*/comfy.ext.config.ts`, { + // Since each config is small, we only import the default export and use eager mode for better tree-shaking and performance. + import: 'default', + eager: true, + }) + const extensionEntrance = import.meta.glob(`./extensions/*/index.ts`) - if (window.__CONFIG__?.subscription_required) { - await import('./cloudSubscription') - } + dispatchComfyExtensions({ configs: extConfigs, entrance: extensionEntrance }) } + diff --git a/src/extensions/core/maskEditorOld.ts b/src/extensions/core/maskEditorOld.ts index e34c3f225a..b849ebaa19 100644 --- a/src/extensions/core/maskEditorOld.ts +++ b/src/extensions/core/maskEditorOld.ts @@ -2,7 +2,7 @@ import { api } from '../../scripts/api' import { app } from '../../scripts/app' import { ComfyApp } from '../../scripts/app' import { $el, ComfyDialog } from '../../scripts/ui' -import { ClipspaceDialog } from './clipspace' +import { ClipspaceDialog } from './extensions/clipspace' // Helper function to convert a data URL to a Blob object // @ts-expect-error fixme ts strict error diff --git a/src/extensions/dispatch.ts b/src/extensions/dispatch.ts new file mode 100644 index 0000000000..3b81e5848d --- /dev/null +++ b/src/extensions/dispatch.ts @@ -0,0 +1,32 @@ +import { isCloud } from '@/platform/distribution/types' +import type { + ComfyExtensionConfigs, + ComfyExtensionEntrance, + ComfyExtensionLoadContext +} from './types' +import { formatExtensions, shouldLoadExtension } from './utils' + +const extLoadContext: ComfyExtensionLoadContext = { + get isCloud() { + return isCloud + }, + get subscriptionRequired() { + return !!window.__CONFIG__?.subscription_required + } +} + +export async function dispatchComfyExtensions(options: { + configs: ComfyExtensionConfigs + entrance: ComfyExtensionEntrance +}) { + const { configs, entrance } = options + const extensions = formatExtensions(entrance, configs) + for (const extension of Object.values(extensions)) { + if (shouldLoadExtension(extLoadContext, extension.config)) { + const module = await extension.entry() + console.log('✅ extension', extension.name, 'loaded', extension, module) + } else { + console.log('❌ extension', extension.name, 'disabled', extension.config) + } + } +} diff --git a/src/extensions/types.ts b/src/extensions/types.ts new file mode 100644 index 0000000000..aa12c34156 --- /dev/null +++ b/src/extensions/types.ts @@ -0,0 +1,30 @@ +export interface ComfyExtensionConfig { + comfyCloud?: + | boolean + | { + subscriptionRequired: boolean + } +} +export type ComfyExtensionConfigs = Record< + string, + ComfyExtensionConfig | undefined +> + +export interface ComfyExtensionLoadContext { + readonly isCloud: boolean + readonly subscriptionRequired: boolean +} + +export type ComfyExtensionEntry = () => Promise> +export type ComfyExtensionEntrance = Record< + string, + ComfyExtensionEntry | undefined +> + +export interface ComfyExtensionPackage { + name?: string + path?: string + config?: ComfyExtensionConfig + entry: ComfyExtensionEntry +} +export type ComfyExtensionPackages = Record diff --git a/src/extensions/utils.ts b/src/extensions/utils.ts new file mode 100644 index 0000000000..cdad268e8e --- /dev/null +++ b/src/extensions/utils.ts @@ -0,0 +1,59 @@ +import type { + ComfyExtensionConfig, + ComfyExtensionConfigs, + ComfyExtensionEntrance, + ComfyExtensionLoadContext, + ComfyExtensionPackages +} from './types' + +export function defineComfyExtConfig( + config: ComfyExtensionConfig +): ComfyExtensionConfig { + return config +} + +export function formatExtensions( + entrance: ComfyExtensionEntrance, + configs: ComfyExtensionConfigs +): ComfyExtensionPackages { + const pkgs: ComfyExtensionPackages = {} + for (const [entryPath, entry] of Object.entries(entrance)) { + const pathArr = entryPath.split('/') + const name = pathArr.at(-2)! + const path = pathArr.slice(0, -1).join('/') + if (!name) { + console.error(`Extension`, path, `has no name`) + continue + } + if (!entry) { + console.error(`Extension`, path, `has no entrance`) + continue + } + + const config = configs[`${path}/comfy.ext.config.ts`] + if (!config) { + console.warn(`⚠️ Extension`, path, `has no config`) + } + pkgs[name] = { name, path, config, entry } + } + return pkgs +} + +export function shouldLoadExtension( + ctx: ComfyExtensionLoadContext, + extConfig: ComfyExtensionConfig | undefined +): boolean { + // No Config -> Load Extension + if (!extConfig) return true + + // Cloud Only Extension + const { comfyCloud } = extConfig + if (comfyCloud) { + if (!ctx.isCloud) return false + if (comfyCloud === true) return true + return comfyCloud.subscriptionRequired && ctx.subscriptionRequired + } + + // Default Extension -> Load Extension + return true +} diff --git a/src/renderer/utils/nodeTypeGuards.ts b/src/renderer/utils/nodeTypeGuards.ts index 9a13edfb57..619c1a4f40 100644 --- a/src/renderer/utils/nodeTypeGuards.ts +++ b/src/renderer/utils/nodeTypeGuards.ts @@ -1,4 +1,4 @@ -import type { PrimitiveNode } from '@/extensions/core/widgetInputs' +import type { PrimitiveNode } from '@/extensions/core/extensions/widgetInputs' import type { LGraphNode } from '@/lib/litegraph/src/litegraph' export const isPrimitiveNode = ( diff --git a/src/services/extensionService.ts b/src/services/extensionService.ts index 75b159e11e..8e15ad1376 100644 --- a/src/services/extensionService.ts +++ b/src/services/extensionService.ts @@ -35,7 +35,8 @@ export const useExtensionService = () => { // Need to load core extensions first as some custom extensions // may depend on them. - await import('../extensions/core/index') + const { importExtensions } = await import('../extensions/core/index') + await importExtensions() extensionStore.captureCoreExtensions() await Promise.all( extensions diff --git a/src/services/load3dService.ts b/src/services/load3dService.ts index e910f4b4d4..d7be9aa742 100644 --- a/src/services/load3dService.ts +++ b/src/services/load3dService.ts @@ -2,7 +2,7 @@ import { toRaw } from 'vue' import { nodeToLoad3dMap } from '@/composables/useLoad3d' import { useLoad3dViewer } from '@/composables/useLoad3dViewer' -import type Load3d from '@/extensions/core/load3d/Load3d' +import type Load3d from '@/extensions/core/extensions/load3d/Load3d' import type { LGraphNode } from '@/lib/litegraph/src/litegraph' import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema' diff --git a/src/utils/executableGroupNodeChildDTO.ts b/src/utils/executableGroupNodeChildDTO.ts index b129f2d103..d42daafa1b 100644 --- a/src/utils/executableGroupNodeChildDTO.ts +++ b/src/utils/executableGroupNodeChildDTO.ts @@ -1,4 +1,4 @@ -import type { GroupNodeHandler } from '@/extensions/core/groupNode' +import type { GroupNodeHandler } from '@/extensions/core/extensions/groupNode' import { ExecutableNodeDTO } from '@/lib/litegraph/src/litegraph' import type { ExecutableLGraphNode, diff --git a/tests-ui/tests/composables/useLoad3d.test.ts b/tests-ui/tests/composables/useLoad3d.test.ts index fadafa4f87..1ed282036f 100644 --- a/tests-ui/tests/composables/useLoad3d.test.ts +++ b/tests-ui/tests/composables/useLoad3d.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { nextTick, ref } from 'vue' import { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d' -import Load3d from '@/extensions/core/load3d/Load3d' -import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' +import Load3d from '@/extensions/core/extensions/load3d/Load3d' +import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils' import { useToastStore } from '@/platform/updates/common/toastStore' import { api } from '@/scripts/api' -vi.mock('@/extensions/core/load3d/Load3d', () => ({ +vi.mock('@/extensions/core/extensions/load3d/Load3d', () => ({ default: vi.fn() })) -vi.mock('@/extensions/core/load3d/Load3dUtils', () => ({ +vi.mock('@/extensions/core/extensions/load3d/Load3dUtils', () => ({ default: { splitFilePath: vi.fn(), getResourceURL: vi.fn(), diff --git a/tests-ui/tests/composables/useLoad3dViewer.test.ts b/tests-ui/tests/composables/useLoad3dViewer.test.ts index 4ec2d77984..7b65d51e10 100644 --- a/tests-ui/tests/composables/useLoad3dViewer.test.ts +++ b/tests-ui/tests/composables/useLoad3dViewer.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { nextTick } from 'vue' import { useLoad3dViewer } from '@/composables/useLoad3dViewer' -import Load3d from '@/extensions/core/load3d/Load3d' -import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' +import Load3d from '@/extensions/core/extensions/load3d/Load3d' +import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils' import { useToastStore } from '@/platform/updates/common/toastStore' import { useLoad3dService } from '@/services/load3dService' @@ -15,7 +15,7 @@ vi.mock('@/platform/updates/common/toastStore', () => ({ useToastStore: vi.fn() })) -vi.mock('@/extensions/core/load3d/Load3dUtils', () => ({ +vi.mock('@/extensions/core/extensions/load3d/Load3dUtils', () => ({ default: { uploadFile: vi.fn() } @@ -25,7 +25,7 @@ vi.mock('@/i18n', () => ({ t: vi.fn((key) => key) })) -vi.mock('@/extensions/core/load3d/Load3d', () => ({ +vi.mock('@/extensions/core/extensions/load3d/Load3d', () => ({ default: vi.fn() })) diff --git a/tests-ui/tests/maskeditor.test.ts b/tests-ui/tests/maskeditor.test.ts index 448c2cb422..4b60792007 100644 --- a/tests-ui/tests/maskeditor.test.ts +++ b/tests-ui/tests/maskeditor.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' -import { imageLayerFilenamesIfApplicable } from '@/extensions/core/maskeditor/utils/maskEditorLayerFilenames' +import { imageLayerFilenamesIfApplicable } from '@/extensions/core/extensions/maskeditor/utils/maskEditorLayerFilenames' describe('imageLayerFilenamesIfApplicable', () => { // In case the naming scheme changes, this test will ensure CI fails if developers forget to support the old naming scheme. (Causing MaskEditor to lose layer data for previously-saved images.) diff --git a/tests-ui/tests/utils/executableGroupNodeChildDTO.test.ts b/tests-ui/tests/utils/executableGroupNodeChildDTO.test.ts index 6b2fb3ffa8..497fc211f3 100644 --- a/tests-ui/tests/utils/executableGroupNodeChildDTO.test.ts +++ b/tests-ui/tests/utils/executableGroupNodeChildDTO.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' -import type { GroupNodeHandler } from '@/extensions/core/groupNode' +import type { GroupNodeHandler } from '@/extensions/core/extensions/groupNode' import type { ExecutableLGraphNode, ExecutionId, From f1856b7a1762fca71a4dd36d7b8174d46c024fc3 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Thu, 13 Nov 2025 19:21:43 +0800 Subject: [PATCH 2/6] refactor: activation events + contributes --- .../cloudBadges/comfy.ext.config.ts | 2 + .../comfy.ext.config.ts | 2 + .../cloudRemoteConfig/comfy.ext.config.ts | 2 + .../cloudSessionCookie/comfy.ext.config.ts | 2 + .../cloudSubscription/comfy.ext.config.ts | 2 + .../extensions/load3d/comfy.ext.config.ts | 111 ++++++++++++++++++ .../extensions/saveMesh/comfy.ext.config.ts | 12 ++ src/extensions/core/index.ts | 7 +- src/extensions/dispatch.ts | 60 +++++++++- src/extensions/types.ts | 43 +++++++ src/extensions/utils.ts | 61 +++++++++- src/services/extensionService.ts | 9 +- 12 files changed, 298 insertions(+), 15 deletions(-) create mode 100644 src/extensions/core/extensions/load3d/comfy.ext.config.ts create mode 100644 src/extensions/core/extensions/saveMesh/comfy.ext.config.ts diff --git a/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts b/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts index e6cde655bf..7cc79f9f61 100644 --- a/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts +++ b/src/extensions/core/extensions/cloudBadges/comfy.ext.config.ts @@ -1,5 +1,7 @@ import { defineComfyExtConfig } from '@/extensions/utils' export default defineComfyExtConfig({ + name: 'Comfy.Cloud.Badges', + activationEvents: ['*'], comfyCloud: true, }) diff --git a/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts b/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts index e6cde655bf..6a7164e70a 100644 --- a/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts +++ b/src/extensions/core/extensions/cloudFeedbackTopbarButton/comfy.ext.config.ts @@ -1,5 +1,7 @@ import { defineComfyExtConfig } from '@/extensions/utils' export default defineComfyExtConfig({ + name: 'Comfy.Cloud.FeedbackButton', + activationEvents: ['*'], comfyCloud: true, }) diff --git a/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts b/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts index e6cde655bf..393068a6f9 100644 --- a/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts +++ b/src/extensions/core/extensions/cloudRemoteConfig/comfy.ext.config.ts @@ -1,5 +1,7 @@ import { defineComfyExtConfig } from '@/extensions/utils' export default defineComfyExtConfig({ + name: 'Comfy.Cloud.RemoteConfig', + activationEvents: ['*'], comfyCloud: true, }) diff --git a/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts b/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts index e6cde655bf..8356d90d62 100644 --- a/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts +++ b/src/extensions/core/extensions/cloudSessionCookie/comfy.ext.config.ts @@ -1,5 +1,7 @@ import { defineComfyExtConfig } from '@/extensions/utils' export default defineComfyExtConfig({ + name: 'Comfy.Cloud.SessionCookie', + activationEvents: ['*'], comfyCloud: true, }) diff --git a/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts b/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts index 059f2284f9..7e52058127 100644 --- a/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts +++ b/src/extensions/core/extensions/cloudSubscription/comfy.ext.config.ts @@ -1,6 +1,8 @@ import { defineComfyExtConfig } from '@/extensions/utils' export default defineComfyExtConfig({ + name: 'Comfy.Cloud.Subscription', + activationEvents: ['*'], comfyCloud: { subscriptionRequired: true, }, diff --git a/src/extensions/core/extensions/load3d/comfy.ext.config.ts b/src/extensions/core/extensions/load3d/comfy.ext.config.ts new file mode 100644 index 0000000000..426a973f77 --- /dev/null +++ b/src/extensions/core/extensions/load3d/comfy.ext.config.ts @@ -0,0 +1,111 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + name: 'Comfy.Load3D', + activationEvents: ['onWidgets:contributes', 'onCommands:contributes', 'onSettings:contributes'], + contributes: [ + { + name: 'Comfy.Preview3D', + widgets: ['PREVIEW_3D'], + }, + { + name: 'Comfy.Load3D', + widgets: ['LOAD_3D'], + settings: [ + { + id: 'Comfy.Load3D.ShowGrid', + category: ['3D', 'Scene', 'Initial Grid Visibility'], + name: 'Initial Grid Visibility', + tooltip: + 'Controls whether the grid is visible by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.', + type: 'boolean', + defaultValue: true, + experimental: true + }, + { + id: 'Comfy.Load3D.BackgroundColor', + category: ['3D', 'Scene', 'Initial Background Color'], + name: 'Initial Background Color', + tooltip: + 'Controls the default background color of the 3D scene. This setting determines the background appearance when a new 3D widget is created, but can be adjusted individually for each widget after creation.', + type: 'color', + defaultValue: '282828', + experimental: true + }, + { + id: 'Comfy.Load3D.CameraType', + category: ['3D', 'Camera', 'Initial Camera Type'], + name: 'Initial Camera Type', + tooltip: + 'Controls whether the camera is perspective or orthographic by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.', + type: 'combo', + options: ['perspective', 'orthographic'], + defaultValue: 'perspective', + experimental: true + }, + { + id: 'Comfy.Load3D.LightIntensity', + category: ['3D', 'Light', 'Initial Light Intensity'], + name: 'Initial Light Intensity', + tooltip: + 'Sets the default brightness level of lighting in the 3D scene. This value determines how intensely lights illuminate objects when a new 3D widget is created, but can be adjusted individually for each widget after creation.', + type: 'number', + defaultValue: 3, + experimental: true + }, + { + id: 'Comfy.Load3D.LightIntensityMaximum', + category: ['3D', 'Light', 'Light Intensity Maximum'], + name: 'Light Intensity Maximum', + tooltip: + 'Sets the maximum allowable light intensity value for 3D scenes. This defines the upper brightness limit that can be set when adjusting lighting in any 3D widget.', + type: 'number', + defaultValue: 10, + experimental: true + }, + { + id: 'Comfy.Load3D.LightIntensityMinimum', + category: ['3D', 'Light', 'Light Intensity Minimum'], + name: 'Light Intensity Minimum', + tooltip: + 'Sets the minimum allowable light intensity value for 3D scenes. This defines the lower brightness limit that can be set when adjusting lighting in any 3D widget.', + type: 'number', + defaultValue: 1, + experimental: true + }, + { + id: 'Comfy.Load3D.LightAdjustmentIncrement', + category: ['3D', 'Light', 'Light Adjustment Increment'], + name: 'Light Adjustment Increment', + tooltip: + 'Controls the increment size when adjusting light intensity in 3D scenes. A smaller step value allows for finer control over lighting adjustments, while a larger value results in more noticeable changes per adjustment.', + type: 'slider', + attrs: { + min: 0.1, + max: 1, + step: 0.1 + }, + defaultValue: 0.5, + experimental: true + }, + { + id: 'Comfy.Load3D.3DViewerEnable', + category: ['3D', '3DViewer', 'Enable'], + name: 'Enable 3D Viewer (Beta)', + tooltip: + 'Enables the 3D Viewer (Beta) for selected nodes. This feature allows you to visualize and interact with 3D models directly within the full size 3d viewer.', + type: 'boolean', + defaultValue: false, + experimental: true + } + ], + commands: [ + { + id: 'Comfy.3DViewer.Open3DViewer', + icon: 'pi pi-pencil', + label: 'Open 3D Viewer (Beta) for Selected Node', + } + ], + }, + ], +}) diff --git a/src/extensions/core/extensions/saveMesh/comfy.ext.config.ts b/src/extensions/core/extensions/saveMesh/comfy.ext.config.ts new file mode 100644 index 0000000000..aea78abfc0 --- /dev/null +++ b/src/extensions/core/extensions/saveMesh/comfy.ext.config.ts @@ -0,0 +1,12 @@ +import { defineComfyExtConfig } from '@/extensions/utils' + +export default defineComfyExtConfig({ + name: 'Comfy.SaveGLB', + activationEvents: ['onWidgets:contributes', 'onCommands:contributes', 'onSettings:contributes'], + contributes: [ + { + name: 'Comfy.SaveGLB', + widgets: ['SAVE_GLB'], + }, + ], +}) diff --git a/src/extensions/core/index.ts b/src/extensions/core/index.ts index 54d02399f1..c00d6a21d4 100644 --- a/src/extensions/core/index.ts +++ b/src/extensions/core/index.ts @@ -1,14 +1,15 @@ import { dispatchComfyExtensions } from '../dispatch' +import type { ComfyExtensionConfigs, ComfyExtensionEntrance } from '../types' -export async function importExtensions() { +export async function registerExtensions() { console.log('importExtensions running...') const extConfigs = import.meta.glob(`./extensions/*/comfy.ext.config.ts`, { // Since each config is small, we only import the default export and use eager mode for better tree-shaking and performance. import: 'default', eager: true, - }) - const extensionEntrance = import.meta.glob(`./extensions/*/index.ts`) + }) as ComfyExtensionConfigs + const extensionEntrance = import.meta.glob(`./extensions/*/index.ts`) as ComfyExtensionEntrance dispatchComfyExtensions({ configs: extConfigs, entrance: extensionEntrance }) } diff --git a/src/extensions/dispatch.ts b/src/extensions/dispatch.ts index 3b81e5848d..6a94dd92a0 100644 --- a/src/extensions/dispatch.ts +++ b/src/extensions/dispatch.ts @@ -4,7 +4,7 @@ import type { ComfyExtensionEntrance, ComfyExtensionLoadContext } from './types' -import { formatExtensions, shouldLoadExtension } from './utils' +import { formatExtensions, normalizationActivationEvents } from './utils' const extLoadContext: ComfyExtensionLoadContext = { get isCloud() { @@ -22,11 +22,61 @@ export async function dispatchComfyExtensions(options: { const { configs, entrance } = options const extensions = formatExtensions(entrance, configs) for (const extension of Object.values(extensions)) { - if (shouldLoadExtension(extLoadContext, extension.config)) { - const module = await extension.entry() - console.log('✅ extension', extension.name, 'loaded', extension, module) + // if (shouldLoadExtension(extLoadContext, extension.config)) { + // const module = await extension.entry() + // console.log('✅ extension', extension.name, 'loaded', extension, module) + // } else { + // console.log('❌ extension', extension.name, 'disabled', extension.config) + // } + const activationEvents = normalizationActivationEvents( + extLoadContext, + extension.config + ) + if (!activationEvents.length) { + console.log( + '❌ extension', + extension.name, + 'has no activation events', + extension.config + ) } else { - console.log('❌ extension', extension.name, 'disabled', extension.config) + console.log( + '🧶 extension', + extension.name, + 'has activation events:', + activationEvents + ) } + activationEvents.forEach((event) => + onceExtImportEvent(event, async ({ event }) => { + console.log( + '✅ extension', + extension.name, + 'loaded by', + event, + extension + ) + await extension.entry() + }) + ) + } +} + +type EventCallback = (ctx: { event: string }) => void | Promise + +const eventMap = new Map>() + +export async function importExtensionsByEvent(event: string) { + const callbacks = eventMap.get(event) + if (!callbacks) return + eventMap.delete(event) + await Promise.all([...callbacks].map((cb) => cb({ event }))) +} + +function onceExtImportEvent(event: string, callback: EventCallback) { + if (eventMap.has(event)) { + eventMap.get(event)!.add(callback) + } else { + eventMap.set(event, new Set([callback])) } } diff --git a/src/extensions/types.ts b/src/extensions/types.ts index aa12c34156..fa788933c7 100644 --- a/src/extensions/types.ts +++ b/src/extensions/types.ts @@ -1,4 +1,47 @@ +import type { ComfyExtension } from '@/types' + +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +type ExcludeFunctions = T extends Function ? never : T +type StaticOnly = { + // eslint-disable-next-line prettier/prettier + [K in keyof T as ExcludeFunctions extends never ? never : K]: ExcludeFunctions +} + +type StaticComfyCommand = StaticOnly< + NonNullable[number] +> +type StaticComfySettingParams = StaticOnly< + NonNullable[number] +> +type StaticComfyKeybinding = StaticOnly< + NonNullable[number] +> +type StaticComfyMenuCommandGroup = StaticOnly< + NonNullable[number] +> + +export type ComfyExtensionActivationEvent = + | '*' + | 'onWidgets:contributes' + | 'onCommands:contributes' + | 'onSettings:contributes' + +type ComfyExtensionContributes = { + name: string + widgets?: string[] + commands?: StaticComfyCommand[] + settings?: StaticComfySettingParams[] + keybindings?: StaticComfyKeybinding[] +} + export interface ComfyExtensionConfig { + name?: string + + activationEvents: ComfyExtensionActivationEvent[] + + contributes?: ComfyExtensionContributes | ComfyExtensionContributes[] + menuCommands?: StaticComfyMenuCommandGroup[] + comfyCloud?: | boolean | { diff --git a/src/extensions/utils.ts b/src/extensions/utils.ts index cdad268e8e..3d773da534 100644 --- a/src/extensions/utils.ts +++ b/src/extensions/utils.ts @@ -39,13 +39,64 @@ export function formatExtensions( return pkgs } -export function shouldLoadExtension( +export function normalizationActivationEvents( ctx: ComfyExtensionLoadContext, - extConfig: ComfyExtensionConfig | undefined -): boolean { - // No Config -> Load Extension - if (!extConfig) return true + config: ComfyExtensionConfig | undefined +): string[] { + if (!config) return ['*'] + + if (!checkAboutCloud(ctx, config)) return [] + + const { activationEvents, contributes: _contributes } = config + + if (activationEvents.includes('*')) return ['*'] + + const contributes = _contributes + ? Array.isArray(_contributes) + ? _contributes + : [_contributes] + : [] + const events: string[] = [] + + if (activationEvents.includes('onCommands:contributes')) { + for (const contribute of contributes) { + if (contribute.commands) { + for (const command of contribute.commands) { + events.push(`onCommands:${command}`) + } + } + } + } + + if (activationEvents.includes('onSettings:contributes')) { + for (const contribute of contributes) { + if (contribute.settings) { + for (const setting of contribute.settings) { + events.push(`onSettings:${setting.id}`) + } + } + } + } + + if (activationEvents.includes('onWidgets:contributes')) { + for (const contribute of contributes) { + events.push(`onWidgets:${contribute.name}`) + if (contribute.widgets) { + for (const widget of contribute.widgets) { + events.push(`onWidgets:${widget}`) + } + } + } + } + + return events +} + +function checkAboutCloud( + ctx: ComfyExtensionLoadContext, + extConfig: ComfyExtensionConfig +): boolean { // Cloud Only Extension const { comfyCloud } = extConfig if (comfyCloud) { diff --git a/src/services/extensionService.ts b/src/services/extensionService.ts index 8e15ad1376..ed705ecf99 100644 --- a/src/services/extensionService.ts +++ b/src/services/extensionService.ts @@ -12,6 +12,7 @@ import { useWidgetStore } from '@/stores/widgetStore' import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore' import type { ComfyExtension } from '@/types/comfy' import type { AuthUserInfo } from '@/types/authTypes' +import { importExtensionsByEvent } from '@/extensions/dispatch' export const useExtensionService = () => { const extensionStore = useExtensionStore() @@ -35,8 +36,12 @@ export const useExtensionService = () => { // Need to load core extensions first as some custom extensions // may depend on them. - const { importExtensions } = await import('../extensions/core/index') - await importExtensions() + const { registerExtensions } = await import('../extensions/core/index') + await registerExtensions() + + // Import Immediately Loaded Extensions + await importExtensionsByEvent('*') + extensionStore.captureCoreExtensions() await Promise.all( extensions From f1cb6dad2048de0ffca8e8810f7a51d9190d5fa7 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Thu, 13 Nov 2025 20:51:11 +0800 Subject: [PATCH 3/6] feat: send onWidgets event --- src/extensions/dispatch.ts | 4 +++ src/extensions/utils.ts | 1 - src/services/litegraphService.ts | 55 +++++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/extensions/dispatch.ts b/src/extensions/dispatch.ts index 6a94dd92a0..ba88fab1cd 100644 --- a/src/extensions/dispatch.ts +++ b/src/extensions/dispatch.ts @@ -73,6 +73,10 @@ export async function importExtensionsByEvent(event: string) { await Promise.all([...callbacks].map((cb) => cb({ event }))) } +export function extentionsImportEventHas(event: string) { + return eventMap.has(event) +} + function onceExtImportEvent(event: string, callback: EventCallback) { if (eventMap.has(event)) { eventMap.get(event)!.add(callback) diff --git a/src/extensions/utils.ts b/src/extensions/utils.ts index 3d773da534..0741e414da 100644 --- a/src/extensions/utils.ts +++ b/src/extensions/utils.ts @@ -81,7 +81,6 @@ export function normalizationActivationEvents( if (activationEvents.includes('onWidgets:contributes')) { for (const contribute of contributes) { - events.push(`onWidgets:${contribute.name}`) if (contribute.widgets) { for (const widget of contribute.widgets) { events.push(`onWidgets:${widget}`) diff --git a/src/services/litegraphService.ts b/src/services/litegraphService.ts index 35562533b2..074226a3de 100644 --- a/src/services/litegraphService.ts +++ b/src/services/litegraphService.ts @@ -58,10 +58,44 @@ import { import { getOrderedInputSpecs } from '@/workbench/utils/nodeDefOrderingUtil' import { useExtensionService } from './extensionService' +import { + extentionsImportEventHas, + importExtensionsByEvent +} from '@/extensions/dispatch' export const CONFIG = Symbol() export const GET_CONFIG = Symbol() +function addInputsAndimportWidgetsAsNeeded(options: { + orderedInputSpecs: InputSpec[] + addInputSocket: (inputSpec: InputSpec) => void + addInputWidget: (inputSpec: InputSpec) => void +}) { + const { orderedInputSpecs, addInputSocket, addInputWidget } = options + const awaitedInputSpecs: InputSpec[] = [] + const syncInputSpecs: InputSpec[] = [] + const importJobs: Promise[] = [] + for (const inputSpec of orderedInputSpecs) { + const widgetType = inputSpec.widgetType ?? inputSpec.type + if (extentionsImportEventHas(`onWidgets:${widgetType}`)) { + importJobs.push(importExtensionsByEvent(`onWidgets:${widgetType}`)) + awaitedInputSpecs.push(inputSpec) + } else { + syncInputSpecs.push(inputSpec) + } + } + + ;(async () => { + await Promise.all(importJobs) + for (const inputSpec of awaitedInputSpecs) addInputSocket(inputSpec) + for (const inputSpec of awaitedInputSpecs) addInputWidget(inputSpec) + })() + + // Create sockets and widgets in the determined order + for (const inputSpec of syncInputSpecs) addInputSocket(inputSpec) + for (const inputSpec of syncInputSpecs) addInputWidget(inputSpec) +} + /** * Service that augments litegraph with ComfyUI specific functionality. */ @@ -244,12 +278,11 @@ export const useLitegraphService = () => { // Use input_order if available to ensure consistent widget ordering const nodeDefImpl = ComfyNode.nodeData as ComfyNodeDefImpl const orderedInputSpecs = getOrderedInputSpecs(nodeDefImpl, inputs) - - // Create sockets and widgets in the determined order - for (const inputSpec of orderedInputSpecs) - this.#addInputSocket(inputSpec) - for (const inputSpec of orderedInputSpecs) - this.#addInputWidget(inputSpec) + addInputsAndimportWidgetsAsNeeded({ + orderedInputSpecs, + addInputSocket: this.#addInputSocket.bind(this), + addInputWidget: this.#addInputWidget.bind(this) + }) } /** @@ -521,11 +554,11 @@ export const useLitegraphService = () => { const nodeDefImpl = ComfyNode.nodeData as ComfyNodeDefImpl const orderedInputSpecs = getOrderedInputSpecs(nodeDefImpl, inputs) - // Create sockets and widgets in the determined order - for (const inputSpec of orderedInputSpecs) - this.#addInputSocket(inputSpec) - for (const inputSpec of orderedInputSpecs) - this.#addInputWidget(inputSpec) + addInputsAndimportWidgetsAsNeeded({ + orderedInputSpecs, + addInputSocket: this.#addInputSocket.bind(this), + addInputWidget: this.#addInputWidget.bind(this) + }) } /** From 40dd82ca41310d5207d9bc41656aa0f3ac33eb7b Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Thu, 13 Nov 2025 21:04:09 +0800 Subject: [PATCH 4/6] chore: remove debug console.log --- src/extensions/dispatch.ts | 32 +------------------------------- src/extensions/utils.ts | 6 +++--- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/src/extensions/dispatch.ts b/src/extensions/dispatch.ts index ba88fab1cd..a527d38868 100644 --- a/src/extensions/dispatch.ts +++ b/src/extensions/dispatch.ts @@ -22,42 +22,12 @@ export async function dispatchComfyExtensions(options: { const { configs, entrance } = options const extensions = formatExtensions(entrance, configs) for (const extension of Object.values(extensions)) { - // if (shouldLoadExtension(extLoadContext, extension.config)) { - // const module = await extension.entry() - // console.log('✅ extension', extension.name, 'loaded', extension, module) - // } else { - // console.log('❌ extension', extension.name, 'disabled', extension.config) - // } const activationEvents = normalizationActivationEvents( extLoadContext, extension.config ) - if (!activationEvents.length) { - console.log( - '❌ extension', - extension.name, - 'has no activation events', - extension.config - ) - } else { - console.log( - '🧶 extension', - extension.name, - 'has activation events:', - activationEvents - ) - } activationEvents.forEach((event) => - onceExtImportEvent(event, async ({ event }) => { - console.log( - '✅ extension', - extension.name, - 'loaded by', - event, - extension - ) - await extension.entry() - }) + onceExtImportEvent(event, async () => void (await extension.entry())) ) } } diff --git a/src/extensions/utils.ts b/src/extensions/utils.ts index 0741e414da..8b28f930e0 100644 --- a/src/extensions/utils.ts +++ b/src/extensions/utils.ts @@ -31,9 +31,9 @@ export function formatExtensions( } const config = configs[`${path}/comfy.ext.config.ts`] - if (!config) { - console.warn(`⚠️ Extension`, path, `has no config`) - } + // if (!config) { + // console.warn(`Extension`, path, `has no config`) + // } pkgs[name] = { name, path, config, entry } } return pkgs From 60016007008877f259e0e36b0a659c98eae468d2 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Fri, 14 Nov 2025 15:42:39 +0800 Subject: [PATCH 5/6] feat: config process queue --- src/extensions/dispatch.ts | 44 ++++++++++++++++++++++++++++++++++++-- src/extensions/types.ts | 14 ++++++------ src/extensions/utils.ts | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/extensions/dispatch.ts b/src/extensions/dispatch.ts index a527d38868..efd2166eea 100644 --- a/src/extensions/dispatch.ts +++ b/src/extensions/dispatch.ts @@ -2,9 +2,17 @@ import { isCloud } from '@/platform/distribution/types' import type { ComfyExtensionConfigs, ComfyExtensionEntrance, - ComfyExtensionLoadContext + ComfyExtensionLoadContext, + StaticComfyCommand, + StaticComfyKeybinding, + StaticComfyMenuCommandGroup, + StaticComfySettingParams } from './types' -import { formatExtensions, normalizationActivationEvents } from './utils' +import { + defineProcessQueue, + formatExtensions, + normalizationActivationEvents +} from './utils' const extLoadContext: ComfyExtensionLoadContext = { get isCloud() { @@ -29,6 +37,18 @@ export async function dispatchComfyExtensions(options: { activationEvents.forEach((event) => onceExtImportEvent(event, async () => void (await extension.entry())) ) + + let contributes = extension.config?.contributes + if (contributes && !Array.isArray(contributes)) contributes = [contributes] + if (contributes && contributes.length) { + for (const contribute of contributes) { + const { settings, commands, keybindings, menuCommands } = contribute + if (settings) pushExtensionSettings(settings) + if (commands) pushExtensionCommands(commands) + if (keybindings) pushExtensionKeybindings(keybindings) + if (menuCommands) pushExtensionMenuCommands(menuCommands) + } + } } } @@ -54,3 +74,23 @@ function onceExtImportEvent(event: string, callback: EventCallback) { eventMap.set(event, new Set([callback])) } } + +const { process: _processExtensionSettings, push: pushExtensionSettings } = + defineProcessQueue() +export const processExtensionSettings = _processExtensionSettings + +const { process: _processExtensionCommands, push: pushExtensionCommands } = + defineProcessQueue() +export const processExtensionCommands = _processExtensionCommands + +const { + process: _processExtensionMenuCommands, + push: pushExtensionMenuCommands +} = defineProcessQueue() +export const processExtensionMenuCommands = _processExtensionMenuCommands + +const { + process: _processExtensionKeybindings, + push: pushExtensionKeybindings +} = defineProcessQueue() +export const processExtensionKeybindings = _processExtensionKeybindings diff --git a/src/extensions/types.ts b/src/extensions/types.ts index fa788933c7..bb5ffde4c5 100644 --- a/src/extensions/types.ts +++ b/src/extensions/types.ts @@ -4,19 +4,21 @@ import type { ComfyExtension } from '@/types' type ExcludeFunctions = T extends Function ? never : T type StaticOnly = { // eslint-disable-next-line prettier/prettier - [K in keyof T as ExcludeFunctions extends never ? never : K]: ExcludeFunctions + [K in keyof T as ExcludeFunctions extends never + ? never + : K]: ExcludeFunctions } -type StaticComfyCommand = StaticOnly< +export type StaticComfyCommand = StaticOnly< NonNullable[number] > -type StaticComfySettingParams = StaticOnly< +export type StaticComfySettingParams = StaticOnly< NonNullable[number] > -type StaticComfyKeybinding = StaticOnly< +export type StaticComfyKeybinding = StaticOnly< NonNullable[number] > -type StaticComfyMenuCommandGroup = StaticOnly< +export type StaticComfyMenuCommandGroup = StaticOnly< NonNullable[number] > @@ -30,6 +32,7 @@ type ComfyExtensionContributes = { name: string widgets?: string[] commands?: StaticComfyCommand[] + menuCommands?: StaticComfyMenuCommandGroup[] settings?: StaticComfySettingParams[] keybindings?: StaticComfyKeybinding[] } @@ -40,7 +43,6 @@ export interface ComfyExtensionConfig { activationEvents: ComfyExtensionActivationEvent[] contributes?: ComfyExtensionContributes | ComfyExtensionContributes[] - menuCommands?: StaticComfyMenuCommandGroup[] comfyCloud?: | boolean diff --git a/src/extensions/utils.ts b/src/extensions/utils.ts index 8b28f930e0..d6539a9aec 100644 --- a/src/extensions/utils.ts +++ b/src/extensions/utils.ts @@ -107,3 +107,42 @@ function checkAboutCloud( // Default Extension -> Load Extension return true } + +/** + * Defines a queue processing function for handling elements in a queue. + * When elements are present in the queue, all existing elements are automatically retrieved + * and passed to the callback function for processing. + * Use the process method to register a callback function, and use the push method to add elements to the queue. + * @returns Returns an object containing process and push methods + */ +export function defineProcessQueue(): { + process: (worker: (items: T[]) => void) => void + push: (items: T[]) => void +} { + let worker: ((items: T[]) => void) | undefined = undefined + const items: T[] = [] + function push(newItems: T[]) { + items.push(...newItems) + consume() + } + function process(newWorker: (items: T[]) => void) { + if (worker) { + throw new Error('queue worker already registered') + } + worker = newWorker + consume() + } + + function consume() { + if (worker !== undefined && items.length > 0) { + const itemsToProcess = items.slice() + items.length = 0 + worker(itemsToProcess) + } + } + + return { + process, + push + } +} From c985fff434875fa7b8218ee6ff70b3e791429f74 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Mon, 17 Nov 2025 17:27:28 +0800 Subject: [PATCH 6/6] feat: process extension settings --- src/platform/settings/settingStore.ts | 10 ++++++++++ src/stores/keybindingStore.ts | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/platform/settings/settingStore.ts b/src/platform/settings/settingStore.ts index 5a1573efbf..6629455f20 100644 --- a/src/platform/settings/settingStore.ts +++ b/src/platform/settings/settingStore.ts @@ -8,6 +8,8 @@ import type { Settings } from '@/schemas/apiSchema' import { api } from '@/scripts/api' import { app } from '@/scripts/app' import type { TreeNode } from '@/types/treeExplorerTypes' +import { processExtensionSettings } from '@/extensions/dispatch' +import { useErrorHandling } from '@/composables/useErrorHandling' export const getSettingInfo = (setting: SettingParams) => { const parts = setting.category || setting.id.split('.') @@ -46,6 +48,14 @@ export const useSettingStore = defineStore('setting', () => { const settingValues = ref>({}) const settingsById = ref>({}) + const { wrapWithErrorHandling } = useErrorHandling() + processExtensionSettings((settings) => { + const _addSetting = wrapWithErrorHandling(addSetting) + for (const setting of settings) { + _addSetting(setting) + } + }) + /** * Check if a setting's value exists, i.e. if the user has set it manually. * @param key - The key of the setting to check. diff --git a/src/stores/keybindingStore.ts b/src/stores/keybindingStore.ts index 76a21120cc..5973d471b9 100644 --- a/src/stores/keybindingStore.ts +++ b/src/stores/keybindingStore.ts @@ -5,6 +5,8 @@ import { computed, ref, toRaw } from 'vue' import { RESERVED_BY_TEXT_INPUT } from '@/constants/reservedKeyCombos' import type { KeyCombo, Keybinding } from '@/schemas/keyBindingSchema' +import { processExtensionKeybindings } from '@/extensions/dispatch' +import { useErrorHandling } from '@/composables/useErrorHandling' export class KeybindingImpl implements Keybinding { commandId: string @@ -171,6 +173,14 @@ export const useKeybindingStore = defineStore('keybinding', () => { } ) + const { wrapWithErrorHandling } = useErrorHandling() + processExtensionKeybindings((keybindings) => { + const addKeybinding = wrapWithErrorHandling(addDefaultKeybinding) + for (const keybinding of keybindings) { + addKeybinding(new KeybindingImpl(keybinding)) + } + }) + function getKeybindingsByCommandId(commandId: string) { return keybindingsByCommandId.value[commandId] ?? [] }