mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
refactor(lora-pool-widget): adopt DOM widget value persistence best practices
- Replace custom onSetValue with ComfyUI's built-in widget.callback - Remove widget.updateConfig, set widget.value directly - Add isRestoring flag to break callback → watch → refreshPreview loop - Update ComponentWidget types with callback and deprecate old methods Refs: docs/dom-widgets/value-persistence-best-practices.md
This commit is contained in:
@@ -95,29 +95,29 @@ const openModal = (modal: ModalType) => {
|
|||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// Setup serialization
|
// Setup callback for external value updates (e.g., workflow load, undo/redo)
|
||||||
props.widget.serializeValue = async () => {
|
// ComfyUI calls this automatically after setValue() in domWidget.ts
|
||||||
const config = state.buildConfig()
|
// NOTE: callback should NOT call refreshPreview() to avoid infinite loops:
|
||||||
console.log('[LoraPoolWidget] Serializing config:', config)
|
// watch(filters) → refreshPreview() → buildConfig() → widget.value = v → callback → refreshPreview() → ...
|
||||||
return config
|
props.widget.callback = (v: LoraPoolConfig | LegacyLoraPoolConfig) => {
|
||||||
|
if (v) {
|
||||||
|
console.log('[LoraPoolWidget] Restoring config from callback')
|
||||||
|
state.restoreFromConfig(v)
|
||||||
|
// Preview will refresh automatically via watch() when restoreFromConfig changes filter refs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle external value updates (e.g., loading workflow, paste)
|
// Restore from saved value if workflow was already loaded
|
||||||
props.widget.onSetValue = (v) => {
|
|
||||||
state.restoreFromConfig(v as LoraPoolConfig | LegacyLoraPoolConfig)
|
|
||||||
state.refreshPreview()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore from saved value
|
|
||||||
if (props.widget.value) {
|
if (props.widget.value) {
|
||||||
console.log('[LoraPoolWidget] Restoring from saved value:', props.widget.value)
|
console.log('[LoraPoolWidget] Restoring from initial value')
|
||||||
state.restoreFromConfig(props.widget.value as LoraPoolConfig | LegacyLoraPoolConfig)
|
state.restoreFromConfig(props.widget.value as LoraPoolConfig | LegacyLoraPoolConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch filter options
|
// Fetch filter options
|
||||||
await state.fetchFilterOptions()
|
await state.fetchFilterOptions()
|
||||||
|
|
||||||
// Initial preview
|
// Initial preview (only called once on mount)
|
||||||
|
// When workflow is loaded, callback restores config, then watch triggers this
|
||||||
await state.refreshPreview()
|
await state.refreshPreview()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -99,8 +99,13 @@ export interface CyclerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentWidget {
|
export interface ComponentWidget {
|
||||||
|
/** @deprecated Use callback instead. Kept for backward compatibility with other widgets. */
|
||||||
serializeValue?: () => Promise<LoraPoolConfig | RandomizerConfig | CyclerConfig>
|
serializeValue?: () => Promise<LoraPoolConfig | RandomizerConfig | CyclerConfig>
|
||||||
value?: LoraPoolConfig | LegacyLoraPoolConfig | RandomizerConfig | CyclerConfig
|
value?: LoraPoolConfig | LegacyLoraPoolConfig | RandomizerConfig | CyclerConfig
|
||||||
|
/** @deprecated Use callback instead. Kept for backward compatibility with other widgets. */
|
||||||
onSetValue?: (v: LoraPoolConfig | LegacyLoraPoolConfig | RandomizerConfig | CyclerConfig) => void
|
onSetValue?: (v: LoraPoolConfig | LegacyLoraPoolConfig | RandomizerConfig | CyclerConfig) => void
|
||||||
|
/** @deprecated Directly set widget.value instead. Kept for backward compatibility with other widgets. */
|
||||||
updateConfig?: (v: LoraPoolConfig | RandomizerConfig | CyclerConfig) => void
|
updateConfig?: (v: LoraPoolConfig | RandomizerConfig | CyclerConfig) => void
|
||||||
|
/** Called by ComfyUI automatically after setValue() - use this for UI sync */
|
||||||
|
callback?: (v: LoraPoolConfig | LegacyLoraPoolConfig | RandomizerConfig | CyclerConfig) => void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import { useLoraPoolApi } from './useLoraPoolApi'
|
|||||||
export function useLoraPoolState(widget: ComponentWidget) {
|
export function useLoraPoolState(widget: ComponentWidget) {
|
||||||
const api = useLoraPoolApi()
|
const api = useLoraPoolApi()
|
||||||
|
|
||||||
|
// Flag to prevent infinite loops during config restoration
|
||||||
|
// callback → restoreFromConfig → watch → refreshPreview → buildConfig → widget.value = config → callback → ...
|
||||||
|
let isRestoring = false
|
||||||
|
|
||||||
// Filter state
|
// Filter state
|
||||||
const selectedBaseModels = ref<string[]>([])
|
const selectedBaseModels = ref<string[]>([])
|
||||||
const includeTags = ref<string[]>([])
|
const includeTags = ref<string[]>([])
|
||||||
@@ -57,10 +61,10 @@ export function useLoraPoolState(widget: ComponentWidget) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update widget value
|
// Update widget value (this triggers callback for UI sync)
|
||||||
if (widget.updateConfig) {
|
// Skip during restoration to prevent infinite loops:
|
||||||
widget.updateConfig(config)
|
// callback → restoreFromConfig → watch → refreshPreview → buildConfig → widget.value = config → callback → ...
|
||||||
} else {
|
if (!isRestoring) {
|
||||||
widget.value = config
|
widget.value = config
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
@@ -91,32 +95,40 @@ export function useLoraPoolState(widget: ComponentWidget) {
|
|||||||
|
|
||||||
// Restore state from config
|
// Restore state from config
|
||||||
const restoreFromConfig = (rawConfig: LoraPoolConfig | LegacyLoraPoolConfig) => {
|
const restoreFromConfig = (rawConfig: LoraPoolConfig | LegacyLoraPoolConfig) => {
|
||||||
// Migrate if needed
|
// Set flag to prevent buildConfig from triggering widget.value updates during restoration
|
||||||
const config = rawConfig.version === 1
|
// This breaks the infinite loop: callback → restoreFromConfig → watch → refreshPreview → buildConfig → widget.value = config → callback
|
||||||
? migrateConfig(rawConfig as LegacyLoraPoolConfig)
|
isRestoring = true
|
||||||
: rawConfig as LoraPoolConfig
|
|
||||||
|
|
||||||
if (!config?.filters) return
|
try {
|
||||||
|
// Migrate if needed
|
||||||
|
const config = rawConfig.version === 1
|
||||||
|
? migrateConfig(rawConfig as LegacyLoraPoolConfig)
|
||||||
|
: rawConfig as LoraPoolConfig
|
||||||
|
|
||||||
const { filters, preview } = config
|
if (!config?.filters) return
|
||||||
|
|
||||||
// Helper to update ref only if value changed
|
const { filters, preview } = config
|
||||||
const updateIfChanged = <T>(refValue: { value: T }, newValue: T) => {
|
|
||||||
if (JSON.stringify(refValue.value) !== JSON.stringify(newValue)) {
|
// Helper to update ref only if value changed
|
||||||
refValue.value = newValue
|
const updateIfChanged = <T>(refValue: { value: T }, newValue: T) => {
|
||||||
|
if (JSON.stringify(refValue.value) !== JSON.stringify(newValue)) {
|
||||||
|
refValue.value = newValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
updateIfChanged(selectedBaseModels, filters.baseModels || [])
|
updateIfChanged(selectedBaseModels, filters.baseModels || [])
|
||||||
updateIfChanged(includeTags, filters.tags?.include || [])
|
updateIfChanged(includeTags, filters.tags?.include || [])
|
||||||
updateIfChanged(excludeTags, filters.tags?.exclude || [])
|
updateIfChanged(excludeTags, filters.tags?.exclude || [])
|
||||||
updateIfChanged(includeFolders, filters.folders?.include || [])
|
updateIfChanged(includeFolders, filters.folders?.include || [])
|
||||||
updateIfChanged(excludeFolders, filters.folders?.exclude || [])
|
updateIfChanged(excludeFolders, filters.folders?.exclude || [])
|
||||||
updateIfChanged(noCreditRequired, filters.license?.noCreditRequired ?? false)
|
updateIfChanged(noCreditRequired, filters.license?.noCreditRequired ?? false)
|
||||||
updateIfChanged(allowSelling, filters.license?.allowSelling ?? false)
|
updateIfChanged(allowSelling, filters.license?.allowSelling ?? false)
|
||||||
|
|
||||||
// matchCount doesn't trigger watchers, so direct assignment is fine
|
// matchCount doesn't trigger watchers, so direct assignment is fine
|
||||||
matchCount.value = preview?.matchCount || 0
|
matchCount.value = preview?.matchCount || 0
|
||||||
|
} finally {
|
||||||
|
isRestoring = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch filter options from API
|
// Fetch filter options from API
|
||||||
|
|||||||
@@ -90,9 +90,8 @@ function createLoraPoolWidget(node) {
|
|||||||
},
|
},
|
||||||
setValue(v: LoraPoolConfig | LegacyLoraPoolConfig) {
|
setValue(v: LoraPoolConfig | LegacyLoraPoolConfig) {
|
||||||
internalValue = v
|
internalValue = v
|
||||||
if (typeof widget.onSetValue === 'function') {
|
// ComfyUI automatically calls widget.callback after setValue
|
||||||
widget.onSetValue(v)
|
// No need for custom onSetValue mechanism
|
||||||
}
|
|
||||||
},
|
},
|
||||||
serialize: true,
|
serialize: true,
|
||||||
// Per dev guide: providing getMinHeight via options allows the system to
|
// Per dev guide: providing getMinHeight via options allows the system to
|
||||||
@@ -103,10 +102,6 @@ function createLoraPoolWidget(node) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
widget.updateConfig = (v: LoraPoolConfig) => {
|
|
||||||
internalValue = v
|
|
||||||
}
|
|
||||||
|
|
||||||
const vueApp = createApp(LoraPoolWidget, {
|
const vueApp = createApp(LoraPoolWidget, {
|
||||||
widget,
|
widget,
|
||||||
node
|
node
|
||||||
|
|||||||
@@ -970,7 +970,7 @@ to { transform: rotate(360deg);
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lora-pool-widget[data-v-7d3f681d] {
|
.lora-pool-widget[data-v-1cc8816c] {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
background: rgba(40, 44, 52, 0.6);
|
background: rgba(40, 44, 52, 0.6);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -1770,7 +1770,7 @@ to {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
var _a;
|
var _a;
|
||||||
import { app } from "../../../scripts/app.js";
|
import { app as app$1 } from "../../../scripts/app.js";
|
||||||
/**
|
/**
|
||||||
* @vue/shared v3.5.26
|
* @vue/shared v3.5.26
|
||||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||||
@@ -3317,7 +3317,7 @@ function onWatcherCleanup(cleanupFn, failSilently = false, owner = activeWatcher
|
|||||||
cleanups.push(cleanupFn);
|
cleanups.push(cleanupFn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function watch$2(source, cb, options = EMPTY_OBJ) {
|
function watch$1(source, cb, options = EMPTY_OBJ) {
|
||||||
const { immediate, deep, once, scheduler, augmentJob, call } = options;
|
const { immediate, deep, once, scheduler, augmentJob, call } = options;
|
||||||
const reactiveGetter = (source2) => {
|
const reactiveGetter = (source2) => {
|
||||||
if (deep) return source2;
|
if (deep) return source2;
|
||||||
@@ -3914,7 +3914,7 @@ const useSSRContext = () => {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function watch$1(source, cb, options) {
|
function watch(source, cb, options) {
|
||||||
return doWatch(source, cb, options);
|
return doWatch(source, cb, options);
|
||||||
}
|
}
|
||||||
function doWatch(source, cb, options = EMPTY_OBJ) {
|
function doWatch(source, cb, options = EMPTY_OBJ) {
|
||||||
@@ -3964,7 +3964,7 @@ function doWatch(source, cb, options = EMPTY_OBJ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const watchHandle = watch$2(source, cb, baseWatchOptions);
|
const watchHandle = watch$1(source, cb, baseWatchOptions);
|
||||||
if (isInSSRComponentSetup) {
|
if (isInSSRComponentSetup) {
|
||||||
if (ssrCleanup) {
|
if (ssrCleanup) {
|
||||||
ssrCleanup.push(watchHandle);
|
ssrCleanup.push(watchHandle);
|
||||||
@@ -5319,12 +5319,12 @@ function createWatcher(raw, ctx, publicThis, key) {
|
|||||||
const handler = ctx[raw];
|
const handler = ctx[raw];
|
||||||
if (isFunction(handler)) {
|
if (isFunction(handler)) {
|
||||||
{
|
{
|
||||||
watch$1(getter, handler);
|
watch(getter, handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isFunction(raw)) {
|
} else if (isFunction(raw)) {
|
||||||
{
|
{
|
||||||
watch$1(getter, raw.bind(publicThis));
|
watch(getter, raw.bind(publicThis));
|
||||||
}
|
}
|
||||||
} else if (isObject(raw)) {
|
} else if (isObject(raw)) {
|
||||||
if (isArray(raw)) {
|
if (isArray(raw)) {
|
||||||
@@ -5332,7 +5332,7 @@ function createWatcher(raw, ctx, publicThis, key) {
|
|||||||
} else {
|
} else {
|
||||||
const handler = isFunction(raw.handler) ? raw.handler.bind(publicThis) : ctx[raw.handler];
|
const handler = isFunction(raw.handler) ? raw.handler.bind(publicThis) : ctx[raw.handler];
|
||||||
if (isFunction(handler)) {
|
if (isFunction(handler)) {
|
||||||
watch$1(getter, handler, raw);
|
watch(getter, handler, raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else ;
|
} else ;
|
||||||
@@ -9649,7 +9649,7 @@ function useStyle(css3) {
|
|||||||
onStyleMounted === null || onStyleMounted === void 0 || onStyleMounted(_name);
|
onStyleMounted === null || onStyleMounted === void 0 || onStyleMounted(_name);
|
||||||
}
|
}
|
||||||
if (isLoaded.value) return;
|
if (isLoaded.value) return;
|
||||||
stop = watch$1(cssRef, function(value) {
|
stop = watch(cssRef, function(value) {
|
||||||
styleRef.value.textContent = value;
|
styleRef.value.textContent = value;
|
||||||
onStyleUpdated === null || onStyleUpdated === void 0 || onStyleUpdated(_name);
|
onStyleUpdated === null || onStyleUpdated === void 0 || onStyleUpdated(_name);
|
||||||
}, {
|
}, {
|
||||||
@@ -10104,7 +10104,7 @@ function setupConfig(app2, PrimeVue2) {
|
|||||||
isThemeChanged.value = true;
|
isThemeChanged.value = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var stopConfigWatcher = watch$1(PrimeVue2.config, function(newValue, oldValue) {
|
var stopConfigWatcher = watch(PrimeVue2.config, function(newValue, oldValue) {
|
||||||
PrimeVueService.emit("config:change", {
|
PrimeVueService.emit("config:change", {
|
||||||
newValue,
|
newValue,
|
||||||
oldValue
|
oldValue
|
||||||
@@ -10113,7 +10113,7 @@ function setupConfig(app2, PrimeVue2) {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true
|
deep: true
|
||||||
});
|
});
|
||||||
var stopRippleWatcher = watch$1(function() {
|
var stopRippleWatcher = watch(function() {
|
||||||
return PrimeVue2.config.ripple;
|
return PrimeVue2.config.ripple;
|
||||||
}, function(newValue, oldValue) {
|
}, function(newValue, oldValue) {
|
||||||
PrimeVueService.emit("config:ripple:change", {
|
PrimeVueService.emit("config:ripple:change", {
|
||||||
@@ -10124,7 +10124,7 @@ function setupConfig(app2, PrimeVue2) {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true
|
deep: true
|
||||||
});
|
});
|
||||||
var stopThemeWatcher = watch$1(function() {
|
var stopThemeWatcher = watch(function() {
|
||||||
return PrimeVue2.config.theme;
|
return PrimeVue2.config.theme;
|
||||||
}, function(newValue, oldValue) {
|
}, function(newValue, oldValue) {
|
||||||
if (!isThemeChanged.value) {
|
if (!isThemeChanged.value) {
|
||||||
@@ -10142,7 +10142,7 @@ function setupConfig(app2, PrimeVue2) {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
deep: false
|
deep: false
|
||||||
});
|
});
|
||||||
var stopUnstyledWatcher = watch$1(function() {
|
var stopUnstyledWatcher = watch(function() {
|
||||||
return PrimeVue2.config.unstyled;
|
return PrimeVue2.config.unstyled;
|
||||||
}, function(newValue, oldValue) {
|
}, function(newValue, oldValue) {
|
||||||
if (!newValue && PrimeVue2.config.theme) {
|
if (!newValue && PrimeVue2.config.theme) {
|
||||||
@@ -10730,7 +10730,7 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
document.removeEventListener("keydown", handleKeydown);
|
document.removeEventListener("keydown", handleKeydown);
|
||||||
});
|
});
|
||||||
watch$1(() => props.visible, (isVisible) => {
|
watch(() => props.visible, (isVisible) => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
document.body.style.overflow = "hidden";
|
document.body.style.overflow = "hidden";
|
||||||
} else {
|
} else {
|
||||||
@@ -10830,7 +10830,7 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|||||||
searchQuery.value = "";
|
searchQuery.value = "";
|
||||||
(_a2 = searchInputRef.value) == null ? void 0 : _a2.focus();
|
(_a2 = searchInputRef.value) == null ? void 0 : _a2.focus();
|
||||||
};
|
};
|
||||||
watch$1(() => props.visible, (isVisible) => {
|
watch(() => props.visible, (isVisible) => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
var _a2;
|
var _a2;
|
||||||
@@ -10957,7 +10957,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|||||||
searchQuery.value = "";
|
searchQuery.value = "";
|
||||||
(_a2 = searchInputRef.value) == null ? void 0 : _a2.focus();
|
(_a2 = searchInputRef.value) == null ? void 0 : _a2.focus();
|
||||||
};
|
};
|
||||||
watch$1(() => props.visible, (isVisible) => {
|
watch(() => props.visible, (isVisible) => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
var _a2;
|
var _a2;
|
||||||
@@ -11192,7 +11192,7 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
|||||||
const newSelected = props.selected.includes(key) ? props.selected.filter((k2) => k2 !== key) : [...props.selected, key];
|
const newSelected = props.selected.includes(key) ? props.selected.filter((k2) => k2 !== key) : [...props.selected, key];
|
||||||
emit2("update:selected", newSelected);
|
emit2("update:selected", newSelected);
|
||||||
};
|
};
|
||||||
watch$1(() => props.visible, (isVisible) => {
|
watch(() => props.visible, (isVisible) => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
searchQuery.value = "";
|
searchQuery.value = "";
|
||||||
expandedKeys.value = /* @__PURE__ */ new Set();
|
expandedKeys.value = /* @__PURE__ */ new Set();
|
||||||
@@ -11336,6 +11336,7 @@ function useLoraPoolApi() {
|
|||||||
}
|
}
|
||||||
function useLoraPoolState(widget) {
|
function useLoraPoolState(widget) {
|
||||||
const api = useLoraPoolApi();
|
const api = useLoraPoolApi();
|
||||||
|
let isRestoring = false;
|
||||||
const selectedBaseModels = ref([]);
|
const selectedBaseModels = ref([]);
|
||||||
const includeTags = ref([]);
|
const includeTags = ref([]);
|
||||||
const excludeTags = ref([]);
|
const excludeTags = ref([]);
|
||||||
@@ -11372,9 +11373,7 @@ function useLoraPoolState(widget) {
|
|||||||
lastUpdated: Date.now()
|
lastUpdated: Date.now()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (widget.updateConfig) {
|
if (!isRestoring) {
|
||||||
widget.updateConfig(config);
|
|
||||||
} else {
|
|
||||||
widget.value = config;
|
widget.value = config;
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
@@ -11403,22 +11402,27 @@ function useLoraPoolState(widget) {
|
|||||||
};
|
};
|
||||||
const restoreFromConfig = (rawConfig) => {
|
const restoreFromConfig = (rawConfig) => {
|
||||||
var _a2, _b, _c, _d, _e2, _f;
|
var _a2, _b, _c, _d, _e2, _f;
|
||||||
const config = rawConfig.version === 1 ? migrateConfig(rawConfig) : rawConfig;
|
isRestoring = true;
|
||||||
if (!(config == null ? void 0 : config.filters)) return;
|
try {
|
||||||
const { filters, preview } = config;
|
const config = rawConfig.version === 1 ? migrateConfig(rawConfig) : rawConfig;
|
||||||
const updateIfChanged = (refValue, newValue) => {
|
if (!(config == null ? void 0 : config.filters)) return;
|
||||||
if (JSON.stringify(refValue.value) !== JSON.stringify(newValue)) {
|
const { filters, preview } = config;
|
||||||
refValue.value = newValue;
|
const updateIfChanged = (refValue, newValue) => {
|
||||||
}
|
if (JSON.stringify(refValue.value) !== JSON.stringify(newValue)) {
|
||||||
};
|
refValue.value = newValue;
|
||||||
updateIfChanged(selectedBaseModels, filters.baseModels || []);
|
}
|
||||||
updateIfChanged(includeTags, ((_a2 = filters.tags) == null ? void 0 : _a2.include) || []);
|
};
|
||||||
updateIfChanged(excludeTags, ((_b = filters.tags) == null ? void 0 : _b.exclude) || []);
|
updateIfChanged(selectedBaseModels, filters.baseModels || []);
|
||||||
updateIfChanged(includeFolders, ((_c = filters.folders) == null ? void 0 : _c.include) || []);
|
updateIfChanged(includeTags, ((_a2 = filters.tags) == null ? void 0 : _a2.include) || []);
|
||||||
updateIfChanged(excludeFolders, ((_d = filters.folders) == null ? void 0 : _d.exclude) || []);
|
updateIfChanged(excludeTags, ((_b = filters.tags) == null ? void 0 : _b.exclude) || []);
|
||||||
updateIfChanged(noCreditRequired, ((_e2 = filters.license) == null ? void 0 : _e2.noCreditRequired) ?? false);
|
updateIfChanged(includeFolders, ((_c = filters.folders) == null ? void 0 : _c.include) || []);
|
||||||
updateIfChanged(allowSelling, ((_f = filters.license) == null ? void 0 : _f.allowSelling) ?? false);
|
updateIfChanged(excludeFolders, ((_d = filters.folders) == null ? void 0 : _d.exclude) || []);
|
||||||
matchCount.value = (preview == null ? void 0 : preview.matchCount) || 0;
|
updateIfChanged(noCreditRequired, ((_e2 = filters.license) == null ? void 0 : _e2.noCreditRequired) ?? false);
|
||||||
|
updateIfChanged(allowSelling, ((_f = filters.license) == null ? void 0 : _f.allowSelling) ?? false);
|
||||||
|
matchCount.value = (preview == null ? void 0 : preview.matchCount) || 0;
|
||||||
|
} finally {
|
||||||
|
isRestoring = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const fetchFilterOptions = async () => {
|
const fetchFilterOptions = async () => {
|
||||||
const [baseModels, tags, folders] = await Promise.all([
|
const [baseModels, tags, folders] = await Promise.all([
|
||||||
@@ -11452,7 +11456,7 @@ function useLoraPoolState(widget) {
|
|||||||
refreshPreview();
|
refreshPreview();
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
watch$1([
|
watch([
|
||||||
selectedBaseModels,
|
selectedBaseModels,
|
||||||
includeTags,
|
includeTags,
|
||||||
excludeTags,
|
excludeTags,
|
||||||
@@ -11520,17 +11524,14 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|||||||
modalState.openModal(modal);
|
modalState.openModal(modal);
|
||||||
};
|
};
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
props.widget.serializeValue = async () => {
|
props.widget.callback = (v2) => {
|
||||||
const config = state.buildConfig();
|
if (v2) {
|
||||||
console.log("[LoraPoolWidget] Serializing config:", config);
|
console.log("[LoraPoolWidget] Restoring config from callback");
|
||||||
return config;
|
state.restoreFromConfig(v2);
|
||||||
};
|
}
|
||||||
props.widget.onSetValue = (v2) => {
|
|
||||||
state.restoreFromConfig(v2);
|
|
||||||
state.refreshPreview();
|
|
||||||
};
|
};
|
||||||
if (props.widget.value) {
|
if (props.widget.value) {
|
||||||
console.log("[LoraPoolWidget] Restoring from saved value:", props.widget.value);
|
console.log("[LoraPoolWidget] Restoring from initial value");
|
||||||
state.restoreFromConfig(props.widget.value);
|
state.restoreFromConfig(props.widget.value);
|
||||||
}
|
}
|
||||||
await state.fetchFilterOptions();
|
await state.fetchFilterOptions();
|
||||||
@@ -11600,7 +11601,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const LoraPoolWidget = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-7d3f681d"]]);
|
const LoraPoolWidget = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-1cc8816c"]]);
|
||||||
const _hoisted_1$8 = { class: "last-used-preview" };
|
const _hoisted_1$8 = { class: "last-used-preview" };
|
||||||
const _hoisted_2$5 = { class: "last-used-preview__content" };
|
const _hoisted_2$5 = { class: "last-used-preview__content" };
|
||||||
const _hoisted_3$3 = ["src", "onError"];
|
const _hoisted_3$3 = ["src", "onError"];
|
||||||
@@ -12473,7 +12474,7 @@ function useLoraRandomizerState(widget) {
|
|||||||
};
|
};
|
||||||
const isClipStrengthDisabled = computed(() => !useCustomClipRange.value);
|
const isClipStrengthDisabled = computed(() => !useCustomClipRange.value);
|
||||||
const isRecommendedStrengthEnabled = computed(() => useRecommendedStrength.value);
|
const isRecommendedStrengthEnabled = computed(() => useRecommendedStrength.value);
|
||||||
watch$1([
|
watch([
|
||||||
countMode,
|
countMode,
|
||||||
countFixed,
|
countFixed,
|
||||||
countMin,
|
countMin,
|
||||||
@@ -12598,7 +12599,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
state.rollMode.value = "fixed";
|
state.rollMode.value = "fixed";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
watch$1(() => {
|
watch(() => {
|
||||||
var _a2, _b;
|
var _a2, _b;
|
||||||
return (_b = (_a2 = props.node.widgets) == null ? void 0 : _a2.find((w2) => w2.name === "loras")) == null ? void 0 : _b.value;
|
return (_b = (_a2 = props.node.widgets) == null ? void 0 : _a2.find((w2) => w2.name === "loras")) == null ? void 0 : _b.value;
|
||||||
}, (newVal) => {
|
}, (newVal) => {
|
||||||
@@ -13000,12 +13001,12 @@ function useLoraCyclerState(widget) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const isClipStrengthDisabled = computed(() => !useCustomClipRange.value);
|
const isClipStrengthDisabled = computed(() => !useCustomClipRange.value);
|
||||||
watch$1(modelStrength, (newValue) => {
|
watch(modelStrength, (newValue) => {
|
||||||
if (!useCustomClipRange.value) {
|
if (!useCustomClipRange.value) {
|
||||||
clipStrength.value = newValue;
|
clipStrength.value = newValue;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
watch$1([
|
watch([
|
||||||
currentIndex,
|
currentIndex,
|
||||||
totalCount,
|
totalCount,
|
||||||
poolConfigHash,
|
poolConfigHash,
|
||||||
@@ -13499,7 +13500,7 @@ function createModeChangeCallback(node, updateDownstreamLoaders2, nodeSpecificCa
|
|||||||
updateDownstreamLoaders2(node);
|
updateDownstreamLoaders2(node);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const app$1 = {};
|
const app = {};
|
||||||
const ROOT_GRAPH_ID = "root";
|
const ROOT_GRAPH_ID = "root";
|
||||||
const LORA_PROVIDER_NODE_TYPES = [
|
const LORA_PROVIDER_NODE_TYPES = [
|
||||||
"Lora Stacker (LoraManager)",
|
"Lora Stacker (LoraManager)",
|
||||||
@@ -13519,7 +13520,7 @@ function getNodeGraphId(node) {
|
|||||||
if (!node) {
|
if (!node) {
|
||||||
return ROOT_GRAPH_ID;
|
return ROOT_GRAPH_ID;
|
||||||
}
|
}
|
||||||
return getGraphId(node.graph || app$1.graph);
|
return getGraphId(node.graph || app.graph);
|
||||||
}
|
}
|
||||||
function getNodeReference(node) {
|
function getNodeReference(node) {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
@@ -13720,7 +13721,7 @@ function forwardMiddleMouseToCanvas(container) {
|
|||||||
if (!container) return;
|
if (!container) return;
|
||||||
container.addEventListener("pointerdown", (event) => {
|
container.addEventListener("pointerdown", (event) => {
|
||||||
if (event.button === 1) {
|
if (event.button === 1) {
|
||||||
const canvas = app.canvas;
|
const canvas = app$1.canvas;
|
||||||
if (canvas && typeof canvas.processMouseDown === "function") {
|
if (canvas && typeof canvas.processMouseDown === "function") {
|
||||||
canvas.processMouseDown(event);
|
canvas.processMouseDown(event);
|
||||||
}
|
}
|
||||||
@@ -13728,7 +13729,7 @@ function forwardMiddleMouseToCanvas(container) {
|
|||||||
});
|
});
|
||||||
container.addEventListener("pointermove", (event) => {
|
container.addEventListener("pointermove", (event) => {
|
||||||
if ((event.buttons & 4) === 4) {
|
if ((event.buttons & 4) === 4) {
|
||||||
const canvas = app.canvas;
|
const canvas = app$1.canvas;
|
||||||
if (canvas && typeof canvas.processMouseMove === "function") {
|
if (canvas && typeof canvas.processMouseMove === "function") {
|
||||||
canvas.processMouseMove(event);
|
canvas.processMouseMove(event);
|
||||||
}
|
}
|
||||||
@@ -13736,7 +13737,7 @@ function forwardMiddleMouseToCanvas(container) {
|
|||||||
});
|
});
|
||||||
container.addEventListener("pointerup", (event) => {
|
container.addEventListener("pointerup", (event) => {
|
||||||
if (event.button === 1) {
|
if (event.button === 1) {
|
||||||
const canvas = app.canvas;
|
const canvas = app$1.canvas;
|
||||||
if (canvas && typeof canvas.processMouseUp === "function") {
|
if (canvas && typeof canvas.processMouseUp === "function") {
|
||||||
canvas.processMouseUp(event);
|
canvas.processMouseUp(event);
|
||||||
}
|
}
|
||||||
@@ -13765,9 +13766,6 @@ function createLoraPoolWidget(node) {
|
|||||||
},
|
},
|
||||||
setValue(v2) {
|
setValue(v2) {
|
||||||
internalValue = v2;
|
internalValue = v2;
|
||||||
if (typeof widget.onSetValue === "function") {
|
|
||||||
widget.onSetValue(v2);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
serialize: true,
|
serialize: true,
|
||||||
// Per dev guide: providing getMinHeight via options allows the system to
|
// Per dev guide: providing getMinHeight via options allows the system to
|
||||||
@@ -13777,9 +13775,6 @@ function createLoraPoolWidget(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
widget.updateConfig = (v2) => {
|
|
||||||
internalValue = v2;
|
|
||||||
};
|
|
||||||
const vueApp = createApp(LoraPoolWidget, {
|
const vueApp = createApp(LoraPoolWidget, {
|
||||||
widget,
|
widget,
|
||||||
node
|
node
|
||||||
@@ -13995,11 +13990,11 @@ function createJsonDisplayWidget(node) {
|
|||||||
const widgetInputOptions = /* @__PURE__ */ new Map();
|
const widgetInputOptions = /* @__PURE__ */ new Map();
|
||||||
const initVueDomModeListener = () => {
|
const initVueDomModeListener = () => {
|
||||||
var _a2, _b;
|
var _a2, _b;
|
||||||
if ((_b = (_a2 = app.ui) == null ? void 0 : _a2.settings) == null ? void 0 : _b.addEventListener) {
|
if ((_b = (_a2 = app$1.ui) == null ? void 0 : _a2.settings) == null ? void 0 : _b.addEventListener) {
|
||||||
app.ui.settings.addEventListener("Comfy.VueNodes.Enabled.change", () => {
|
app$1.ui.settings.addEventListener("Comfy.VueNodes.Enabled.change", () => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
var _a3, _b2, _c;
|
var _a3, _b2, _c;
|
||||||
const isVueDomMode = ((_c = (_b2 = (_a3 = app.ui) == null ? void 0 : _a3.settings) == null ? void 0 : _b2.getSettingValue) == null ? void 0 : _c.call(_b2, "Comfy.VueNodes.Enabled")) ?? false;
|
const isVueDomMode = ((_c = (_b2 = (_a3 = app$1.ui) == null ? void 0 : _a3.settings) == null ? void 0 : _b2.getSettingValue) == null ? void 0 : _c.call(_b2, "Comfy.VueNodes.Enabled")) ?? false;
|
||||||
document.dispatchEvent(new CustomEvent("lora-manager:vue-mode-change", {
|
document.dispatchEvent(new CustomEvent("lora-manager:vue-mode-change", {
|
||||||
detail: { isVueDomMode }
|
detail: { isVueDomMode }
|
||||||
}));
|
}));
|
||||||
@@ -14007,12 +14002,12 @@ const initVueDomModeListener = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if ((_a = app.ui) == null ? void 0 : _a.settings) {
|
if ((_a = app$1.ui) == null ? void 0 : _a.settings) {
|
||||||
initVueDomModeListener();
|
initVueDomModeListener();
|
||||||
} else {
|
} else {
|
||||||
const checkAppReady = setInterval(() => {
|
const checkAppReady = setInterval(() => {
|
||||||
var _a2;
|
var _a2;
|
||||||
if ((_a2 = app.ui) == null ? void 0 : _a2.settings) {
|
if ((_a2 = app$1.ui) == null ? void 0 : _a2.settings) {
|
||||||
initVueDomModeListener();
|
initVueDomModeListener();
|
||||||
clearInterval(checkAppReady);
|
clearInterval(checkAppReady);
|
||||||
}
|
}
|
||||||
@@ -14053,7 +14048,7 @@ function createAutocompleteTextWidgetFactory(node, widgetName, modelType, inputO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const spellcheck = ((_c = (_b = (_a2 = app.ui) == null ? void 0 : _a2.settings) == null ? void 0 : _b.getSettingValue) == null ? void 0 : _c.call(_b, "Comfy.TextareaWidget.Spellcheck")) ?? false;
|
const spellcheck = ((_c = (_b = (_a2 = app$1.ui) == null ? void 0 : _a2.settings) == null ? void 0 : _b.getSettingValue) == null ? void 0 : _c.call(_b, "Comfy.TextareaWidget.Spellcheck")) ?? false;
|
||||||
const vueApp = createApp(AutocompleteTextWidget, {
|
const vueApp = createApp(AutocompleteTextWidget, {
|
||||||
widget,
|
widget,
|
||||||
node,
|
node,
|
||||||
@@ -14078,7 +14073,7 @@ function createAutocompleteTextWidgetFactory(node, widgetName, modelType, inputO
|
|||||||
};
|
};
|
||||||
return { widget };
|
return { widget };
|
||||||
}
|
}
|
||||||
app.registerExtension({
|
app$1.registerExtension({
|
||||||
name: "LoraManager.VueWidgets",
|
name: "LoraManager.VueWidgets",
|
||||||
getCustomWidgets() {
|
getCustomWidgets() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user