mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-02 03:30:04 +00:00
Add frontend extension management panel (#1141)
* Manage register of extension in pinia * Add disabled extensions setting * nit * Disable extension * Add virtual divider * Basic extension panel * Style cell * nit * Fix loading * inactive rules * nit * Calculate changes * nit * Experimental setting guard
This commit is contained in:
@@ -420,5 +420,20 @@ export const CORE_SETTINGS: SettingParams[] = [
|
||||
type: 'hidden',
|
||||
defaultValue: [] as Keybinding[],
|
||||
versionAdded: '1.3.7'
|
||||
},
|
||||
{
|
||||
id: 'Comfy.Extension.Disabled',
|
||||
name: 'Disabled extension names',
|
||||
type: 'hidden',
|
||||
defaultValue: [] as string[],
|
||||
versionAdded: '1.3.11'
|
||||
},
|
||||
{
|
||||
id: 'Comfy.Settings.ExtensionPanel',
|
||||
name: 'Show extension panel in settings dialog',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
experimental: true,
|
||||
versionAdded: '1.3.11'
|
||||
}
|
||||
]
|
||||
|
||||
81
src/stores/extensionStore.ts
Normal file
81
src/stores/extensionStore.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { ref, computed, markRaw } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { ComfyExtension } from '@/types/comfy'
|
||||
import { useKeybindingStore } from './keybindingStore'
|
||||
import { useCommandStore } from './commandStore'
|
||||
import { useSettingStore } from './settingStore'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
export const useExtensionStore = defineStore('extension', () => {
|
||||
// For legacy reasons, the name uniquely identifies an extension
|
||||
const extensionByName = ref<Record<string, ComfyExtension>>({})
|
||||
const extensions = computed(() => Object.values(extensionByName.value))
|
||||
// Not using computed because disable extension requires reloading of the page.
|
||||
// Dynamically update this list won't affect extensions that are already loaded.
|
||||
const disabledExtensionNames = ref<Set<string>>(new Set())
|
||||
|
||||
// Disabled extension names that are currently not in the extension list.
|
||||
// If a node pack is disabled in the backend, we shouldn't remove the configuration
|
||||
// of the frontend extension disable list, in case the node pack is re-enabled.
|
||||
const inactiveDisabledExtensionNames = computed(() => {
|
||||
return Array.from(disabledExtensionNames.value).filter(
|
||||
(name) => !(name in extensionByName.value)
|
||||
)
|
||||
})
|
||||
|
||||
const isExtensionEnabled = (name: string) =>
|
||||
!disabledExtensionNames.value.has(name)
|
||||
const enabledExtensions = computed(() => {
|
||||
return extensions.value.filter((ext) => isExtensionEnabled(ext.name))
|
||||
})
|
||||
|
||||
function registerExtension(extension: ComfyExtension) {
|
||||
if (!extension.name) {
|
||||
throw new Error("Extensions must have a 'name' property.")
|
||||
}
|
||||
|
||||
if (extensionByName.value[extension.name]) {
|
||||
throw new Error(`Extension named '${extension.name}' already registered.`)
|
||||
}
|
||||
|
||||
if (disabledExtensionNames.value.has(extension.name)) {
|
||||
console.log(`Extension ${extension.name} is disabled.`)
|
||||
}
|
||||
|
||||
extensionByName.value[extension.name] = markRaw(extension)
|
||||
useKeybindingStore().loadExtensionKeybindings(extension)
|
||||
useCommandStore().loadExtensionCommands(extension)
|
||||
|
||||
/*
|
||||
* Extensions are currently stored in both extensionStore and app.extensions.
|
||||
* Legacy jest tests still depend on app.extensions being populated.
|
||||
*/
|
||||
app.extensions.push(extension)
|
||||
}
|
||||
|
||||
function loadDisabledExtensionNames() {
|
||||
disabledExtensionNames.value = new Set(
|
||||
useSettingStore().get('Comfy.Extension.Disabled')
|
||||
)
|
||||
// pysssss.Locking is replaced by pin/unpin in ComfyUI core.
|
||||
// https://github.com/Comfy-Org/litegraph.js/pull/117
|
||||
disabledExtensionNames.value.add('pysssss.Locking')
|
||||
}
|
||||
|
||||
// Some core extensions are registered before the store is initialized, e.g.
|
||||
// colorPalette.
|
||||
// Register them manually here so the state of app.extensions and
|
||||
// extensionByName are in sync.
|
||||
for (const ext of app.extensions) {
|
||||
extensionByName.value[ext.name] = markRaw(ext)
|
||||
}
|
||||
|
||||
return {
|
||||
extensions,
|
||||
enabledExtensions,
|
||||
inactiveDisabledExtensionNames,
|
||||
isExtensionEnabled,
|
||||
registerExtension,
|
||||
loadDisabledExtensionNames
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user