mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
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:
@@ -25,9 +25,11 @@ import LoraCyclerSettingsView from './lora-cycler/LoraCyclerSettingsView.vue'
|
|||||||
import { useLoraCyclerState } from '../composables/useLoraCyclerState'
|
import { useLoraCyclerState } from '../composables/useLoraCyclerState'
|
||||||
import type { ComponentWidget, CyclerConfig, LoraPoolConfig } from '../composables/types'
|
import type { ComponentWidget, CyclerConfig, LoraPoolConfig } from '../composables/types'
|
||||||
|
|
||||||
|
type CyclerWidget = ComponentWidget<CyclerConfig>
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
widget: ComponentWidget
|
widget: CyclerWidget
|
||||||
node: { id: number; inputs?: any[]; widgets?: any[]; graph?: any }
|
node: { id: number; inputs?: any[]; widgets?: any[]; graph?: any }
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@@ -112,19 +114,17 @@ const checkPoolConfigChanges = async () => {
|
|||||||
|
|
||||||
// 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
|
||||||
return state.buildConfig()
|
props.widget.callback = (v: CyclerConfig) => {
|
||||||
|
if (v) {
|
||||||
|
state.restoreFromConfig(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 CyclerConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore from saved value
|
|
||||||
if (props.widget.value) {
|
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
|
// 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
|
// Update the widget value so the indices are included in the serialized config
|
||||||
const config = state.buildConfig()
|
props.widget.value = state.buildConfig()
|
||||||
if ((props.widget as any).updateConfig) {
|
|
||||||
;(props.widget as any).updateConfig(config)
|
|
||||||
} else {
|
|
||||||
props.widget.value = config
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark component as mounted
|
// Mark component as mounted
|
||||||
|
|||||||
@@ -45,9 +45,11 @@ import LoraRandomizerSettingsView from './lora-randomizer/LoraRandomizerSettings
|
|||||||
import { useLoraRandomizerState } from '../composables/useLoraRandomizerState'
|
import { useLoraRandomizerState } from '../composables/useLoraRandomizerState'
|
||||||
import type { ComponentWidget, RandomizerConfig, LoraEntry } from '../composables/types'
|
import type { ComponentWidget, RandomizerConfig, LoraEntry } from '../composables/types'
|
||||||
|
|
||||||
|
type RandomizerWidget = ComponentWidget<RandomizerConfig>
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
widget: ComponentWidget
|
widget: RandomizerWidget
|
||||||
node: { id: number; inputs?: any[]; widgets?: any[]; graph?: any }
|
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
|
// Mark component as mounted so watch can now respond to changes
|
||||||
isMounted.value = true
|
isMounted.value = true
|
||||||
|
|
||||||
// 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()
|
props.widget.callback = (v: RandomizerConfig) => {
|
||||||
return config
|
if (v) {
|
||||||
|
state.restoreFromConfig(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 RandomizerConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore from saved value
|
|
||||||
if (props.widget.value) {
|
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
|
// 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
|
// Update the widget value so the seeds are included in the serialized config
|
||||||
const config = state.buildConfig()
|
props.widget.value = state.buildConfig()
|
||||||
if ((props.widget as any).updateConfig) {
|
|
||||||
;(props.widget as any).updateConfig(config)
|
|
||||||
} else {
|
|
||||||
props.widget.value = config
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ export interface CyclerLoraItem {
|
|||||||
model_name: string
|
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
|
// State refs
|
||||||
const currentIndex = ref(1) // 1-based
|
const currentIndex = ref(1) // 1-based
|
||||||
const totalCount = ref(0)
|
const totalCount = ref(0)
|
||||||
@@ -26,33 +30,58 @@ export function useLoraCyclerState(widget: ComponentWidget) {
|
|||||||
const nextIndex = ref<number | null>(null)
|
const nextIndex = ref<number | null>(null)
|
||||||
|
|
||||||
// Build config object from current state
|
// Build config object from current state
|
||||||
const buildConfig = (): CyclerConfig => ({
|
const buildConfig = (): CyclerConfig => {
|
||||||
current_index: currentIndex.value,
|
// Skip updating widget.value during restoration to prevent infinite loops
|
||||||
total_count: totalCount.value,
|
if (isRestoring) {
|
||||||
pool_config_hash: poolConfigHash.value,
|
return {
|
||||||
model_strength: modelStrength.value,
|
current_index: currentIndex.value,
|
||||||
clip_strength: clipStrength.value,
|
total_count: totalCount.value,
|
||||||
use_same_clip_strength: !useCustomClipRange.value,
|
pool_config_hash: poolConfigHash.value,
|
||||||
sort_by: sortBy.value,
|
model_strength: modelStrength.value,
|
||||||
current_lora_name: currentLoraName.value,
|
clip_strength: clipStrength.value,
|
||||||
current_lora_filename: currentLoraFilename.value,
|
use_same_clip_strength: !useCustomClipRange.value,
|
||||||
execution_index: executionIndex.value,
|
sort_by: sortBy.value,
|
||||||
next_index: nextIndex.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
|
// Restore state from config object
|
||||||
const restoreFromConfig = (config: CyclerConfig) => {
|
const restoreFromConfig = (config: CyclerConfig) => {
|
||||||
currentIndex.value = config.current_index || 1
|
// Set flag to prevent buildConfig from triggering widget.value updates during restoration
|
||||||
totalCount.value = config.total_count || 0
|
isRestoring = true
|
||||||
poolConfigHash.value = config.pool_config_hash || ''
|
|
||||||
modelStrength.value = config.model_strength ?? 1.0
|
try {
|
||||||
clipStrength.value = config.clip_strength ?? 1.0
|
currentIndex.value = config.current_index || 1
|
||||||
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
|
totalCount.value = config.total_count || 0
|
||||||
sortBy.value = config.sort_by || 'filename'
|
poolConfigHash.value = config.pool_config_hash || ''
|
||||||
currentLoraName.value = config.current_lora_name || ''
|
modelStrength.value = config.model_strength ?? 1.0
|
||||||
currentLoraFilename.value = config.current_lora_filename || ''
|
clipStrength.value = config.clip_strength ?? 1.0
|
||||||
// Note: execution_index and next_index are not restored from config
|
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
|
||||||
// as they are transient values used only during batch execution
|
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
|
// Shift indices for batch queue synchronization
|
||||||
@@ -208,12 +237,7 @@ export function useLoraCyclerState(widget: ComponentWidget) {
|
|||||||
currentLoraName,
|
currentLoraName,
|
||||||
currentLoraFilename,
|
currentLoraFilename,
|
||||||
], () => {
|
], () => {
|
||||||
const config = buildConfig()
|
widget.value = buildConfig()
|
||||||
if (widget.updateConfig) {
|
|
||||||
widget.updateConfig(config)
|
|
||||||
} else {
|
|
||||||
widget.value = config
|
|
||||||
}
|
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import type { ComponentWidget, RandomizerConfig, LoraEntry } from './types'
|
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
|
// State refs
|
||||||
const countMode = ref<'fixed' | 'range'>('range')
|
const countMode = ref<'fixed' | 'range'>('range')
|
||||||
const countFixed = ref(3)
|
const countFixed = ref(3)
|
||||||
@@ -28,7 +32,29 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
|
|||||||
const nextSeed = ref<number | null>(null)
|
const nextSeed = ref<number | null>(null)
|
||||||
|
|
||||||
// Build config object from current state
|
// 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_mode: countMode.value,
|
||||||
count_fixed: countFixed.value,
|
count_fixed: countFixed.value,
|
||||||
count_min: countMin.value,
|
count_min: countMin.value,
|
||||||
@@ -45,7 +71,8 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
|
|||||||
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
|
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
|
||||||
execution_seed: executionSeed.value,
|
execution_seed: executionSeed.value,
|
||||||
next_seed: nextSeed.value,
|
next_seed: nextSeed.value,
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Shift seeds for batch queue synchronization
|
// Shift seeds for batch queue synchronization
|
||||||
// Previous next_seed becomes current execution_seed, and generate a new next_seed
|
// 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
|
// Restore state from config object
|
||||||
const restoreFromConfig = (config: RandomizerConfig) => {
|
const restoreFromConfig = (config: RandomizerConfig) => {
|
||||||
countMode.value = config.count_mode || 'range'
|
// Set flag to prevent buildConfig from triggering widget.value updates during restoration
|
||||||
countFixed.value = config.count_fixed || 3
|
isRestoring = true
|
||||||
countMin.value = config.count_min || 2
|
|
||||||
countMax.value = config.count_max || 5
|
try {
|
||||||
modelStrengthMin.value = config.model_strength_min ?? 0.0
|
countMode.value = config.count_mode || 'range'
|
||||||
modelStrengthMax.value = config.model_strength_max ?? 1.0
|
countFixed.value = config.count_fixed || 3
|
||||||
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
|
countMin.value = config.count_min || 2
|
||||||
clipStrengthMin.value = config.clip_strength_min ?? 0.0
|
countMax.value = config.count_max || 5
|
||||||
clipStrengthMax.value = config.clip_strength_max ?? 1.0
|
modelStrengthMin.value = config.model_strength_min ?? 0.0
|
||||||
// Migrate old roll_mode values to new ones
|
modelStrengthMax.value = config.model_strength_max ?? 1.0
|
||||||
const rawRollMode = (config as any).roll_mode as string
|
useCustomClipRange.value = !(config.use_same_clip_strength ?? true)
|
||||||
if (rawRollMode === 'frontend') {
|
clipStrengthMin.value = config.clip_strength_min ?? 0.0
|
||||||
rollMode.value = 'fixed'
|
clipStrengthMax.value = config.clip_strength_max ?? 1.0
|
||||||
} else if (rawRollMode === 'backend') {
|
// Migrate old roll_mode values to new ones
|
||||||
rollMode.value = 'always'
|
const rawRollMode = (config as any).roll_mode as string
|
||||||
} else if (rawRollMode === 'fixed' || rawRollMode === 'always') {
|
if (rawRollMode === 'frontend') {
|
||||||
rollMode.value = rawRollMode as 'fixed' | 'always'
|
rollMode.value = 'fixed'
|
||||||
} else {
|
} else if (rawRollMode === 'backend') {
|
||||||
rollMode.value = 'fixed'
|
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
|
// Roll loras - call API to get random selection
|
||||||
@@ -182,12 +216,7 @@ export function useLoraRandomizerState(widget: ComponentWidget) {
|
|||||||
recommendedStrengthScaleMin,
|
recommendedStrengthScaleMin,
|
||||||
recommendedStrengthScaleMax,
|
recommendedStrengthScaleMax,
|
||||||
], () => {
|
], () => {
|
||||||
const config = buildConfig()
|
widget.value = buildConfig()
|
||||||
if (widget.updateConfig) {
|
|
||||||
widget.updateConfig(config)
|
|
||||||
} else {
|
|
||||||
widget.value = config
|
|
||||||
}
|
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -157,10 +157,8 @@ function createLoraRandomizerWidget(node) {
|
|||||||
},
|
},
|
||||||
setValue(v: RandomizerConfig) {
|
setValue(v: RandomizerConfig) {
|
||||||
internalValue = v
|
internalValue = v
|
||||||
console.log('randomizer widget value update: ', internalValue)
|
// ComfyUI automatically calls widget.callback after setValue
|
||||||
if (typeof widget.onSetValue === 'function') {
|
// No need for custom onSetValue mechanism
|
||||||
widget.onSetValue(v)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
serialize: true,
|
serialize: true,
|
||||||
getMinHeight() {
|
getMinHeight() {
|
||||||
@@ -169,10 +167,6 @@ function createLoraRandomizerWidget(node) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
widget.updateConfig = (v: RandomizerConfig) => {
|
|
||||||
internalValue = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add method to get pool config from connected node
|
// Add method to get pool config from connected node
|
||||||
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node)
|
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node)
|
||||||
|
|
||||||
@@ -242,9 +236,8 @@ function createLoraCyclerWidget(node) {
|
|||||||
setValue(v: CyclerConfig) {
|
setValue(v: CyclerConfig) {
|
||||||
const oldFilename = internalValue?.current_lora_filename
|
const oldFilename = internalValue?.current_lora_filename
|
||||||
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
|
||||||
}
|
|
||||||
// Update downstream loaders when the active LoRA filename changes
|
// Update downstream loaders when the active LoRA filename changes
|
||||||
if (oldFilename !== v?.current_lora_filename) {
|
if (oldFilename !== v?.current_lora_filename) {
|
||||||
updateDownstreamLoaders(node)
|
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
|
// Add method to get pool config from connected node
|
||||||
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node)
|
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node)
|
||||||
|
|
||||||
|
|||||||
@@ -1453,7 +1453,7 @@ to { transform: rotate(360deg);
|
|||||||
transform: translateY(4px);
|
transform: translateY(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.lora-randomizer-widget[data-v-45df1002] {
|
.lora-randomizer-widget[data-v-8063df56] {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
background: rgba(40, 44, 52, 0.6);
|
background: rgba(40, 44, 52, 0.6);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -1684,7 +1684,7 @@ to {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lora-cycler-widget[data-v-95dec8bd] {
|
.lora-cycler-widget[data-v-6c9d29f9] {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
background: rgba(40, 44, 52, 0.6);
|
background: rgba(40, 44, 52, 0.6);
|
||||||
border-radius: 6px;
|
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"]]);
|
const LoraRandomizerSettingsView = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-f7a531b6"]]);
|
||||||
function useLoraRandomizerState(widget) {
|
function useLoraRandomizerState(widget) {
|
||||||
|
let isRestoring = false;
|
||||||
const countMode = ref("range");
|
const countMode = ref("range");
|
||||||
const countFixed = ref(3);
|
const countFixed = ref(3);
|
||||||
const countMin = ref(2);
|
const countMin = ref(2);
|
||||||
@@ -12344,24 +12345,46 @@ function useLoraRandomizerState(widget) {
|
|||||||
const lastUsed = ref(null);
|
const lastUsed = ref(null);
|
||||||
const executionSeed = ref(null);
|
const executionSeed = ref(null);
|
||||||
const nextSeed = ref(null);
|
const nextSeed = ref(null);
|
||||||
const buildConfig = () => ({
|
const buildConfig = () => {
|
||||||
count_mode: countMode.value,
|
if (isRestoring) {
|
||||||
count_fixed: countFixed.value,
|
return {
|
||||||
count_min: countMin.value,
|
count_mode: countMode.value,
|
||||||
count_max: countMax.value,
|
count_fixed: countFixed.value,
|
||||||
model_strength_min: modelStrengthMin.value,
|
count_min: countMin.value,
|
||||||
model_strength_max: modelStrengthMax.value,
|
count_max: countMax.value,
|
||||||
use_same_clip_strength: !useCustomClipRange.value,
|
model_strength_min: modelStrengthMin.value,
|
||||||
clip_strength_min: clipStrengthMin.value,
|
model_strength_max: modelStrengthMax.value,
|
||||||
clip_strength_max: clipStrengthMax.value,
|
use_same_clip_strength: !useCustomClipRange.value,
|
||||||
roll_mode: rollMode.value,
|
clip_strength_min: clipStrengthMin.value,
|
||||||
last_used: lastUsed.value,
|
clip_strength_max: clipStrengthMax.value,
|
||||||
use_recommended_strength: useRecommendedStrength.value,
|
roll_mode: rollMode.value,
|
||||||
recommended_strength_scale_min: recommendedStrengthScaleMin.value,
|
last_used: lastUsed.value,
|
||||||
recommended_strength_scale_max: recommendedStrengthScaleMax.value,
|
use_recommended_strength: useRecommendedStrength.value,
|
||||||
execution_seed: executionSeed.value,
|
recommended_strength_scale_min: recommendedStrengthScaleMin.value,
|
||||||
next_seed: nextSeed.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 = () => {
|
const generateNewSeed = () => {
|
||||||
executionSeed.value = nextSeed.value;
|
executionSeed.value = nextSeed.value;
|
||||||
nextSeed.value = Math.floor(Math.random() * 2147483647);
|
nextSeed.value = Math.floor(Math.random() * 2147483647);
|
||||||
@@ -12372,29 +12395,34 @@ function useLoraRandomizerState(widget) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const restoreFromConfig = (config) => {
|
const restoreFromConfig = (config) => {
|
||||||
countMode.value = config.count_mode || "range";
|
isRestoring = true;
|
||||||
countFixed.value = config.count_fixed || 3;
|
try {
|
||||||
countMin.value = config.count_min || 2;
|
countMode.value = config.count_mode || "range";
|
||||||
countMax.value = config.count_max || 5;
|
countFixed.value = config.count_fixed || 3;
|
||||||
modelStrengthMin.value = config.model_strength_min ?? 0;
|
countMin.value = config.count_min || 2;
|
||||||
modelStrengthMax.value = config.model_strength_max ?? 1;
|
countMax.value = config.count_max || 5;
|
||||||
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
|
modelStrengthMin.value = config.model_strength_min ?? 0;
|
||||||
clipStrengthMin.value = config.clip_strength_min ?? 0;
|
modelStrengthMax.value = config.model_strength_max ?? 1;
|
||||||
clipStrengthMax.value = config.clip_strength_max ?? 1;
|
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
|
||||||
const rawRollMode = config.roll_mode;
|
clipStrengthMin.value = config.clip_strength_min ?? 0;
|
||||||
if (rawRollMode === "frontend") {
|
clipStrengthMax.value = config.clip_strength_max ?? 1;
|
||||||
rollMode.value = "fixed";
|
const rawRollMode = config.roll_mode;
|
||||||
} else if (rawRollMode === "backend") {
|
if (rawRollMode === "frontend") {
|
||||||
rollMode.value = "always";
|
rollMode.value = "fixed";
|
||||||
} else if (rawRollMode === "fixed" || rawRollMode === "always") {
|
} else if (rawRollMode === "backend") {
|
||||||
rollMode.value = rawRollMode;
|
rollMode.value = "always";
|
||||||
} else {
|
} else if (rawRollMode === "fixed" || rawRollMode === "always") {
|
||||||
rollMode.value = "fixed";
|
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) => {
|
const rollLoras = async (poolConfig, lockedLoras) => {
|
||||||
try {
|
try {
|
||||||
@@ -12466,12 +12494,7 @@ function useLoraRandomizerState(widget) {
|
|||||||
recommendedStrengthScaleMin,
|
recommendedStrengthScaleMin,
|
||||||
recommendedStrengthScaleMax
|
recommendedStrengthScaleMax
|
||||||
], () => {
|
], () => {
|
||||||
const config = buildConfig();
|
widget.value = buildConfig();
|
||||||
if (widget.updateConfig) {
|
|
||||||
widget.updateConfig(config);
|
|
||||||
} else {
|
|
||||||
widget.value = config;
|
|
||||||
}
|
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
return {
|
return {
|
||||||
// State refs
|
// State refs
|
||||||
@@ -12596,12 +12619,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
isMounted.value = true;
|
isMounted.value = true;
|
||||||
props.widget.serializeValue = async () => {
|
props.widget.callback = (v2) => {
|
||||||
const config = state.buildConfig();
|
if (v2) {
|
||||||
return config;
|
state.restoreFromConfig(v2);
|
||||||
};
|
}
|
||||||
props.widget.onSetValue = (v2) => {
|
|
||||||
state.restoreFromConfig(v2);
|
|
||||||
};
|
};
|
||||||
if (props.widget.value) {
|
if (props.widget.value) {
|
||||||
state.restoreFromConfig(props.widget.value);
|
state.restoreFromConfig(props.widget.value);
|
||||||
@@ -12614,12 +12635,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
state.initializeNextSeed();
|
state.initializeNextSeed();
|
||||||
props.widget[HAS_EXECUTED] = true;
|
props.widget[HAS_EXECUTED] = true;
|
||||||
}
|
}
|
||||||
const config = state.buildConfig();
|
props.widget.value = state.buildConfig();
|
||||||
if (props.widget.updateConfig) {
|
|
||||||
props.widget.updateConfig(config);
|
|
||||||
} else {
|
|
||||||
props.widget.value = config;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const originalOnExecuted = (_b = props.node.onExecuted) == null ? void 0 : _b.bind(props.node);
|
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_1$3 = { class: "cycler-settings" };
|
||||||
const _hoisted_2$2 = { class: "setting-section progress-section" };
|
const _hoisted_2$2 = { class: "setting-section progress-section" };
|
||||||
const _hoisted_3$1 = { class: "progress-display" };
|
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"]]);
|
const LoraCyclerSettingsView = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-8690e14a"]]);
|
||||||
function useLoraCyclerState(widget) {
|
function useLoraCyclerState(widget) {
|
||||||
|
let isRestoring = false;
|
||||||
const currentIndex = ref(1);
|
const currentIndex = ref(1);
|
||||||
const totalCount = ref(0);
|
const totalCount = ref(0);
|
||||||
const poolConfigHash = ref("");
|
const poolConfigHash = ref("");
|
||||||
@@ -12859,29 +12876,51 @@ function useLoraCyclerState(widget) {
|
|||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const executionIndex = ref(null);
|
const executionIndex = ref(null);
|
||||||
const nextIndex = ref(null);
|
const nextIndex = ref(null);
|
||||||
const buildConfig = () => ({
|
const buildConfig = () => {
|
||||||
current_index: currentIndex.value,
|
if (isRestoring) {
|
||||||
total_count: totalCount.value,
|
return {
|
||||||
pool_config_hash: poolConfigHash.value,
|
current_index: currentIndex.value,
|
||||||
model_strength: modelStrength.value,
|
total_count: totalCount.value,
|
||||||
clip_strength: clipStrength.value,
|
pool_config_hash: poolConfigHash.value,
|
||||||
use_same_clip_strength: !useCustomClipRange.value,
|
model_strength: modelStrength.value,
|
||||||
sort_by: sortBy.value,
|
clip_strength: clipStrength.value,
|
||||||
current_lora_name: currentLoraName.value,
|
use_same_clip_strength: !useCustomClipRange.value,
|
||||||
current_lora_filename: currentLoraFilename.value,
|
sort_by: sortBy.value,
|
||||||
execution_index: executionIndex.value,
|
current_lora_name: currentLoraName.value,
|
||||||
next_index: nextIndex.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) => {
|
const restoreFromConfig = (config) => {
|
||||||
currentIndex.value = config.current_index || 1;
|
isRestoring = true;
|
||||||
totalCount.value = config.total_count || 0;
|
try {
|
||||||
poolConfigHash.value = config.pool_config_hash || "";
|
currentIndex.value = config.current_index || 1;
|
||||||
modelStrength.value = config.model_strength ?? 1;
|
totalCount.value = config.total_count || 0;
|
||||||
clipStrength.value = config.clip_strength ?? 1;
|
poolConfigHash.value = config.pool_config_hash || "";
|
||||||
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
|
modelStrength.value = config.model_strength ?? 1;
|
||||||
sortBy.value = config.sort_by || "filename";
|
clipStrength.value = config.clip_strength ?? 1;
|
||||||
currentLoraName.value = config.current_lora_name || "";
|
useCustomClipRange.value = !(config.use_same_clip_strength ?? true);
|
||||||
currentLoraFilename.value = config.current_lora_filename || "";
|
sortBy.value = config.sort_by || "filename";
|
||||||
|
currentLoraName.value = config.current_lora_name || "";
|
||||||
|
currentLoraFilename.value = config.current_lora_filename || "";
|
||||||
|
} finally {
|
||||||
|
isRestoring = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const generateNextIndex = () => {
|
const generateNextIndex = () => {
|
||||||
executionIndex.value = nextIndex.value;
|
executionIndex.value = nextIndex.value;
|
||||||
@@ -12994,12 +13033,7 @@ function useLoraCyclerState(widget) {
|
|||||||
currentLoraName,
|
currentLoraName,
|
||||||
currentLoraFilename
|
currentLoraFilename
|
||||||
], () => {
|
], () => {
|
||||||
const config = buildConfig();
|
widget.value = buildConfig();
|
||||||
if (widget.updateConfig) {
|
|
||||||
widget.updateConfig(config);
|
|
||||||
} else {
|
|
||||||
widget.value = config;
|
|
||||||
}
|
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
return {
|
return {
|
||||||
// State refs
|
// State refs
|
||||||
@@ -13093,11 +13127,10 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
};
|
};
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
var _a2;
|
var _a2;
|
||||||
props.widget.serializeValue = async () => {
|
props.widget.callback = (v2) => {
|
||||||
return state.buildConfig();
|
if (v2) {
|
||||||
};
|
state.restoreFromConfig(v2);
|
||||||
props.widget.onSetValue = (v2) => {
|
}
|
||||||
state.restoreFromConfig(v2);
|
|
||||||
};
|
};
|
||||||
if (props.widget.value) {
|
if (props.widget.value) {
|
||||||
state.restoreFromConfig(props.widget.value);
|
state.restoreFromConfig(props.widget.value);
|
||||||
@@ -13109,12 +13142,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
state.initializeNextIndex();
|
state.initializeNextIndex();
|
||||||
props.widget[HAS_EXECUTED] = true;
|
props.widget[HAS_EXECUTED] = true;
|
||||||
}
|
}
|
||||||
const config = state.buildConfig();
|
props.widget.value = state.buildConfig();
|
||||||
if (props.widget.updateConfig) {
|
|
||||||
props.widget.updateConfig(config);
|
|
||||||
} else {
|
|
||||||
props.widget.value = config;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
isMounted.value = true;
|
isMounted.value = true;
|
||||||
try {
|
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_1$1 = { class: "json-display-widget" };
|
||||||
const _hoisted_2$1 = {
|
const _hoisted_2$1 = {
|
||||||
class: "json-content",
|
class: "json-content",
|
||||||
@@ -13796,10 +13824,6 @@ function createLoraRandomizerWidget(node) {
|
|||||||
},
|
},
|
||||||
setValue(v2) {
|
setValue(v2) {
|
||||||
internalValue = v2;
|
internalValue = v2;
|
||||||
console.log("randomizer widget value update: ", internalValue);
|
|
||||||
if (typeof widget.onSetValue === "function") {
|
|
||||||
widget.onSetValue(v2);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
serialize: true,
|
serialize: true,
|
||||||
getMinHeight() {
|
getMinHeight() {
|
||||||
@@ -13807,9 +13831,6 @@ function createLoraRandomizerWidget(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
widget.updateConfig = (v2) => {
|
|
||||||
internalValue = v2;
|
|
||||||
};
|
|
||||||
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node);
|
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node);
|
||||||
widget.onRoll = (randomLoras) => {
|
widget.onRoll = (randomLoras) => {
|
||||||
const lorasWidget = node.widgets.find((w2) => w2.name === "loras");
|
const lorasWidget = node.widgets.find((w2) => w2.name === "loras");
|
||||||
@@ -13863,9 +13884,6 @@ function createLoraCyclerWidget(node) {
|
|||||||
setValue(v2) {
|
setValue(v2) {
|
||||||
const oldFilename = internalValue == null ? void 0 : internalValue.current_lora_filename;
|
const oldFilename = internalValue == null ? void 0 : internalValue.current_lora_filename;
|
||||||
internalValue = v2;
|
internalValue = v2;
|
||||||
if (typeof widget.onSetValue === "function") {
|
|
||||||
widget.onSetValue(v2);
|
|
||||||
}
|
|
||||||
if (oldFilename !== (v2 == null ? void 0 : v2.current_lora_filename)) {
|
if (oldFilename !== (v2 == null ? void 0 : v2.current_lora_filename)) {
|
||||||
updateDownstreamLoaders(node);
|
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);
|
node.getPoolConfig = () => getPoolConfigFromConnectedNode(node);
|
||||||
const vueApp = createApp(LoraCyclerWidget, {
|
const vueApp = createApp(LoraCyclerWidget, {
|
||||||
widget,
|
widget,
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user