refactor(vue-widgets): adopt DOM widget value persistence best practices for randomizer and cycler

- Replace custom onSetValue with ComfyUI's built-in widget.callback
- Remove widget.updateConfig, set widget.value directly
- Add isRestoring flag to break callback → watch → widget.value loop
- Update ComponentWidget types with generic parameter for type-safe callbacks

Refs: docs/dom-widgets/value-persistence-best-practices.md
This commit is contained in:
Will Miao
2026-01-28 00:21:30 +08:00
parent a02462fff4
commit 18d3ecb4da
7 changed files with 274 additions and 237 deletions

View File

@@ -25,9 +25,11 @@ import LoraCyclerSettingsView from './lora-cycler/LoraCyclerSettingsView.vue'
import { useLoraCyclerState } from '../composables/useLoraCyclerState'
import type { ComponentWidget, CyclerConfig, LoraPoolConfig } from '../composables/types'
type CyclerWidget = ComponentWidget<CyclerConfig>
// Props
const props = defineProps<{
widget: ComponentWidget
widget: CyclerWidget
node: { id: number; inputs?: any[]; widgets?: any[]; graph?: any }
}>()
@@ -112,19 +114,17 @@ const checkPoolConfigChanges = async () => {
// Lifecycle
onMounted(async () => {
// Setup serialization
props.widget.serializeValue = async () => {
return state.buildConfig()
// Setup callback for external value updates (e.g., workflow load, undo/redo)
// ComfyUI calls this automatically after setValue() in domWidget.ts
props.widget.callback = (v: CyclerConfig) => {
if (v) {
state.restoreFromConfig(v)
}
}
// Handle external value updates (e.g., loading workflow, paste)
props.widget.onSetValue = (v) => {
state.restoreFromConfig(v as CyclerConfig)
}
// Restore from saved value
// Restore from saved value if workflow was already loaded
if (props.widget.value) {
state.restoreFromConfig(props.widget.value as CyclerConfig)
state.restoreFromConfig(props.widget.value)
}
// Add beforeQueued hook to handle index shifting for batch queue synchronization
@@ -141,12 +141,7 @@ onMounted(async () => {
}
// Update the widget value so the indices are included in the serialized config
const config = state.buildConfig()
if ((props.widget as any).updateConfig) {
;(props.widget as any).updateConfig(config)
} else {
props.widget.value = config
}
props.widget.value = state.buildConfig()
}
// Mark component as mounted

View File

@@ -45,9 +45,11 @@ import LoraRandomizerSettingsView from './lora-randomizer/LoraRandomizerSettings
import { useLoraRandomizerState } from '../composables/useLoraRandomizerState'
import type { ComponentWidget, RandomizerConfig, LoraEntry } from '../composables/types'
type RandomizerWidget = ComponentWidget<RandomizerConfig>
// Props
const props = defineProps<{
widget: ComponentWidget
widget: RandomizerWidget
node: { id: number; inputs?: any[]; widgets?: any[]; graph?: any }
}>()
@@ -177,20 +179,17 @@ onMounted(async () => {
// Mark component as mounted so watch can now respond to changes
isMounted.value = true
// Setup serialization
props.widget.serializeValue = async () => {
const config = state.buildConfig()
return config
// Setup callback for external value updates (e.g., workflow load, undo/redo)
// ComfyUI calls this automatically after setValue() in domWidget.ts
props.widget.callback = (v: RandomizerConfig) => {
if (v) {
state.restoreFromConfig(v)
}
}
// Handle external value updates (e.g., loading workflow, paste)
props.widget.onSetValue = (v) => {
state.restoreFromConfig(v as RandomizerConfig)
}
// Restore from saved value
// Restore from saved value if workflow was already loaded
if (props.widget.value) {
state.restoreFromConfig(props.widget.value as RandomizerConfig)
state.restoreFromConfig(props.widget.value)
}
// Add beforeQueued hook to handle seed shifting for batch queue synchronization
@@ -209,12 +208,7 @@ onMounted(async () => {
}
// Update the widget value so the seeds are included in the serialized config
const config = state.buildConfig()
if ((props.widget as any).updateConfig) {
;(props.widget as any).updateConfig(config)
} else {
props.widget.value = config
}
props.widget.value = state.buildConfig()
}
}

View File

@@ -6,7 +6,11 @@ export interface CyclerLoraItem {
model_name: string
}
export function useLoraCyclerState(widget: ComponentWidget) {
export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
// Flag to prevent infinite loops during config restoration
// callback → restoreFromConfig → watch → widget.value = config → callback → ...
let isRestoring = false
// State refs
const currentIndex = ref(1) // 1-based
const totalCount = ref(0)
@@ -26,33 +30,58 @@ export function useLoraCyclerState(widget: ComponentWidget) {
const nextIndex = ref<number | null>(null)
// Build config object from current state
const buildConfig = (): CyclerConfig => ({
current_index: currentIndex.value,
total_count: totalCount.value,
pool_config_hash: poolConfigHash.value,
model_strength: modelStrength.value,
clip_strength: clipStrength.value,
use_same_clip_strength: !useCustomClipRange.value,
sort_by: sortBy.value,
current_lora_name: currentLoraName.value,
current_lora_filename: currentLoraFilename.value,
execution_index: executionIndex.value,
next_index: nextIndex.value,
})
const buildConfig = (): CyclerConfig => {
// Skip updating widget.value during restoration to prevent infinite loops
if (isRestoring) {
return {
current_index: currentIndex.value,
total_count: totalCount.value,
pool_config_hash: poolConfigHash.value,
model_strength: modelStrength.value,
clip_strength: clipStrength.value,
use_same_clip_strength: !useCustomClipRange.value,
sort_by: sortBy.value,
current_lora_name: currentLoraName.value,
current_lora_filename: currentLoraFilename.value,
execution_index: executionIndex.value,
next_index: nextIndex.value,
}
}
return {
current_index: currentIndex.value,
total_count: totalCount.value,
pool_config_hash: poolConfigHash.value,
model_strength: modelStrength.value,
clip_strength: clipStrength.value,
use_same_clip_strength: !useCustomClipRange.value,
sort_by: sortBy.value,
current_lora_name: currentLoraName.value,
current_lora_filename: currentLoraFilename.value,
execution_index: executionIndex.value,
next_index: nextIndex.value,
}
}
// Restore state from config object
const restoreFromConfig = (config: CyclerConfig) => {
currentIndex.value = config.current_index || 1
totalCount.value = config.total_count || 0
poolConfigHash.value = config.pool_config_hash || ''
modelStrength.value = config.model_strength ?? 1.0
clipStrength.value = config.clip_strength ?? 1.0
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
sortBy.value = config.sort_by || 'filename'
currentLoraName.value = config.current_lora_name || ''
currentLoraFilename.value = config.current_lora_filename || ''
// Note: execution_index and next_index are not restored from config
// as they are transient values used only during batch execution
// Set flag to prevent buildConfig from triggering widget.value updates during restoration
isRestoring = true
try {
currentIndex.value = config.current_index || 1
totalCount.value = config.total_count || 0
poolConfigHash.value = config.pool_config_hash || ''
modelStrength.value = config.model_strength ?? 1.0
clipStrength.value = config.clip_strength ?? 1.0
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
sortBy.value = config.sort_by || 'filename'
currentLoraName.value = config.current_lora_name || ''
currentLoraFilename.value = config.current_lora_filename || ''
// Note: execution_index and next_index are not restored from config
// as they are transient values used only during batch execution
} finally {
isRestoring = false
}
}
// Shift indices for batch queue synchronization
@@ -208,12 +237,7 @@ export function useLoraCyclerState(widget: ComponentWidget) {
currentLoraName,
currentLoraFilename,
], () => {
const config = buildConfig()
if (widget.updateConfig) {
widget.updateConfig(config)
} else {
widget.value = config
}
widget.value = buildConfig()
}, { deep: true })
return {

View File

@@ -1,7 +1,11 @@
import { ref, computed, watch } from 'vue'
import type { ComponentWidget, RandomizerConfig, LoraEntry } from './types'
export function useLoraRandomizerState(widget: ComponentWidget) {
export function useLoraRandomizerState(widget: ComponentWidget<RandomizerConfig>) {
// Flag to prevent infinite loops during config restoration
// callback → restoreFromConfig → watch → widget.value = config → callback → ...
let isRestoring = false
// State refs
const countMode = ref<'fixed' | 'range'>('range')
const countFixed = ref(3)
@@ -28,7 +32,29 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
const nextSeed = ref<number | null>(null)
// Build config object from current state
const buildConfig = (): RandomizerConfig => ({
const buildConfig = (): RandomizerConfig => {
// Skip updating widget.value during restoration to prevent infinite loops
if (isRestoring) {
return {
count_mode: countMode.value,
count_fixed: countFixed.value,
count_min: countMin.value,
count_max: countMax.value,
model_strength_min: modelStrengthMin.value,
model_strength_max: modelStrengthMax.value,
use_same_clip_strength: !useCustomClipRange.value,
clip_strength_min: clipStrengthMin.value,
clip_strength_max: clipStrengthMax.value,
roll_mode: rollMode.value,
last_used: lastUsed.value,
use_recommended_strength: useRecommendedStrength.value,
recommended_strength_scale_min: recommendedStrengthScaleMin.value,
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
execution_seed: executionSeed.value,
next_seed: nextSeed.value,
}
}
return {
count_mode: countMode.value,
count_fixed: countFixed.value,
count_min: countMin.value,
@@ -45,7 +71,8 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
execution_seed: executionSeed.value,
next_seed: nextSeed.value,
})
}
}
// Shift seeds for batch queue synchronization
// Previous next_seed becomes current execution_seed, and generate a new next_seed
@@ -63,30 +90,37 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
// Restore state from config object
const restoreFromConfig = (config: RandomizerConfig) => {
countMode.value = config.count_mode || 'range'
countFixed.value = config.count_fixed || 3
countMin.value = config.count_min || 2
countMax.value = config.count_max || 5
modelStrengthMin.value = config.model_strength_min ?? 0.0
modelStrengthMax.value = config.model_strength_max ?? 1.0
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
clipStrengthMin.value = config.clip_strength_min ?? 0.0
clipStrengthMax.value = config.clip_strength_max ?? 1.0
// Migrate old roll_mode values to new ones
const rawRollMode = (config as any).roll_mode as string
if (rawRollMode === 'frontend') {
rollMode.value = 'fixed'
} else if (rawRollMode === 'backend') {
rollMode.value = 'always'
} else if (rawRollMode === 'fixed' || rawRollMode === 'always') {
rollMode.value = rawRollMode as 'fixed' | 'always'
} else {
rollMode.value = 'fixed'
// Set flag to prevent buildConfig from triggering widget.value updates during restoration
isRestoring = true
try {
countMode.value = config.count_mode || 'range'
countFixed.value = config.count_fixed || 3
countMin.value = config.count_min || 2
countMax.value = config.count_max || 5
modelStrengthMin.value = config.model_strength_min ?? 0.0
modelStrengthMax.value = config.model_strength_max ?? 1.0
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
clipStrengthMin.value = config.clip_strength_min ?? 0.0
clipStrengthMax.value = config.clip_strength_max ?? 1.0
// Migrate old roll_mode values to new ones
const rawRollMode = (config as any).roll_mode as string
if (rawRollMode === 'frontend') {
rollMode.value = 'fixed'
} else if (rawRollMode === 'backend') {
rollMode.value = 'always'
} else if (rawRollMode === 'fixed' || rawRollMode === 'always') {
rollMode.value = rawRollMode as 'fixed' | 'always'
} else {
rollMode.value = 'fixed'
}
lastUsed.value = config.last_used || null
useRecommendedStrength.value = config.use_recommended_strength ?? false
recommendedStrengthScaleMin.value = config.recommended_strength_scale_min ?? 0.5
recommendedStrengthScaleMax.value = config.recommended_strength_scale_max ?? 1.0
} finally {
isRestoring = false
}
lastUsed.value = config.last_used || null
useRecommendedStrength.value = config.use_recommended_strength ?? false
recommendedStrengthScaleMin.value = config.recommended_strength_scale_min ?? 0.5
recommendedStrengthScaleMax.value = config.recommended_strength_scale_max ?? 1.0
}
// Roll loras - call API to get random selection
@@ -182,12 +216,7 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
recommendedStrengthScaleMin,
recommendedStrengthScaleMax,
], () => {
const config = buildConfig()
if (widget.updateConfig) {
widget.updateConfig(config)
} else {
widget.value = config
}
widget.value = buildConfig()
}, { deep: true })
return {

View File

@@ -157,10 +157,8 @@ function createLoraRandomizerWidget(node) {
},
setValue(v: RandomizerConfig) {
internalValue = v
console.log('randomizer widget value update: ', internalValue)
if (typeof widget.onSetValue === 'function') {
widget.onSetValue(v)
}
// ComfyUI automatically calls widget.callback after setValue
// No need for custom onSetValue mechanism
},
serialize: true,
getMinHeight() {
@@ -169,10 +167,6 @@ function createLoraRandomizerWidget(node) {
}
)
widget.updateConfig = (v: RandomizerConfig) => {
internalValue = v
}
// Add method to get pool config from connected node
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node)
@@ -242,9 +236,8 @@ function createLoraCyclerWidget(node) {
setValue(v: CyclerConfig) {
const oldFilename = internalValue?.current_lora_filename
internalValue = v
if (typeof widget.onSetValue === 'function') {
widget.onSetValue(v)
}
// ComfyUI automatically calls widget.callback after setValue
// No need for custom onSetValue mechanism
// Update downstream loaders when the active LoRA filename changes
if (oldFilename !== v?.current_lora_filename) {
updateDownstreamLoaders(node)
@@ -257,15 +250,6 @@ function createLoraCyclerWidget(node) {
}
)
widget.updateConfig = (v: CyclerConfig) => {
const oldFilename = internalValue?.current_lora_filename
internalValue = v
// Update downstream loaders when the active LoRA filename changes
if (oldFilename !== v?.current_lora_filename) {
updateDownstreamLoaders(node)
}
}
// Add method to get pool config from connected node
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node)

View File

@@ -1453,7 +1453,7 @@ to { transform: rotate(360deg);
transform: translateY(4px);
}
.lora-randomizer-widget[data-v-45df1002] {
.lora-randomizer-widget[data-v-8063df56] {
padding: 6px;
background: rgba(40, 44, 52, 0.6);
border-radius: 6px;
@@ -1684,7 +1684,7 @@ to {
opacity: 1;
}
.lora-cycler-widget[data-v-95dec8bd] {
.lora-cycler-widget[data-v-6c9d29f9] {
padding: 6px;
background: rgba(40, 44, 52, 0.6);
border-radius: 6px;
@@ -12327,6 +12327,7 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
});
const LoraRandomizerSettingsView = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-f7a531b6"]]);
function useLoraRandomizerState(widget) {
let isRestoring = false;
const countMode = ref("range");
const countFixed = ref(3);
const countMin = ref(2);
@@ -12344,24 +12345,46 @@ function useLoraRandomizerState(widget) {
const lastUsed = ref(null);
const executionSeed = ref(null);
const nextSeed = ref(null);
const buildConfig = () => ({
count_mode: countMode.value,
count_fixed: countFixed.value,
count_min: countMin.value,
count_max: countMax.value,
model_strength_min: modelStrengthMin.value,
model_strength_max: modelStrengthMax.value,
use_same_clip_strength: !useCustomClipRange.value,
clip_strength_min: clipStrengthMin.value,
clip_strength_max: clipStrengthMax.value,
roll_mode: rollMode.value,
last_used: lastUsed.value,
use_recommended_strength: useRecommendedStrength.value,
recommended_strength_scale_min: recommendedStrengthScaleMin.value,
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
execution_seed: executionSeed.value,
next_seed: nextSeed.value
});
const buildConfig = () => {
if (isRestoring) {
return {
count_mode: countMode.value,
count_fixed: countFixed.value,
count_min: countMin.value,
count_max: countMax.value,
model_strength_min: modelStrengthMin.value,
model_strength_max: modelStrengthMax.value,
use_same_clip_strength: !useCustomClipRange.value,
clip_strength_min: clipStrengthMin.value,
clip_strength_max: clipStrengthMax.value,
roll_mode: rollMode.value,
last_used: lastUsed.value,
use_recommended_strength: useRecommendedStrength.value,
recommended_strength_scale_min: recommendedStrengthScaleMin.value,
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
execution_seed: executionSeed.value,
next_seed: nextSeed.value
};
}
return {
count_mode: countMode.value,
count_fixed: countFixed.value,
count_min: countMin.value,
count_max: countMax.value,
model_strength_min: modelStrengthMin.value,
model_strength_max: modelStrengthMax.value,
use_same_clip_strength: !useCustomClipRange.value,
clip_strength_min: clipStrengthMin.value,
clip_strength_max: clipStrengthMax.value,
roll_mode: rollMode.value,
last_used: lastUsed.value,
use_recommended_strength: useRecommendedStrength.value,
recommended_strength_scale_min: recommendedStrengthScaleMin.value,
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
execution_seed: executionSeed.value,
next_seed: nextSeed.value
};
};
const generateNewSeed = () => {
executionSeed.value = nextSeed.value;
nextSeed.value = Math.floor(Math.random() * 2147483647);
@@ -12372,29 +12395,34 @@ function useLoraRandomizerState(widget) {
}
};
const restoreFromConfig = (config) => {
countMode.value = config.count_mode || "range";
countFixed.value = config.count_fixed || 3;
countMin.value = config.count_min || 2;
countMax.value = config.count_max || 5;
modelStrengthMin.value = config.model_strength_min ?? 0;
modelStrengthMax.value = config.model_strength_max ?? 1;
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
clipStrengthMin.value = config.clip_strength_min ?? 0;
clipStrengthMax.value = config.clip_strength_max ?? 1;
const rawRollMode = config.roll_mode;
if (rawRollMode === "frontend") {
rollMode.value = "fixed";
} else if (rawRollMode === "backend") {
rollMode.value = "always";
} else if (rawRollMode === "fixed" || rawRollMode === "always") {
rollMode.value = rawRollMode;
} else {
rollMode.value = "fixed";
isRestoring = true;
try {
countMode.value = config.count_mode || "range";
countFixed.value = config.count_fixed || 3;
countMin.value = config.count_min || 2;
countMax.value = config.count_max || 5;
modelStrengthMin.value = config.model_strength_min ?? 0;
modelStrengthMax.value = config.model_strength_max ?? 1;
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
clipStrengthMin.value = config.clip_strength_min ?? 0;
clipStrengthMax.value = config.clip_strength_max ?? 1;
const rawRollMode = config.roll_mode;
if (rawRollMode === "frontend") {
rollMode.value = "fixed";
} else if (rawRollMode === "backend") {
rollMode.value = "always";
} else if (rawRollMode === "fixed" || rawRollMode === "always") {
rollMode.value = rawRollMode;
} else {
rollMode.value = "fixed";
}
lastUsed.value = config.last_used || null;
useRecommendedStrength.value = config.use_recommended_strength ?? false;
recommendedStrengthScaleMin.value = config.recommended_strength_scale_min ?? 0.5;
recommendedStrengthScaleMax.value = config.recommended_strength_scale_max ?? 1;
} finally {
isRestoring = false;
}
lastUsed.value = config.last_used || null;
useRecommendedStrength.value = config.use_recommended_strength ?? false;
recommendedStrengthScaleMin.value = config.recommended_strength_scale_min ?? 0.5;
recommendedStrengthScaleMax.value = config.recommended_strength_scale_max ?? 1;
};
const rollLoras = async (poolConfig, lockedLoras) => {
try {
@@ -12466,12 +12494,7 @@ function useLoraRandomizerState(widget) {
recommendedStrengthScaleMin,
recommendedStrengthScaleMax
], () => {
const config = buildConfig();
if (widget.updateConfig) {
widget.updateConfig(config);
} else {
widget.value = config;
}
widget.value = buildConfig();
}, { deep: true });
return {
// State refs
@@ -12596,12 +12619,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
}
}
isMounted.value = true;
props.widget.serializeValue = async () => {
const config = state.buildConfig();
return config;
};
props.widget.onSetValue = (v2) => {
state.restoreFromConfig(v2);
props.widget.callback = (v2) => {
if (v2) {
state.restoreFromConfig(v2);
}
};
if (props.widget.value) {
state.restoreFromConfig(props.widget.value);
@@ -12614,12 +12635,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
state.initializeNextSeed();
props.widget[HAS_EXECUTED] = true;
}
const config = state.buildConfig();
if (props.widget.updateConfig) {
props.widget.updateConfig(config);
} else {
props.widget.value = config;
}
props.widget.value = state.buildConfig();
}
};
const originalOnExecuted = (_b = props.node.onExecuted) == null ? void 0 : _b.bind(props.node);
@@ -12683,7 +12699,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
};
}
});
const LoraRandomizerWidget = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-45df1002"]]);
const LoraRandomizerWidget = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-8063df56"]]);
const _hoisted_1$3 = { class: "cycler-settings" };
const _hoisted_2$2 = { class: "setting-section progress-section" };
const _hoisted_3$1 = { class: "progress-display" };
@@ -12847,6 +12863,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
});
const LoraCyclerSettingsView = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-8690e14a"]]);
function useLoraCyclerState(widget) {
let isRestoring = false;
const currentIndex = ref(1);
const totalCount = ref(0);
const poolConfigHash = ref("");
@@ -12859,29 +12876,51 @@ function useLoraCyclerState(widget) {
const isLoading = ref(false);
const executionIndex = ref(null);
const nextIndex = ref(null);
const buildConfig = () => ({
current_index: currentIndex.value,
total_count: totalCount.value,
pool_config_hash: poolConfigHash.value,
model_strength: modelStrength.value,
clip_strength: clipStrength.value,
use_same_clip_strength: !useCustomClipRange.value,
sort_by: sortBy.value,
current_lora_name: currentLoraName.value,
current_lora_filename: currentLoraFilename.value,
execution_index: executionIndex.value,
next_index: nextIndex.value
});
const buildConfig = () => {
if (isRestoring) {
return {
current_index: currentIndex.value,
total_count: totalCount.value,
pool_config_hash: poolConfigHash.value,
model_strength: modelStrength.value,
clip_strength: clipStrength.value,
use_same_clip_strength: !useCustomClipRange.value,
sort_by: sortBy.value,
current_lora_name: currentLoraName.value,
current_lora_filename: currentLoraFilename.value,
execution_index: executionIndex.value,
next_index: nextIndex.value
};
}
return {
current_index: currentIndex.value,
total_count: totalCount.value,
pool_config_hash: poolConfigHash.value,
model_strength: modelStrength.value,
clip_strength: clipStrength.value,
use_same_clip_strength: !useCustomClipRange.value,
sort_by: sortBy.value,
current_lora_name: currentLoraName.value,
current_lora_filename: currentLoraFilename.value,
execution_index: executionIndex.value,
next_index: nextIndex.value
};
};
const restoreFromConfig = (config) => {
currentIndex.value = config.current_index || 1;
totalCount.value = config.total_count || 0;
poolConfigHash.value = config.pool_config_hash || "";
modelStrength.value = config.model_strength ?? 1;
clipStrength.value = config.clip_strength ?? 1;
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
sortBy.value = config.sort_by || "filename";
currentLoraName.value = config.current_lora_name || "";
currentLoraFilename.value = config.current_lora_filename || "";
isRestoring = true;
try {
currentIndex.value = config.current_index || 1;
totalCount.value = config.total_count || 0;
poolConfigHash.value = config.pool_config_hash || "";
modelStrength.value = config.model_strength ?? 1;
clipStrength.value = config.clip_strength ?? 1;
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
sortBy.value = config.sort_by || "filename";
currentLoraName.value = config.current_lora_name || "";
currentLoraFilename.value = config.current_lora_filename || "";
} finally {
isRestoring = false;
}
};
const generateNextIndex = () => {
executionIndex.value = nextIndex.value;
@@ -12994,12 +13033,7 @@ function useLoraCyclerState(widget) {
currentLoraName,
currentLoraFilename
], () => {
const config = buildConfig();
if (widget.updateConfig) {
widget.updateConfig(config);
} else {
widget.value = config;
}
widget.value = buildConfig();
}, { deep: true });
return {
// State refs
@@ -13093,11 +13127,10 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
};
onMounted(async () => {
var _a2;
props.widget.serializeValue = async () => {
return state.buildConfig();
};
props.widget.onSetValue = (v2) => {
state.restoreFromConfig(v2);
props.widget.callback = (v2) => {
if (v2) {
state.restoreFromConfig(v2);
}
};
if (props.widget.value) {
state.restoreFromConfig(props.widget.value);
@@ -13109,12 +13142,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
state.initializeNextIndex();
props.widget[HAS_EXECUTED] = true;
}
const config = state.buildConfig();
if (props.widget.updateConfig) {
props.widget.updateConfig(config);
} else {
props.widget.value = config;
}
props.widget.value = state.buildConfig();
};
isMounted.value = true;
try {
@@ -13182,7 +13210,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
};
}
});
const LoraCyclerWidget = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-95dec8bd"]]);
const LoraCyclerWidget = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-6c9d29f9"]]);
const _hoisted_1$1 = { class: "json-display-widget" };
const _hoisted_2$1 = {
class: "json-content",
@@ -13796,10 +13824,6 @@ function createLoraRandomizerWidget(node) {
},
setValue(v2) {
internalValue = v2;
console.log("randomizer widget value update: ", internalValue);
if (typeof widget.onSetValue === "function") {
widget.onSetValue(v2);
}
},
serialize: true,
getMinHeight() {
@@ -13807,9 +13831,6 @@ function createLoraRandomizerWidget(node) {
}
}
);
widget.updateConfig = (v2) => {
internalValue = v2;
};
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node);
widget.onRoll = (randomLoras) => {
const lorasWidget = node.widgets.find((w2) => w2.name === "loras");
@@ -13863,9 +13884,6 @@ function createLoraCyclerWidget(node) {
setValue(v2) {
const oldFilename = internalValue == null ? void 0 : internalValue.current_lora_filename;
internalValue = v2;
if (typeof widget.onSetValue === "function") {
widget.onSetValue(v2);
}
if (oldFilename !== (v2 == null ? void 0 : v2.current_lora_filename)) {
updateDownstreamLoaders(node);
}
@@ -13876,13 +13894,6 @@ function createLoraCyclerWidget(node) {
}
}
);
widget.updateConfig = (v2) => {
const oldFilename = internalValue == null ? void 0 : internalValue.current_lora_filename;
internalValue = v2;
if (oldFilename !== (v2 == null ? void 0 : v2.current_lora_filename)) {
updateDownstreamLoaders(node);
}
};
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node);
const vueApp = createApp(LoraCyclerWidget, {
widget,

File diff suppressed because one or more lines are too long