mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Compare commits
3 Commits
03e1fa75c5
...
61c31ecbd0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61c31ecbd0 | ||
|
|
1ae1b0d607 | ||
|
|
8dd849892d |
@@ -56,6 +56,9 @@ class LoraCyclerLM:
|
|||||||
clip_strength = float(cycler_config.get("clip_strength", 1.0))
|
clip_strength = float(cycler_config.get("clip_strength", 1.0))
|
||||||
sort_by = "filename"
|
sort_by = "filename"
|
||||||
|
|
||||||
|
# Include "no lora" option
|
||||||
|
include_no_lora = cycler_config.get("include_no_lora", False)
|
||||||
|
|
||||||
# Dual-index mechanism for batch queue synchronization
|
# Dual-index mechanism for batch queue synchronization
|
||||||
execution_index = cycler_config.get("execution_index") # Can be None
|
execution_index = cycler_config.get("execution_index") # Can be None
|
||||||
# next_index_from_config = cycler_config.get("next_index") # Not used on backend
|
# next_index_from_config = cycler_config.get("next_index") # Not used on backend
|
||||||
@@ -71,7 +74,10 @@ class LoraCyclerLM:
|
|||||||
|
|
||||||
total_count = len(lora_list)
|
total_count = len(lora_list)
|
||||||
|
|
||||||
if total_count == 0:
|
# Calculate effective total count (includes no lora option if enabled)
|
||||||
|
effective_total_count = total_count + 1 if include_no_lora else total_count
|
||||||
|
|
||||||
|
if total_count == 0 and not include_no_lora:
|
||||||
logger.warning("[LoraCyclerLM] No LoRAs available in pool")
|
logger.warning("[LoraCyclerLM] No LoRAs available in pool")
|
||||||
return {
|
return {
|
||||||
"result": ([],),
|
"result": ([],),
|
||||||
@@ -93,42 +99,66 @@ class LoraCyclerLM:
|
|||||||
else:
|
else:
|
||||||
actual_index = current_index
|
actual_index = current_index
|
||||||
|
|
||||||
# Clamp index to valid range (1-based)
|
# Clamp index to valid range (1-based, includes no lora if enabled)
|
||||||
clamped_index = max(1, min(actual_index, total_count))
|
clamped_index = max(1, min(actual_index, effective_total_count))
|
||||||
|
|
||||||
# Get LoRA at current index (convert to 0-based for list access)
|
# Check if current index is the "no lora" option (last position when include_no_lora is True)
|
||||||
current_lora = lora_list[clamped_index - 1]
|
is_no_lora = include_no_lora and clamped_index == effective_total_count
|
||||||
|
|
||||||
# Build LORA_STACK with single LoRA
|
if is_no_lora:
|
||||||
lora_path, _ = get_lora_info(current_lora["file_name"])
|
# "No LoRA" option - return empty stack
|
||||||
if not lora_path:
|
|
||||||
logger.warning(
|
|
||||||
f"[LoraCyclerLM] Could not find path for LoRA: {current_lora['file_name']}"
|
|
||||||
)
|
|
||||||
lora_stack = []
|
lora_stack = []
|
||||||
|
current_lora_name = "No LoRA"
|
||||||
|
current_lora_filename = "No LoRA"
|
||||||
else:
|
else:
|
||||||
# Normalize path separators
|
# Get LoRA at current index (convert to 0-based for list access)
|
||||||
lora_path = lora_path.replace("/", os.sep)
|
current_lora = lora_list[clamped_index - 1]
|
||||||
lora_stack = [(lora_path, model_strength, clip_strength)]
|
current_lora_name = current_lora["file_name"]
|
||||||
|
current_lora_filename = current_lora["file_name"]
|
||||||
|
|
||||||
|
# Build LORA_STACK with single LoRA
|
||||||
|
if current_lora["file_name"] == "None":
|
||||||
|
lora_path = None
|
||||||
|
else:
|
||||||
|
lora_path, _ = get_lora_info(current_lora["file_name"])
|
||||||
|
|
||||||
|
if not lora_path:
|
||||||
|
if current_lora["file_name"] != "None":
|
||||||
|
logger.warning(
|
||||||
|
f"[LoraCyclerLM] Could not find path for LoRA: {current_lora['file_name']}"
|
||||||
|
)
|
||||||
|
lora_stack = []
|
||||||
|
else:
|
||||||
|
# Normalize path separators
|
||||||
|
lora_path = lora_path.replace("/", os.sep)
|
||||||
|
lora_stack = [(lora_path, model_strength, clip_strength)]
|
||||||
|
|
||||||
# Calculate next index (wrap to 1 if at end)
|
# Calculate next index (wrap to 1 if at end)
|
||||||
next_index = clamped_index + 1
|
next_index = clamped_index + 1
|
||||||
if next_index > total_count:
|
if next_index > effective_total_count:
|
||||||
next_index = 1
|
next_index = 1
|
||||||
|
|
||||||
# Get next LoRA for UI display (what will be used next generation)
|
# Get next LoRA for UI display (what will be used next generation)
|
||||||
next_lora = lora_list[next_index - 1]
|
is_next_no_lora = include_no_lora and next_index == effective_total_count
|
||||||
next_display_name = next_lora["file_name"]
|
if is_next_no_lora:
|
||||||
|
next_display_name = "No LoRA"
|
||||||
|
next_lora_filename = "No LoRA"
|
||||||
|
else:
|
||||||
|
next_lora = lora_list[next_index - 1]
|
||||||
|
next_display_name = next_lora["file_name"]
|
||||||
|
next_lora_filename = next_lora["file_name"]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"result": (lora_stack,),
|
"result": (lora_stack,),
|
||||||
"ui": {
|
"ui": {
|
||||||
"current_index": [clamped_index],
|
"current_index": [clamped_index],
|
||||||
"next_index": [next_index],
|
"next_index": [next_index],
|
||||||
"total_count": [total_count],
|
"total_count": [
|
||||||
"current_lora_name": [current_lora["file_name"]],
|
total_count
|
||||||
"current_lora_filename": [current_lora["file_name"]],
|
], # Return actual LoRA count, not effective_total_count
|
||||||
|
"current_lora_name": [current_lora_name],
|
||||||
|
"current_lora_filename": [current_lora_filename],
|
||||||
"next_lora_name": [next_display_name],
|
"next_lora_name": [next_display_name],
|
||||||
"next_lora_filename": [next_lora["file_name"]],
|
"next_lora_filename": [next_lora_filename],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
addopts = -v --import-mode=importlib -m "not performance"
|
addopts = -v --import-mode=importlib -m "not performance" --ignore=__init__.py
|
||||||
testpaths = tests
|
testpaths = tests
|
||||||
python_files = test_*.py
|
python_files = test_*.py
|
||||||
python_classes = Test*
|
python_classes = Test*
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<div class="lora-cycler-widget">
|
<div class="lora-cycler-widget">
|
||||||
<LoraCyclerSettingsView
|
<LoraCyclerSettingsView
|
||||||
:current-index="state.currentIndex.value"
|
:current-index="state.currentIndex.value"
|
||||||
:total-count="state.totalCount.value"
|
:total-count="displayTotalCount"
|
||||||
:current-lora-name="state.currentLoraName.value"
|
:current-lora-name="displayLoraName"
|
||||||
:current-lora-filename="state.currentLoraFilename.value"
|
:current-lora-filename="state.currentLoraFilename.value"
|
||||||
:model-strength="state.modelStrength.value"
|
:model-strength="state.modelStrength.value"
|
||||||
:clip-strength="state.clipStrength.value"
|
:clip-strength="state.clipStrength.value"
|
||||||
@@ -16,11 +16,14 @@
|
|||||||
:is-pause-disabled="hasQueuedPrompts"
|
:is-pause-disabled="hasQueuedPrompts"
|
||||||
:is-workflow-executing="state.isWorkflowExecuting.value"
|
:is-workflow-executing="state.isWorkflowExecuting.value"
|
||||||
:executing-repeat-step="state.executingRepeatStep.value"
|
:executing-repeat-step="state.executingRepeatStep.value"
|
||||||
|
:include-no-lora="state.includeNoLora.value"
|
||||||
|
:is-no-lora="isNoLora"
|
||||||
@update:current-index="handleIndexUpdate"
|
@update:current-index="handleIndexUpdate"
|
||||||
@update:model-strength="state.modelStrength.value = $event"
|
@update:model-strength="state.modelStrength.value = $event"
|
||||||
@update:clip-strength="state.clipStrength.value = $event"
|
@update:clip-strength="state.clipStrength.value = $event"
|
||||||
@update:use-custom-clip-range="handleUseCustomClipRangeChange"
|
@update:use-custom-clip-range="handleUseCustomClipRangeChange"
|
||||||
@update:repeat-count="handleRepeatCountChange"
|
@update:repeat-count="handleRepeatCountChange"
|
||||||
|
@update:include-no-lora="handleIncludeNoLoraChange"
|
||||||
@toggle-pause="handleTogglePause"
|
@toggle-pause="handleTogglePause"
|
||||||
@reset-index="handleResetIndex"
|
@reset-index="handleResetIndex"
|
||||||
@open-lora-selector="isModalOpen = true"
|
@open-lora-selector="isModalOpen = true"
|
||||||
@@ -30,6 +33,7 @@
|
|||||||
:visible="isModalOpen"
|
:visible="isModalOpen"
|
||||||
:lora-list="cachedLoraList"
|
:lora-list="cachedLoraList"
|
||||||
:current-index="state.currentIndex.value"
|
:current-index="state.currentIndex.value"
|
||||||
|
:include-no-lora="state.includeNoLora.value"
|
||||||
@close="isModalOpen = false"
|
@close="isModalOpen = false"
|
||||||
@select="handleModalSelect"
|
@select="handleModalSelect"
|
||||||
/>
|
/>
|
||||||
@@ -37,7 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref, computed } from 'vue'
|
||||||
import LoraCyclerSettingsView from './lora-cycler/LoraCyclerSettingsView.vue'
|
import LoraCyclerSettingsView from './lora-cycler/LoraCyclerSettingsView.vue'
|
||||||
import LoraListModal from './lora-cycler/LoraListModal.vue'
|
import LoraListModal from './lora-cycler/LoraListModal.vue'
|
||||||
import { useLoraCyclerState } from '../composables/useLoraCyclerState'
|
import { useLoraCyclerState } from '../composables/useLoraCyclerState'
|
||||||
@@ -102,6 +106,31 @@ const isModalOpen = ref(false)
|
|||||||
// Cache for LoRA list (used by modal)
|
// Cache for LoRA list (used by modal)
|
||||||
const cachedLoraList = ref<LoraItem[]>([])
|
const cachedLoraList = ref<LoraItem[]>([])
|
||||||
|
|
||||||
|
// Computed: display total count (includes no lora option if enabled)
|
||||||
|
const displayTotalCount = computed(() => {
|
||||||
|
const baseCount = state.totalCount.value
|
||||||
|
return state.includeNoLora.value ? baseCount + 1 : baseCount
|
||||||
|
})
|
||||||
|
|
||||||
|
// Computed: display LoRA name (shows "No LoRA" if on the last index and includeNoLora is enabled)
|
||||||
|
const displayLoraName = computed(() => {
|
||||||
|
const currentIndex = state.currentIndex.value
|
||||||
|
const totalCount = state.totalCount.value
|
||||||
|
|
||||||
|
// If includeNoLora is enabled and we're on the last position (no lora slot)
|
||||||
|
if (state.includeNoLora.value && currentIndex === totalCount + 1) {
|
||||||
|
return 'No LoRA'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise show the normal LoRA name
|
||||||
|
return state.currentLoraName.value
|
||||||
|
})
|
||||||
|
|
||||||
|
// Computed: check if currently on "No LoRA" option
|
||||||
|
const isNoLora = computed(() => {
|
||||||
|
return state.includeNoLora.value && state.currentIndex.value === state.totalCount.value + 1
|
||||||
|
})
|
||||||
|
|
||||||
// Get pool config from connected node
|
// Get pool config from connected node
|
||||||
const getPoolConfig = (): LoraPoolConfig | null => {
|
const getPoolConfig = (): LoraPoolConfig | null => {
|
||||||
// Check if getPoolConfig method exists on node (added by main.ts)
|
// Check if getPoolConfig method exists on node (added by main.ts)
|
||||||
@@ -113,7 +142,17 @@ const getPoolConfig = (): LoraPoolConfig | null => {
|
|||||||
|
|
||||||
// Update display from LoRA list and index
|
// Update display from LoRA list and index
|
||||||
const updateDisplayFromLoraList = (loraList: LoraItem[], index: number) => {
|
const updateDisplayFromLoraList = (loraList: LoraItem[], index: number) => {
|
||||||
if (loraList.length > 0 && index > 0 && index <= loraList.length) {
|
const actualLoraCount = loraList.length
|
||||||
|
|
||||||
|
// If index is beyond actual LoRA count, it means we're on the "no lora" option
|
||||||
|
if (state.includeNoLora.value && index === actualLoraCount + 1) {
|
||||||
|
state.currentLoraName.value = 'No LoRA'
|
||||||
|
state.currentLoraFilename.value = 'No LoRA'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, show normal LoRA info
|
||||||
|
if (actualLoraCount > 0 && index > 0 && index <= actualLoraCount) {
|
||||||
const currentLora = loraList[index - 1]
|
const currentLora = loraList[index - 1]
|
||||||
if (currentLora) {
|
if (currentLora) {
|
||||||
state.currentLoraName.value = currentLora.file_name
|
state.currentLoraName.value = currentLora.file_name
|
||||||
@@ -124,6 +163,14 @@ const updateDisplayFromLoraList = (loraList: LoraItem[], index: number) => {
|
|||||||
|
|
||||||
// Handle index update from user
|
// Handle index update from user
|
||||||
const handleIndexUpdate = async (newIndex: number) => {
|
const handleIndexUpdate = async (newIndex: number) => {
|
||||||
|
// Calculate max valid index (includes no lora slot if enabled)
|
||||||
|
const maxIndex = state.includeNoLora.value
|
||||||
|
? state.totalCount.value + 1
|
||||||
|
: state.totalCount.value
|
||||||
|
|
||||||
|
// Clamp index to valid range
|
||||||
|
const clampedIndex = Math.max(1, Math.min(newIndex, maxIndex || 1))
|
||||||
|
|
||||||
// Reset execution state when user manually changes index
|
// Reset execution state when user manually changes index
|
||||||
// This ensures the next execution starts from the user-set index
|
// This ensures the next execution starts from the user-set index
|
||||||
;(props.widget as any)[HAS_EXECUTED] = false
|
;(props.widget as any)[HAS_EXECUTED] = false
|
||||||
@@ -134,14 +181,14 @@ const handleIndexUpdate = async (newIndex: number) => {
|
|||||||
executionQueue.length = 0
|
executionQueue.length = 0
|
||||||
hasQueuedPrompts.value = false
|
hasQueuedPrompts.value = false
|
||||||
|
|
||||||
state.setIndex(newIndex)
|
state.setIndex(clampedIndex)
|
||||||
|
|
||||||
// Refresh list to update current LoRA display
|
// Refresh list to update current LoRA display
|
||||||
try {
|
try {
|
||||||
const poolConfig = getPoolConfig()
|
const poolConfig = getPoolConfig()
|
||||||
const loraList = await state.fetchCyclerList(poolConfig)
|
const loraList = await state.fetchCyclerList(poolConfig)
|
||||||
cachedLoraList.value = loraList
|
cachedLoraList.value = loraList
|
||||||
updateDisplayFromLoraList(loraList, newIndex)
|
updateDisplayFromLoraList(loraList, clampedIndex)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[LoraCyclerWidget] Error updating index:', error)
|
console.error('[LoraCyclerWidget] Error updating index:', error)
|
||||||
}
|
}
|
||||||
@@ -169,6 +216,17 @@ const handleRepeatCountChange = (newValue: number) => {
|
|||||||
state.displayRepeatUsed.value = 0
|
state.displayRepeatUsed.value = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle include no lora toggle
|
||||||
|
const handleIncludeNoLoraChange = (newValue: boolean) => {
|
||||||
|
state.includeNoLora.value = newValue
|
||||||
|
|
||||||
|
// If turning off and current index is beyond the actual LoRA count,
|
||||||
|
// clamp it to the last valid LoRA index
|
||||||
|
if (!newValue && state.currentIndex.value > state.totalCount.value) {
|
||||||
|
state.currentIndex.value = Math.max(1, state.totalCount.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle pause toggle
|
// Handle pause toggle
|
||||||
const handleTogglePause = () => {
|
const handleTogglePause = () => {
|
||||||
state.togglePause()
|
state.togglePause()
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
@click="handleOpenSelector"
|
@click="handleOpenSelector"
|
||||||
>
|
>
|
||||||
<span class="progress-label">{{ isWorkflowExecuting ? 'Using LoRA:' : 'Next LoRA:' }}</span>
|
<span class="progress-label">{{ isWorkflowExecuting ? 'Using LoRA:' : 'Next LoRA:' }}</span>
|
||||||
<span class="progress-name clickable" :class="{ disabled: isPauseDisabled }" :title="currentLoraFilename">
|
<span class="progress-name clickable"
|
||||||
|
:class="{ disabled: isPauseDisabled, 'no-lora': isNoLora }"
|
||||||
|
:title="currentLoraFilename">
|
||||||
{{ currentLoraName || 'None' }}
|
{{ currentLoraName || 'None' }}
|
||||||
<svg class="selector-icon" viewBox="0 0 24 24" fill="currentColor">
|
<svg class="selector-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path d="M7 10l5 5 5-5z"/>
|
<path d="M7 10l5 5 5-5z"/>
|
||||||
@@ -160,6 +162,27 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Include No LoRA Toggle -->
|
||||||
|
<div class="setting-section">
|
||||||
|
<div class="section-header-with-toggle">
|
||||||
|
<label class="setting-label">
|
||||||
|
Add "No LoRA" step
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="toggle-switch"
|
||||||
|
:class="{ 'toggle-switch--active': includeNoLora }"
|
||||||
|
@click="$emit('update:includeNoLora', !includeNoLora)"
|
||||||
|
role="switch"
|
||||||
|
:aria-checked="includeNoLora"
|
||||||
|
title="Add an iteration without LoRA for comparison"
|
||||||
|
>
|
||||||
|
<span class="toggle-switch__track"></span>
|
||||||
|
<span class="toggle-switch__thumb"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -182,6 +205,8 @@ const props = defineProps<{
|
|||||||
isPauseDisabled: boolean
|
isPauseDisabled: boolean
|
||||||
isWorkflowExecuting: boolean
|
isWorkflowExecuting: boolean
|
||||||
executingRepeatStep: number
|
executingRepeatStep: number
|
||||||
|
includeNoLora: boolean
|
||||||
|
isNoLora?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -190,6 +215,7 @@ const emit = defineEmits<{
|
|||||||
'update:clipStrength': [value: number]
|
'update:clipStrength': [value: number]
|
||||||
'update:useCustomClipRange': [value: boolean]
|
'update:useCustomClipRange': [value: boolean]
|
||||||
'update:repeatCount': [value: number]
|
'update:repeatCount': [value: number]
|
||||||
|
'update:includeNoLora': [value: boolean]
|
||||||
'toggle-pause': []
|
'toggle-pause': []
|
||||||
'reset-index': []
|
'reset-index': []
|
||||||
'open-lora-selector': []
|
'open-lora-selector': []
|
||||||
@@ -346,6 +372,16 @@ const onRepeatBlur = (event: Event) => {
|
|||||||
color: rgba(191, 219, 254, 1);
|
color: rgba(191, 219, 254, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.progress-name.no-lora {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgba(226, 232, 240, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-name.clickable.no-lora:hover:not(.disabled) {
|
||||||
|
background: rgba(160, 174, 192, 0.2);
|
||||||
|
color: rgba(226, 232, 240, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
.progress-name.clickable.disabled {
|
.progress-name.clickable.disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
|||||||
@@ -35,7 +35,10 @@
|
|||||||
v-for="item in filteredList"
|
v-for="item in filteredList"
|
||||||
:key="item.index"
|
:key="item.index"
|
||||||
class="lora-item"
|
class="lora-item"
|
||||||
:class="{ active: currentIndex === item.index }"
|
:class="{
|
||||||
|
active: currentIndex === item.index,
|
||||||
|
'no-lora-item': item.lora.file_name === 'No LoRA'
|
||||||
|
}"
|
||||||
@mouseenter="showPreview(item.lora.file_name, $event)"
|
@mouseenter="showPreview(item.lora.file_name, $event)"
|
||||||
@mouseleave="hidePreview"
|
@mouseleave="hidePreview"
|
||||||
@click="selectLora(item.index)"
|
@click="selectLora(item.index)"
|
||||||
@@ -65,6 +68,7 @@ const props = defineProps<{
|
|||||||
visible: boolean
|
visible: boolean
|
||||||
loraList: LoraItem[]
|
loraList: LoraItem[]
|
||||||
currentIndex: number
|
currentIndex: number
|
||||||
|
includeNoLora?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -79,7 +83,8 @@ const searchInputRef = ref<HTMLInputElement | null>(null)
|
|||||||
let previewTooltip: any = null
|
let previewTooltip: any = null
|
||||||
|
|
||||||
const subtitleText = computed(() => {
|
const subtitleText = computed(() => {
|
||||||
const total = props.loraList.length
|
const baseTotal = props.loraList.length
|
||||||
|
const total = props.includeNoLora ? baseTotal + 1 : baseTotal
|
||||||
const filtered = filteredList.value.length
|
const filtered = filteredList.value.length
|
||||||
if (filtered === total) {
|
if (filtered === total) {
|
||||||
return `Total: ${total} LoRA${total !== 1 ? 's' : ''}`
|
return `Total: ${total} LoRA${total !== 1 ? 's' : ''}`
|
||||||
@@ -88,11 +93,19 @@ const subtitleText = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const filteredList = computed<LoraListItem[]>(() => {
|
const filteredList = computed<LoraListItem[]>(() => {
|
||||||
const list = props.loraList.map((lora, idx) => ({
|
const list: LoraListItem[] = props.loraList.map((lora, idx) => ({
|
||||||
index: idx + 1,
|
index: idx + 1,
|
||||||
lora
|
lora
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// Add "No LoRA" option at the end if includeNoLora is enabled
|
||||||
|
if (props.includeNoLora) {
|
||||||
|
list.push({
|
||||||
|
index: list.length + 1,
|
||||||
|
lora: { file_name: 'No LoRA' } as LoraItem
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (!searchQuery.value.trim()) {
|
if (!searchQuery.value.trim()) {
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
@@ -303,6 +316,15 @@ onUnmounted(() => {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lora-item.no-lora-item .lora-name {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgba(226, 232, 240, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lora-item.no-lora-item:hover .lora-name {
|
||||||
|
color: rgba(226, 232, 240, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
.no-results {
|
.no-results {
|
||||||
padding: 32px 20px;
|
padding: 32px 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export interface LoraPoolConfig {
|
|||||||
noCreditRequired: boolean
|
noCreditRequired: boolean
|
||||||
allowSelling: boolean
|
allowSelling: boolean
|
||||||
}
|
}
|
||||||
|
includeEmptyLora?: boolean // Optional, deprecated (moved to Cycler)
|
||||||
}
|
}
|
||||||
preview: { matchCount: number; lastUpdated: number }
|
preview: { matchCount: number; lastUpdated: number }
|
||||||
}
|
}
|
||||||
@@ -84,6 +85,8 @@ export interface CyclerConfig {
|
|||||||
repeat_count: number // How many times each LoRA should repeat (default: 1)
|
repeat_count: number // How many times each LoRA should repeat (default: 1)
|
||||||
repeat_used: number // How many times current index has been used
|
repeat_used: number // How many times current index has been used
|
||||||
is_paused: boolean // Whether iteration is paused
|
is_paused: boolean // Whether iteration is paused
|
||||||
|
// Include "no LoRA" option in cycle
|
||||||
|
include_no_lora: boolean // Whether to include empty LoRA option
|
||||||
}
|
}
|
||||||
|
|
||||||
// Widget config union type
|
// Widget config union type
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { ComponentWidget, CyclerConfig, LoraPoolConfig } from './types'
|
|||||||
export interface CyclerLoraItem {
|
export interface CyclerLoraItem {
|
||||||
file_name: string
|
file_name: string
|
||||||
model_name: string
|
model_name: string
|
||||||
|
file_path: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
||||||
@@ -34,6 +35,7 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
const repeatUsed = ref(0) // How many times current index has been used (internal tracking)
|
const repeatUsed = ref(0) // How many times current index has been used (internal tracking)
|
||||||
const displayRepeatUsed = ref(0) // For UI display, deferred updates like currentIndex
|
const displayRepeatUsed = ref(0) // For UI display, deferred updates like currentIndex
|
||||||
const isPaused = ref(false) // Whether iteration is paused
|
const isPaused = ref(false) // Whether iteration is paused
|
||||||
|
const includeNoLora = ref(false) // Whether to include empty LoRA option in cycle
|
||||||
|
|
||||||
// Execution progress tracking (visual feedback)
|
// Execution progress tracking (visual feedback)
|
||||||
const isWorkflowExecuting = ref(false) // Workflow is currently running
|
const isWorkflowExecuting = ref(false) // Workflow is currently running
|
||||||
@@ -58,6 +60,7 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
repeat_count: repeatCount.value,
|
repeat_count: repeatCount.value,
|
||||||
repeat_used: repeatUsed.value,
|
repeat_used: repeatUsed.value,
|
||||||
is_paused: isPaused.value,
|
is_paused: isPaused.value,
|
||||||
|
include_no_lora: includeNoLora.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -75,6 +78,7 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
repeat_count: repeatCount.value,
|
repeat_count: repeatCount.value,
|
||||||
repeat_used: repeatUsed.value,
|
repeat_used: repeatUsed.value,
|
||||||
is_paused: isPaused.value,
|
is_paused: isPaused.value,
|
||||||
|
include_no_lora: includeNoLora.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +97,13 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
sortBy.value = config.sort_by || 'filename'
|
sortBy.value = config.sort_by || 'filename'
|
||||||
currentLoraName.value = config.current_lora_name || ''
|
currentLoraName.value = config.current_lora_name || ''
|
||||||
currentLoraFilename.value = config.current_lora_filename || ''
|
currentLoraFilename.value = config.current_lora_filename || ''
|
||||||
// Advanced index control features
|
// Advanced index control features
|
||||||
repeatCount.value = config.repeat_count ?? 1
|
repeatCount.value = config.repeat_count ?? 1
|
||||||
repeatUsed.value = config.repeat_used ?? 0
|
repeatUsed.value = config.repeat_used ?? 0
|
||||||
isPaused.value = config.is_paused ?? false
|
isPaused.value = config.is_paused ?? false
|
||||||
// Note: execution_index and next_index are not restored from config
|
includeNoLora.value = config.include_no_lora ?? false
|
||||||
// as they are transient values used only during batch execution
|
// Note: execution_index and next_index are not restored from config
|
||||||
|
// as they are transient values used only during batch execution
|
||||||
} finally {
|
} finally {
|
||||||
isRestoring = false
|
isRestoring = false
|
||||||
}
|
}
|
||||||
@@ -111,7 +116,9 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
// Calculate the next index (wrap to 1 if at end)
|
// Calculate the next index (wrap to 1 if at end)
|
||||||
const current = executionIndex.value ?? currentIndex.value
|
const current = executionIndex.value ?? currentIndex.value
|
||||||
let next = current + 1
|
let next = current + 1
|
||||||
if (totalCount.value > 0 && next > totalCount.value) {
|
// Total count includes no lora option if enabled
|
||||||
|
const effectiveTotalCount = includeNoLora.value ? totalCount.value + 1 : totalCount.value
|
||||||
|
if (effectiveTotalCount > 0 && next > effectiveTotalCount) {
|
||||||
next = 1
|
next = 1
|
||||||
}
|
}
|
||||||
nextIndex.value = next
|
nextIndex.value = next
|
||||||
@@ -122,7 +129,9 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
if (nextIndex.value === null) {
|
if (nextIndex.value === null) {
|
||||||
// First execution uses current_index, so next is current + 1
|
// First execution uses current_index, so next is current + 1
|
||||||
let next = currentIndex.value + 1
|
let next = currentIndex.value + 1
|
||||||
if (totalCount.value > 0 && next > totalCount.value) {
|
// Total count includes no lora option if enabled
|
||||||
|
const effectiveTotalCount = includeNoLora.value ? totalCount.value + 1 : totalCount.value
|
||||||
|
if (effectiveTotalCount > 0 && next > effectiveTotalCount) {
|
||||||
next = 1
|
next = 1
|
||||||
}
|
}
|
||||||
nextIndex.value = next
|
nextIndex.value = next
|
||||||
@@ -230,7 +239,9 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
|
|
||||||
// Set index manually
|
// Set index manually
|
||||||
const setIndex = (index: number) => {
|
const setIndex = (index: number) => {
|
||||||
if (index >= 1 && index <= totalCount.value) {
|
// Total count includes no lora option if enabled
|
||||||
|
const effectiveTotalCount = includeNoLora.value ? totalCount.value + 1 : totalCount.value
|
||||||
|
if (index >= 1 && index <= effectiveTotalCount) {
|
||||||
currentIndex.value = index
|
currentIndex.value = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,6 +283,7 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
repeatCount,
|
repeatCount,
|
||||||
repeatUsed,
|
repeatUsed,
|
||||||
isPaused,
|
isPaused,
|
||||||
|
includeNoLora,
|
||||||
], () => {
|
], () => {
|
||||||
widget.value = buildConfig()
|
widget.value = buildConfig()
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
@@ -294,6 +306,7 @@ export function useLoraCyclerState(widget: ComponentWidget<CyclerConfig>) {
|
|||||||
repeatUsed,
|
repeatUsed,
|
||||||
displayRepeatUsed,
|
displayRepeatUsed,
|
||||||
isPaused,
|
isPaused,
|
||||||
|
includeNoLora,
|
||||||
isWorkflowExecuting,
|
isWorkflowExecuting,
|
||||||
executingRepeatStep,
|
executingRepeatStep,
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const LORA_RANDOMIZER_WIDGET_MIN_WIDTH = 500
|
|||||||
const LORA_RANDOMIZER_WIDGET_MIN_HEIGHT = 448
|
const LORA_RANDOMIZER_WIDGET_MIN_HEIGHT = 448
|
||||||
const LORA_RANDOMIZER_WIDGET_MAX_HEIGHT = LORA_RANDOMIZER_WIDGET_MIN_HEIGHT
|
const LORA_RANDOMIZER_WIDGET_MAX_HEIGHT = LORA_RANDOMIZER_WIDGET_MIN_HEIGHT
|
||||||
const LORA_CYCLER_WIDGET_MIN_WIDTH = 380
|
const LORA_CYCLER_WIDGET_MIN_WIDTH = 380
|
||||||
const LORA_CYCLER_WIDGET_MIN_HEIGHT = 314
|
const LORA_CYCLER_WIDGET_MIN_HEIGHT = 344
|
||||||
const LORA_CYCLER_WIDGET_MAX_HEIGHT = LORA_CYCLER_WIDGET_MIN_HEIGHT
|
const LORA_CYCLER_WIDGET_MAX_HEIGHT = LORA_CYCLER_WIDGET_MIN_HEIGHT
|
||||||
const JSON_DISPLAY_WIDGET_MIN_WIDTH = 300
|
const JSON_DISPLAY_WIDGET_MIN_WIDTH = 300
|
||||||
const JSON_DISPLAY_WIDGET_MIN_HEIGHT = 200
|
const JSON_DISPLAY_WIDGET_MIN_HEIGHT = 200
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ describe('useLoraCyclerState', () => {
|
|||||||
current_lora_filename: '',
|
current_lora_filename: '',
|
||||||
repeat_count: 1,
|
repeat_count: 1,
|
||||||
repeat_used: 0,
|
repeat_used: 0,
|
||||||
is_paused: false
|
is_paused: false,
|
||||||
|
include_no_lora: false
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(state.currentIndex.value).toBe(5)
|
expect(state.currentIndex.value).toBe(5)
|
||||||
|
|||||||
4
vue-widgets/tests/fixtures/mockConfigs.ts
vendored
4
vue-widgets/tests/fixtures/mockConfigs.ts
vendored
@@ -24,6 +24,7 @@ export function createMockCyclerConfig(overrides: Partial<CyclerConfig> = {}): C
|
|||||||
repeat_count: 1,
|
repeat_count: 1,
|
||||||
repeat_used: 0,
|
repeat_used: 0,
|
||||||
is_paused: false,
|
is_paused: false,
|
||||||
|
include_no_lora: false,
|
||||||
...overrides
|
...overrides
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +55,8 @@ export function createMockPoolConfig(overrides: Partial<LoraPoolConfig> = {}): L
|
|||||||
export function createMockLoraList(count: number = 5): CyclerLoraItem[] {
|
export function createMockLoraList(count: number = 5): CyclerLoraItem[] {
|
||||||
return Array.from({ length: count }, (_, i) => ({
|
return Array.from({ length: count }, (_, i) => ({
|
||||||
file_name: `lora${i + 1}.safetensors`,
|
file_name: `lora${i + 1}.safetensors`,
|
||||||
model_name: `LoRA Model ${i + 1}`
|
model_name: `LoRA Model ${i + 1}`,
|
||||||
|
file_path: `/models/loras/lora${i + 1}.safetensors`
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1473,16 +1473,16 @@ to { transform: rotate(360deg);
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cycler-settings[data-v-5b16b9d3] {
|
.cycler-settings[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
color: #e4e4e7;
|
color: #e4e4e7;
|
||||||
}
|
}
|
||||||
.settings-header[data-v-5b16b9d3] {
|
.settings-header[data-v-f65566fd] {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.settings-title[data-v-5b16b9d3] {
|
.settings-title[data-v-f65566fd] {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
@@ -1491,10 +1491,10 @@ to { transform: rotate(360deg);
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
.setting-section[data-v-5b16b9d3] {
|
.setting-section[data-v-f65566fd] {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.setting-label[data-v-5b16b9d3] {
|
.setting-label[data-v-f65566fd] {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: rgba(226, 232, 240, 0.8);
|
color: rgba(226, 232, 240, 0.8);
|
||||||
@@ -1503,10 +1503,10 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Progress Display */
|
/* Progress Display */
|
||||||
.progress-section[data-v-5b16b9d3] {
|
.progress-section[data-v-f65566fd] {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
.progress-display[data-v-5b16b9d3] {
|
.progress-display[data-v-f65566fd] {
|
||||||
background: rgba(26, 32, 44, 0.9);
|
background: rgba(26, 32, 44, 0.9);
|
||||||
border: 1px solid rgba(226, 232, 240, 0.2);
|
border: 1px solid rgba(226, 232, 240, 0.2);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -1516,31 +1516,31 @@ to { transform: rotate(360deg);
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
transition: border-color 0.3s ease;
|
transition: border-color 0.3s ease;
|
||||||
}
|
}
|
||||||
.progress-display.executing[data-v-5b16b9d3] {
|
.progress-display.executing[data-v-f65566fd] {
|
||||||
border-color: rgba(66, 153, 225, 0.5);
|
border-color: rgba(66, 153, 225, 0.5);
|
||||||
animation: pulse-5b16b9d3 2s ease-in-out infinite;
|
animation: pulse-f65566fd 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
@keyframes pulse-5b16b9d3 {
|
@keyframes pulse-f65566fd {
|
||||||
0%, 100% { border-color: rgba(66, 153, 225, 0.3);
|
0%, 100% { border-color: rgba(66, 153, 225, 0.3);
|
||||||
}
|
}
|
||||||
50% { border-color: rgba(66, 153, 225, 0.7);
|
50% { border-color: rgba(66, 153, 225, 0.7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.progress-info[data-v-5b16b9d3] {
|
.progress-info[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
.progress-label[data-v-5b16b9d3] {
|
.progress-label[data-v-f65566fd] {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: rgba(226, 232, 240, 0.5);
|
color: rgba(226, 232, 240, 0.5);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
}
|
}
|
||||||
.progress-name[data-v-5b16b9d3] {
|
.progress-name[data-v-f65566fd] {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: rgba(191, 219, 254, 1);
|
color: rgba(191, 219, 254, 1);
|
||||||
@@ -1548,7 +1548,7 @@ to { transform: rotate(360deg);
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.progress-name.clickable[data-v-5b16b9d3] {
|
.progress-name.clickable[data-v-f65566fd] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
margin: -2px -6px;
|
margin: -2px -6px;
|
||||||
@@ -1558,34 +1558,42 @@ to { transform: rotate(360deg);
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
.progress-name.clickable[data-v-5b16b9d3]:hover:not(.disabled) {
|
.progress-name.clickable[data-v-f65566fd]:hover:not(.disabled) {
|
||||||
background: rgba(66, 153, 225, 0.2);
|
background: rgba(66, 153, 225, 0.2);
|
||||||
color: rgba(191, 219, 254, 1);
|
color: rgba(191, 219, 254, 1);
|
||||||
}
|
}
|
||||||
.progress-name.clickable.disabled[data-v-5b16b9d3] {
|
.progress-name.no-lora[data-v-f65566fd] {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgba(226, 232, 240, 0.6);
|
||||||
|
}
|
||||||
|
.progress-name.clickable.no-lora[data-v-f65566fd]:hover:not(.disabled) {
|
||||||
|
background: rgba(160, 174, 192, 0.2);
|
||||||
|
color: rgba(226, 232, 240, 0.8);
|
||||||
|
}
|
||||||
|
.progress-name.clickable.disabled[data-v-f65566fd] {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.progress-info.disabled[data-v-5b16b9d3] {
|
.progress-info.disabled[data-v-f65566fd] {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.selector-icon[data-v-5b16b9d3] {
|
.selector-icon[data-v-f65566fd] {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.progress-name.clickable:hover .selector-icon[data-v-5b16b9d3] {
|
.progress-name.clickable:hover .selector-icon[data-v-f65566fd] {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
.progress-counter[data-v-5b16b9d3] {
|
.progress-counter[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.progress-index[data-v-5b16b9d3] {
|
.progress-index[data-v-f65566fd] {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: rgba(66, 153, 225, 1);
|
color: rgba(66, 153, 225, 1);
|
||||||
@@ -1594,12 +1602,12 @@ to { transform: rotate(360deg);
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
.progress-separator[data-v-5b16b9d3] {
|
.progress-separator[data-v-f65566fd] {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: rgba(226, 232, 240, 0.4);
|
color: rgba(226, 232, 240, 0.4);
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
}
|
}
|
||||||
.progress-total[data-v-5b16b9d3] {
|
.progress-total[data-v-f65566fd] {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: rgba(226, 232, 240, 0.6);
|
color: rgba(226, 232, 240, 0.6);
|
||||||
@@ -1610,7 +1618,7 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Repeat Progress */
|
/* Repeat Progress */
|
||||||
.repeat-progress[data-v-5b16b9d3] {
|
.repeat-progress[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
@@ -1620,23 +1628,23 @@ to { transform: rotate(360deg);
|
|||||||
border: 1px solid rgba(226, 232, 240, 0.1);
|
border: 1px solid rgba(226, 232, 240, 0.1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
.repeat-progress-track[data-v-5b16b9d3] {
|
.repeat-progress-track[data-v-f65566fd] {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: rgba(226, 232, 240, 0.15);
|
background: rgba(226, 232, 240, 0.15);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.repeat-progress-fill[data-v-5b16b9d3] {
|
.repeat-progress-fill[data-v-f65566fd] {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: linear-gradient(90deg, #f59e0b, #fbbf24);
|
background: linear-gradient(90deg, #f59e0b, #fbbf24);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
transition: width 0.3s ease;
|
transition: width 0.3s ease;
|
||||||
}
|
}
|
||||||
.repeat-progress-fill.is-complete[data-v-5b16b9d3] {
|
.repeat-progress-fill.is-complete[data-v-f65566fd] {
|
||||||
background: linear-gradient(90deg, #10b981, #34d399);
|
background: linear-gradient(90deg, #10b981, #34d399);
|
||||||
}
|
}
|
||||||
.repeat-progress-text[data-v-5b16b9d3] {
|
.repeat-progress-text[data-v-f65566fd] {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-family: 'SF Mono', 'Roboto Mono', monospace;
|
font-family: 'SF Mono', 'Roboto Mono', monospace;
|
||||||
color: rgba(253, 230, 138, 0.9);
|
color: rgba(253, 230, 138, 0.9);
|
||||||
@@ -1645,19 +1653,19 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Index Controls Row - Grouped Layout */
|
/* Index Controls Row - Grouped Layout */
|
||||||
.index-controls-row[data-v-5b16b9d3] {
|
.index-controls-row[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Control Group */
|
/* Control Group */
|
||||||
.control-group[data-v-5b16b9d3] {
|
.control-group[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
.control-group-label[data-v-5b16b9d3] {
|
.control-group-label[data-v-f65566fd] {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: rgba(226, 232, 240, 0.5);
|
color: rgba(226, 232, 240, 0.5);
|
||||||
@@ -1665,13 +1673,13 @@ to { transform: rotate(360deg);
|
|||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.control-group-content[data-v-5b16b9d3] {
|
.control-group-content[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
.index-input[data-v-5b16b9d3] {
|
.index-input[data-v-f65566fd] {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
@@ -1684,15 +1692,15 @@ to { transform: rotate(360deg);
|
|||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.index-input[data-v-5b16b9d3]:focus {
|
.index-input[data-v-f65566fd]:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(66, 153, 225, 0.6);
|
border-color: rgba(66, 153, 225, 0.6);
|
||||||
}
|
}
|
||||||
.index-input[data-v-5b16b9d3]:disabled {
|
.index-input[data-v-f65566fd]:disabled {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.index-hint[data-v-5b16b9d3] {
|
.index-hint[data-v-f65566fd] {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: rgba(226, 232, 240, 0.4);
|
color: rgba(226, 232, 240, 0.4);
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
@@ -1700,7 +1708,7 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Repeat Controls */
|
/* Repeat Controls */
|
||||||
.repeat-input[data-v-5b16b9d3] {
|
.repeat-input[data-v-f65566fd] {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
@@ -1714,11 +1722,11 @@ to { transform: rotate(360deg);
|
|||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.repeat-input[data-v-5b16b9d3]:focus {
|
.repeat-input[data-v-f65566fd]:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(66, 153, 225, 0.6);
|
border-color: rgba(66, 153, 225, 0.6);
|
||||||
}
|
}
|
||||||
.repeat-suffix[data-v-5b16b9d3] {
|
.repeat-suffix[data-v-f65566fd] {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: rgba(226, 232, 240, 0.4);
|
color: rgba(226, 232, 240, 0.4);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -1726,7 +1734,7 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Action Buttons */
|
/* Action Buttons */
|
||||||
.action-buttons[data-v-5b16b9d3] {
|
.action-buttons[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
@@ -1734,7 +1742,7 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Control Buttons */
|
/* Control Buttons */
|
||||||
.control-btn[data-v-5b16b9d3] {
|
.control-btn[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -1748,52 +1756,52 @@ to { transform: rotate(360deg);
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
.control-btn[data-v-5b16b9d3]:hover:not(:disabled) {
|
.control-btn[data-v-f65566fd]:hover:not(:disabled) {
|
||||||
background: rgba(66, 153, 225, 0.2);
|
background: rgba(66, 153, 225, 0.2);
|
||||||
border-color: rgba(66, 153, 225, 0.4);
|
border-color: rgba(66, 153, 225, 0.4);
|
||||||
color: rgba(191, 219, 254, 1);
|
color: rgba(191, 219, 254, 1);
|
||||||
}
|
}
|
||||||
.control-btn[data-v-5b16b9d3]:disabled {
|
.control-btn[data-v-f65566fd]:disabled {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.control-btn.active[data-v-5b16b9d3] {
|
.control-btn.active[data-v-f65566fd] {
|
||||||
background: rgba(245, 158, 11, 0.2);
|
background: rgba(245, 158, 11, 0.2);
|
||||||
border-color: rgba(245, 158, 11, 0.5);
|
border-color: rgba(245, 158, 11, 0.5);
|
||||||
color: rgba(253, 230, 138, 1);
|
color: rgba(253, 230, 138, 1);
|
||||||
}
|
}
|
||||||
.control-btn.active[data-v-5b16b9d3]:hover {
|
.control-btn.active[data-v-f65566fd]:hover {
|
||||||
background: rgba(245, 158, 11, 0.3);
|
background: rgba(245, 158, 11, 0.3);
|
||||||
border-color: rgba(245, 158, 11, 0.6);
|
border-color: rgba(245, 158, 11, 0.6);
|
||||||
}
|
}
|
||||||
.control-icon[data-v-5b16b9d3] {
|
.control-icon[data-v-f65566fd] {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Slider Container */
|
/* Slider Container */
|
||||||
.slider-container[data-v-5b16b9d3] {
|
.slider-container[data-v-f65566fd] {
|
||||||
background: rgba(26, 32, 44, 0.9);
|
background: rgba(26, 32, 44, 0.9);
|
||||||
border: 1px solid rgba(226, 232, 240, 0.2);
|
border: 1px solid rgba(226, 232, 240, 0.2);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
.slider-container--disabled[data-v-5b16b9d3] {
|
.slider-container--disabled[data-v-f65566fd] {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.section-header-with-toggle[data-v-5b16b9d3] {
|
.section-header-with-toggle[data-v-f65566fd] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.section-header-with-toggle .setting-label[data-v-5b16b9d3] {
|
.section-header-with-toggle .setting-label[data-v-f65566fd] {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Toggle Switch */
|
/* Toggle Switch */
|
||||||
.toggle-switch[data-v-5b16b9d3] {
|
.toggle-switch[data-v-f65566fd] {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
@@ -1802,7 +1810,7 @@ to { transform: rotate(360deg);
|
|||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.toggle-switch__track[data-v-5b16b9d3] {
|
.toggle-switch__track[data-v-f65566fd] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: var(--comfy-input-bg, #333);
|
background: var(--comfy-input-bg, #333);
|
||||||
@@ -1810,11 +1818,11 @@ to { transform: rotate(360deg);
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
.toggle-switch--active .toggle-switch__track[data-v-5b16b9d3] {
|
.toggle-switch--active .toggle-switch__track[data-v-f65566fd] {
|
||||||
background: rgba(66, 153, 225, 0.3);
|
background: rgba(66, 153, 225, 0.3);
|
||||||
border-color: rgba(66, 153, 225, 0.6);
|
border-color: rgba(66, 153, 225, 0.6);
|
||||||
}
|
}
|
||||||
.toggle-switch__thumb[data-v-5b16b9d3] {
|
.toggle-switch__thumb[data-v-f65566fd] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
left: 2px;
|
left: 2px;
|
||||||
@@ -1825,19 +1833,19 @@ to { transform: rotate(360deg);
|
|||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
.toggle-switch--active .toggle-switch__thumb[data-v-5b16b9d3] {
|
.toggle-switch--active .toggle-switch__thumb[data-v-f65566fd] {
|
||||||
transform: translateX(16px);
|
transform: translateX(16px);
|
||||||
background: #4299e1;
|
background: #4299e1;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.toggle-switch:hover .toggle-switch__thumb[data-v-5b16b9d3] {
|
.toggle-switch:hover .toggle-switch__thumb[data-v-f65566fd] {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-container[data-v-d7fd504d] {
|
.search-container[data-v-83f6f852] {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.search-icon[data-v-d7fd504d] {
|
.search-icon[data-v-83f6f852] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1847,7 +1855,7 @@ to { transform: rotate(360deg);
|
|||||||
color: var(--fg-color, #fff);
|
color: var(--fg-color, #fff);
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.search-input[data-v-d7fd504d] {
|
.search-input[data-v-83f6f852] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 32px;
|
padding: 8px 32px;
|
||||||
background: var(--comfy-input-bg, #333);
|
background: var(--comfy-input-bg, #333);
|
||||||
@@ -1858,14 +1866,14 @@ to { transform: rotate(360deg);
|
|||||||
outline: none;
|
outline: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.search-input[data-v-d7fd504d]:focus {
|
.search-input[data-v-83f6f852]:focus {
|
||||||
border-color: rgba(66, 153, 225, 0.6);
|
border-color: rgba(66, 153, 225, 0.6);
|
||||||
}
|
}
|
||||||
.search-input[data-v-d7fd504d]::placeholder {
|
.search-input[data-v-83f6f852]::placeholder {
|
||||||
color: var(--fg-color, #fff);
|
color: var(--fg-color, #fff);
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
.clear-button[data-v-d7fd504d] {
|
.clear-button[data-v-83f6f852] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1882,22 +1890,22 @@ to { transform: rotate(360deg);
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
transition: opacity 0.15s;
|
transition: opacity 0.15s;
|
||||||
}
|
}
|
||||||
.clear-button[data-v-d7fd504d]:hover {
|
.clear-button[data-v-83f6f852]:hover {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
.clear-button svg[data-v-d7fd504d] {
|
.clear-button svg[data-v-83f6f852] {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
color: var(--fg-color, #fff);
|
color: var(--fg-color, #fff);
|
||||||
}
|
}
|
||||||
.lora-list[data-v-d7fd504d] {
|
.lora-list[data-v-83f6f852] {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.lora-item[data-v-d7fd504d] {
|
.lora-item[data-v-83f6f852] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
@@ -1907,14 +1915,14 @@ to { transform: rotate(360deg);
|
|||||||
transition: all 0.15s;
|
transition: all 0.15s;
|
||||||
border-left: 3px solid transparent;
|
border-left: 3px solid transparent;
|
||||||
}
|
}
|
||||||
.lora-item[data-v-d7fd504d]:hover {
|
.lora-item[data-v-83f6f852]:hover {
|
||||||
background: rgba(66, 153, 225, 0.15);
|
background: rgba(66, 153, 225, 0.15);
|
||||||
}
|
}
|
||||||
.lora-item.active[data-v-d7fd504d] {
|
.lora-item.active[data-v-83f6f852] {
|
||||||
background: rgba(66, 153, 225, 0.25);
|
background: rgba(66, 153, 225, 0.25);
|
||||||
border-left-color: rgba(66, 153, 225, 0.8);
|
border-left-color: rgba(66, 153, 225, 0.8);
|
||||||
}
|
}
|
||||||
.lora-index[data-v-d7fd504d] {
|
.lora-index[data-v-83f6f852] {
|
||||||
font-family: 'SF Mono', 'Roboto Mono', monospace;
|
font-family: 'SF Mono', 'Roboto Mono', monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: rgba(226, 232, 240, 0.5);
|
color: rgba(226, 232, 240, 0.5);
|
||||||
@@ -1922,7 +1930,7 @@ to { transform: rotate(360deg);
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
.lora-name[data-v-d7fd504d] {
|
.lora-name[data-v-83f6f852] {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--fg-color, #fff);
|
color: var(--fg-color, #fff);
|
||||||
@@ -1930,7 +1938,7 @@ to { transform: rotate(360deg);
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.current-badge[data-v-d7fd504d] {
|
.current-badge[data-v-83f6f852] {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
background: rgba(66, 153, 225, 0.3);
|
background: rgba(66, 153, 225, 0.3);
|
||||||
@@ -1939,7 +1947,14 @@ to { transform: rotate(360deg);
|
|||||||
color: rgba(191, 219, 254, 1);
|
color: rgba(191, 219, 254, 1);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.no-results[data-v-d7fd504d] {
|
.lora-item.no-lora-item .lora-name[data-v-83f6f852] {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgba(226, 232, 240, 0.6);
|
||||||
|
}
|
||||||
|
.lora-item.no-lora-item:hover .lora-name[data-v-83f6f852] {
|
||||||
|
color: rgba(226, 232, 240, 0.8);
|
||||||
|
}
|
||||||
|
.no-results[data-v-83f6f852] {
|
||||||
padding: 32px 20px;
|
padding: 32px 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--fg-color, #fff);
|
color: var(--fg-color, #fff);
|
||||||
@@ -1947,7 +1962,7 @@ to { transform: rotate(360deg);
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lora-cycler-widget[data-v-f09f4e8b] {
|
.lora-cycler-widget[data-v-f6dad3ae] {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
background: rgba(40, 44, 52, 0.6);
|
background: rgba(40, 44, 52, 0.6);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -13108,6 +13123,9 @@ const _hoisted_26 = { class: "setting-section" };
|
|||||||
const _hoisted_27 = { class: "section-header-with-toggle" };
|
const _hoisted_27 = { class: "section-header-with-toggle" };
|
||||||
const _hoisted_28 = { class: "setting-label" };
|
const _hoisted_28 = { class: "setting-label" };
|
||||||
const _hoisted_29 = ["aria-checked"];
|
const _hoisted_29 = ["aria-checked"];
|
||||||
|
const _hoisted_30 = { class: "setting-section" };
|
||||||
|
const _hoisted_31 = { class: "section-header-with-toggle" };
|
||||||
|
const _hoisted_32 = ["aria-checked"];
|
||||||
const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
||||||
__name: "LoraCyclerSettingsView",
|
__name: "LoraCyclerSettingsView",
|
||||||
props: {
|
props: {
|
||||||
@@ -13124,9 +13142,11 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
isPaused: { type: Boolean },
|
isPaused: { type: Boolean },
|
||||||
isPauseDisabled: { type: Boolean },
|
isPauseDisabled: { type: Boolean },
|
||||||
isWorkflowExecuting: { type: Boolean },
|
isWorkflowExecuting: { type: Boolean },
|
||||||
executingRepeatStep: {}
|
executingRepeatStep: {},
|
||||||
|
includeNoLora: { type: Boolean },
|
||||||
|
isNoLora: { type: Boolean }
|
||||||
},
|
},
|
||||||
emits: ["update:currentIndex", "update:modelStrength", "update:clipStrength", "update:useCustomClipRange", "update:repeatCount", "toggle-pause", "reset-index", "open-lora-selector"],
|
emits: ["update:currentIndex", "update:modelStrength", "update:clipStrength", "update:useCustomClipRange", "update:repeatCount", "update:includeNoLora", "toggle-pause", "reset-index", "open-lora-selector"],
|
||||||
setup(__props, { emit: __emit }) {
|
setup(__props, { emit: __emit }) {
|
||||||
const props = __props;
|
const props = __props;
|
||||||
const emit2 = __emit;
|
const emit2 = __emit;
|
||||||
@@ -13172,7 +13192,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
};
|
};
|
||||||
return (_ctx, _cache) => {
|
return (_ctx, _cache) => {
|
||||||
return openBlock(), createElementBlock("div", _hoisted_1$4, [
|
return openBlock(), createElementBlock("div", _hoisted_1$4, [
|
||||||
_cache[21] || (_cache[21] = createBaseVNode("div", { class: "settings-header" }, [
|
_cache[24] || (_cache[24] = createBaseVNode("div", { class: "settings-header" }, [
|
||||||
createBaseVNode("h3", { class: "settings-title" }, "CYCLER SETTINGS")
|
createBaseVNode("h3", { class: "settings-title" }, "CYCLER SETTINGS")
|
||||||
], -1)),
|
], -1)),
|
||||||
createBaseVNode("div", _hoisted_2$3, [
|
createBaseVNode("div", _hoisted_2$3, [
|
||||||
@@ -13185,11 +13205,11 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
}, [
|
}, [
|
||||||
createBaseVNode("span", _hoisted_3$3, toDisplayString(__props.isWorkflowExecuting ? "Using LoRA:" : "Next LoRA:"), 1),
|
createBaseVNode("span", _hoisted_3$3, toDisplayString(__props.isWorkflowExecuting ? "Using LoRA:" : "Next LoRA:"), 1),
|
||||||
createBaseVNode("span", {
|
createBaseVNode("span", {
|
||||||
class: normalizeClass(["progress-name clickable", { disabled: __props.isPauseDisabled }]),
|
class: normalizeClass(["progress-name clickable", { disabled: __props.isPauseDisabled, "no-lora": __props.isNoLora }]),
|
||||||
title: __props.currentLoraFilename
|
title: __props.currentLoraFilename
|
||||||
}, [
|
}, [
|
||||||
createTextVNode(toDisplayString(__props.currentLoraName || "None") + " ", 1),
|
createTextVNode(toDisplayString(__props.currentLoraName || "None") + " ", 1),
|
||||||
_cache[11] || (_cache[11] = createBaseVNode("svg", {
|
_cache[12] || (_cache[12] = createBaseVNode("svg", {
|
||||||
class: "selector-icon",
|
class: "selector-icon",
|
||||||
viewBox: "0 0 24 24",
|
viewBox: "0 0 24 24",
|
||||||
fill: "currentColor"
|
fill: "currentColor"
|
||||||
@@ -13200,7 +13220,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
], 2),
|
], 2),
|
||||||
createBaseVNode("div", _hoisted_5$1, [
|
createBaseVNode("div", _hoisted_5$1, [
|
||||||
createBaseVNode("span", _hoisted_6$1, toDisplayString(__props.currentIndex), 1),
|
createBaseVNode("span", _hoisted_6$1, toDisplayString(__props.currentIndex), 1),
|
||||||
_cache[12] || (_cache[12] = createBaseVNode("span", { class: "progress-separator" }, "/", -1)),
|
_cache[13] || (_cache[13] = createBaseVNode("span", { class: "progress-separator" }, "/", -1)),
|
||||||
createBaseVNode("span", _hoisted_7$1, toDisplayString(__props.totalCount), 1),
|
createBaseVNode("span", _hoisted_7$1, toDisplayString(__props.totalCount), 1),
|
||||||
__props.repeatCount > 1 ? (openBlock(), createElementBlock("div", _hoisted_8, [
|
__props.repeatCount > 1 ? (openBlock(), createElementBlock("div", _hoisted_8, [
|
||||||
createBaseVNode("div", _hoisted_9, [
|
createBaseVNode("div", _hoisted_9, [
|
||||||
@@ -13217,7 +13237,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
createBaseVNode("div", _hoisted_11, [
|
createBaseVNode("div", _hoisted_11, [
|
||||||
createBaseVNode("div", _hoisted_12, [
|
createBaseVNode("div", _hoisted_12, [
|
||||||
createBaseVNode("div", _hoisted_13, [
|
createBaseVNode("div", _hoisted_13, [
|
||||||
_cache[13] || (_cache[13] = createBaseVNode("label", { class: "control-group-label" }, "Starting Index", -1)),
|
_cache[14] || (_cache[14] = createBaseVNode("label", { class: "control-group-label" }, "Starting Index", -1)),
|
||||||
createBaseVNode("div", _hoisted_14, [
|
createBaseVNode("div", _hoisted_14, [
|
||||||
createBaseVNode("input", {
|
createBaseVNode("input", {
|
||||||
type: "number",
|
type: "number",
|
||||||
@@ -13239,7 +13259,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
createBaseVNode("div", _hoisted_17, [
|
createBaseVNode("div", _hoisted_17, [
|
||||||
_cache[15] || (_cache[15] = createBaseVNode("label", { class: "control-group-label" }, "Repeat", -1)),
|
_cache[16] || (_cache[16] = createBaseVNode("label", { class: "control-group-label" }, "Repeat", -1)),
|
||||||
createBaseVNode("div", _hoisted_18, [
|
createBaseVNode("div", _hoisted_18, [
|
||||||
createBaseVNode("input", {
|
createBaseVNode("input", {
|
||||||
type: "number",
|
type: "number",
|
||||||
@@ -13257,7 +13277,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
}, ["stop"])),
|
}, ["stop"])),
|
||||||
title: "Each LoRA will be used this many times before moving to the next"
|
title: "Each LoRA will be used this many times before moving to the next"
|
||||||
}, null, 40, _hoisted_19),
|
}, null, 40, _hoisted_19),
|
||||||
_cache[14] || (_cache[14] = createBaseVNode("span", { class: "repeat-suffix" }, "×", -1))
|
_cache[15] || (_cache[15] = createBaseVNode("span", { class: "repeat-suffix" }, "×", -1))
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
createBaseVNode("div", _hoisted_20, [
|
createBaseVNode("div", _hoisted_20, [
|
||||||
@@ -13267,9 +13287,9 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
onClick: _cache[6] || (_cache[6] = ($event) => _ctx.$emit("toggle-pause")),
|
onClick: _cache[6] || (_cache[6] = ($event) => _ctx.$emit("toggle-pause")),
|
||||||
title: __props.isPauseDisabled ? "Cannot pause while prompts are queued" : __props.isPaused ? "Continue iteration" : "Pause iteration"
|
title: __props.isPauseDisabled ? "Cannot pause while prompts are queued" : __props.isPaused ? "Continue iteration" : "Pause iteration"
|
||||||
}, [
|
}, [
|
||||||
__props.isPaused ? (openBlock(), createElementBlock("svg", _hoisted_22, [..._cache[16] || (_cache[16] = [
|
__props.isPaused ? (openBlock(), createElementBlock("svg", _hoisted_22, [..._cache[17] || (_cache[17] = [
|
||||||
createBaseVNode("path", { d: "M8 5v14l11-7z" }, null, -1)
|
createBaseVNode("path", { d: "M8 5v14l11-7z" }, null, -1)
|
||||||
])])) : (openBlock(), createElementBlock("svg", _hoisted_23, [..._cache[17] || (_cache[17] = [
|
])])) : (openBlock(), createElementBlock("svg", _hoisted_23, [..._cache[18] || (_cache[18] = [
|
||||||
createBaseVNode("path", { d: "M6 4h4v16H6zm8 0h4v16h-4z" }, null, -1)
|
createBaseVNode("path", { d: "M6 4h4v16H6zm8 0h4v16h-4z" }, null, -1)
|
||||||
])]))
|
])]))
|
||||||
], 10, _hoisted_21),
|
], 10, _hoisted_21),
|
||||||
@@ -13277,7 +13297,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
class: "control-btn",
|
class: "control-btn",
|
||||||
onClick: _cache[7] || (_cache[7] = ($event) => _ctx.$emit("reset-index")),
|
onClick: _cache[7] || (_cache[7] = ($event) => _ctx.$emit("reset-index")),
|
||||||
title: "Reset to index 1"
|
title: "Reset to index 1"
|
||||||
}, [..._cache[18] || (_cache[18] = [
|
}, [..._cache[19] || (_cache[19] = [
|
||||||
createBaseVNode("svg", {
|
createBaseVNode("svg", {
|
||||||
viewBox: "0 0 24 24",
|
viewBox: "0 0 24 24",
|
||||||
fill: "currentColor",
|
fill: "currentColor",
|
||||||
@@ -13290,7 +13310,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
createBaseVNode("div", _hoisted_24, [
|
createBaseVNode("div", _hoisted_24, [
|
||||||
_cache[19] || (_cache[19] = createBaseVNode("label", { class: "setting-label" }, "Model Strength", -1)),
|
_cache[20] || (_cache[20] = createBaseVNode("label", { class: "setting-label" }, "Model Strength", -1)),
|
||||||
createBaseVNode("div", _hoisted_25, [
|
createBaseVNode("div", _hoisted_25, [
|
||||||
createVNode(SingleSlider, {
|
createVNode(SingleSlider, {
|
||||||
min: -10,
|
min: -10,
|
||||||
@@ -13312,7 +13332,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
role: "switch",
|
role: "switch",
|
||||||
"aria-checked": __props.useCustomClipRange,
|
"aria-checked": __props.useCustomClipRange,
|
||||||
title: "Use custom clip strength when enabled, otherwise use model strength"
|
title: "Use custom clip strength when enabled, otherwise use model strength"
|
||||||
}, [..._cache[20] || (_cache[20] = [
|
}, [..._cache[21] || (_cache[21] = [
|
||||||
createBaseVNode("span", { class: "toggle-switch__track" }, null, -1),
|
createBaseVNode("span", { class: "toggle-switch__track" }, null, -1),
|
||||||
createBaseVNode("span", { class: "toggle-switch__thumb" }, null, -1)
|
createBaseVNode("span", { class: "toggle-switch__thumb" }, null, -1)
|
||||||
])], 10, _hoisted_29)
|
])], 10, _hoisted_29)
|
||||||
@@ -13330,12 +13350,28 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|||||||
"onUpdate:value": _cache[10] || (_cache[10] = ($event) => _ctx.$emit("update:clipStrength", $event))
|
"onUpdate:value": _cache[10] || (_cache[10] = ($event) => _ctx.$emit("update:clipStrength", $event))
|
||||||
}, null, 8, ["value", "disabled"])
|
}, null, 8, ["value", "disabled"])
|
||||||
], 2)
|
], 2)
|
||||||
|
]),
|
||||||
|
createBaseVNode("div", _hoisted_30, [
|
||||||
|
createBaseVNode("div", _hoisted_31, [
|
||||||
|
_cache[23] || (_cache[23] = createBaseVNode("label", { class: "setting-label" }, ' Add "No LoRA" step ', -1)),
|
||||||
|
createBaseVNode("button", {
|
||||||
|
type: "button",
|
||||||
|
class: normalizeClass(["toggle-switch", { "toggle-switch--active": __props.includeNoLora }]),
|
||||||
|
onClick: _cache[11] || (_cache[11] = ($event) => _ctx.$emit("update:includeNoLora", !__props.includeNoLora)),
|
||||||
|
role: "switch",
|
||||||
|
"aria-checked": __props.includeNoLora,
|
||||||
|
title: "Add an iteration without LoRA for comparison"
|
||||||
|
}, [..._cache[22] || (_cache[22] = [
|
||||||
|
createBaseVNode("span", { class: "toggle-switch__track" }, null, -1),
|
||||||
|
createBaseVNode("span", { class: "toggle-switch__thumb" }, null, -1)
|
||||||
|
])], 10, _hoisted_32)
|
||||||
|
])
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const LoraCyclerSettingsView = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-5b16b9d3"]]);
|
const LoraCyclerSettingsView = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-f65566fd"]]);
|
||||||
const _hoisted_1$3 = { class: "search-container" };
|
const _hoisted_1$3 = { class: "search-container" };
|
||||||
const _hoisted_2$2 = { class: "lora-list" };
|
const _hoisted_2$2 = { class: "lora-list" };
|
||||||
const _hoisted_3$2 = ["onMouseenter", "onClick"];
|
const _hoisted_3$2 = ["onMouseenter", "onClick"];
|
||||||
@@ -13354,7 +13390,8 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
visible: { type: Boolean },
|
visible: { type: Boolean },
|
||||||
loraList: {},
|
loraList: {},
|
||||||
currentIndex: {}
|
currentIndex: {},
|
||||||
|
includeNoLora: { type: Boolean }
|
||||||
},
|
},
|
||||||
emits: ["close", "select"],
|
emits: ["close", "select"],
|
||||||
setup(__props, { emit: __emit }) {
|
setup(__props, { emit: __emit }) {
|
||||||
@@ -13364,7 +13401,8 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|||||||
const searchInputRef = ref(null);
|
const searchInputRef = ref(null);
|
||||||
let previewTooltip = null;
|
let previewTooltip = null;
|
||||||
const subtitleText = computed(() => {
|
const subtitleText = computed(() => {
|
||||||
const total = props.loraList.length;
|
const baseTotal = props.loraList.length;
|
||||||
|
const total = props.includeNoLora ? baseTotal + 1 : baseTotal;
|
||||||
const filtered = filteredList.value.length;
|
const filtered = filteredList.value.length;
|
||||||
if (filtered === total) {
|
if (filtered === total) {
|
||||||
return `Total: ${total} LoRA${total !== 1 ? "s" : ""}`;
|
return `Total: ${total} LoRA${total !== 1 ? "s" : ""}`;
|
||||||
@@ -13376,6 +13414,12 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|||||||
index: idx + 1,
|
index: idx + 1,
|
||||||
lora
|
lora
|
||||||
}));
|
}));
|
||||||
|
if (props.includeNoLora) {
|
||||||
|
list.push({
|
||||||
|
index: list.length + 1,
|
||||||
|
lora: { file_name: "No LoRA" }
|
||||||
|
});
|
||||||
|
}
|
||||||
if (!searchQuery.value.trim()) {
|
if (!searchQuery.value.trim()) {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -13497,7 +13541,10 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|||||||
(openBlock(true), createElementBlock(Fragment, null, renderList(filteredList.value, (item) => {
|
(openBlock(true), createElementBlock(Fragment, null, renderList(filteredList.value, (item) => {
|
||||||
return openBlock(), createElementBlock("div", {
|
return openBlock(), createElementBlock("div", {
|
||||||
key: item.index,
|
key: item.index,
|
||||||
class: normalizeClass(["lora-item", { active: __props.currentIndex === item.index }]),
|
class: normalizeClass(["lora-item", {
|
||||||
|
active: __props.currentIndex === item.index,
|
||||||
|
"no-lora-item": item.lora.file_name === "No LoRA"
|
||||||
|
}]),
|
||||||
onMouseenter: ($event) => showPreview(item.lora.file_name, $event),
|
onMouseenter: ($event) => showPreview(item.lora.file_name, $event),
|
||||||
onMouseleave: hidePreview,
|
onMouseleave: hidePreview,
|
||||||
onClick: ($event) => selectLora(item.index)
|
onClick: ($event) => selectLora(item.index)
|
||||||
@@ -13518,7 +13565,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const LoraListModal = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-d7fd504d"]]);
|
const LoraListModal = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-83f6f852"]]);
|
||||||
function useLoraCyclerState(widget) {
|
function useLoraCyclerState(widget) {
|
||||||
let isRestoring = false;
|
let isRestoring = false;
|
||||||
const currentIndex = ref(1);
|
const currentIndex = ref(1);
|
||||||
@@ -13537,6 +13584,7 @@ function useLoraCyclerState(widget) {
|
|||||||
const repeatUsed = ref(0);
|
const repeatUsed = ref(0);
|
||||||
const displayRepeatUsed = ref(0);
|
const displayRepeatUsed = ref(0);
|
||||||
const isPaused = ref(false);
|
const isPaused = ref(false);
|
||||||
|
const includeNoLora = ref(false);
|
||||||
const isWorkflowExecuting = ref(false);
|
const isWorkflowExecuting = ref(false);
|
||||||
const executingRepeatStep = ref(0);
|
const executingRepeatStep = ref(0);
|
||||||
const buildConfig = () => {
|
const buildConfig = () => {
|
||||||
@@ -13555,7 +13603,8 @@ function useLoraCyclerState(widget) {
|
|||||||
next_index: nextIndex.value,
|
next_index: nextIndex.value,
|
||||||
repeat_count: repeatCount.value,
|
repeat_count: repeatCount.value,
|
||||||
repeat_used: repeatUsed.value,
|
repeat_used: repeatUsed.value,
|
||||||
is_paused: isPaused.value
|
is_paused: isPaused.value,
|
||||||
|
include_no_lora: includeNoLora.value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -13572,7 +13621,8 @@ function useLoraCyclerState(widget) {
|
|||||||
next_index: nextIndex.value,
|
next_index: nextIndex.value,
|
||||||
repeat_count: repeatCount.value,
|
repeat_count: repeatCount.value,
|
||||||
repeat_used: repeatUsed.value,
|
repeat_used: repeatUsed.value,
|
||||||
is_paused: isPaused.value
|
is_paused: isPaused.value,
|
||||||
|
include_no_lora: includeNoLora.value
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const restoreFromConfig = (config) => {
|
const restoreFromConfig = (config) => {
|
||||||
@@ -13590,6 +13640,7 @@ function useLoraCyclerState(widget) {
|
|||||||
repeatCount.value = config.repeat_count ?? 1;
|
repeatCount.value = config.repeat_count ?? 1;
|
||||||
repeatUsed.value = config.repeat_used ?? 0;
|
repeatUsed.value = config.repeat_used ?? 0;
|
||||||
isPaused.value = config.is_paused ?? false;
|
isPaused.value = config.is_paused ?? false;
|
||||||
|
includeNoLora.value = config.include_no_lora ?? false;
|
||||||
} finally {
|
} finally {
|
||||||
isRestoring = false;
|
isRestoring = false;
|
||||||
}
|
}
|
||||||
@@ -13598,7 +13649,8 @@ function useLoraCyclerState(widget) {
|
|||||||
executionIndex.value = nextIndex.value;
|
executionIndex.value = nextIndex.value;
|
||||||
const current = executionIndex.value ?? currentIndex.value;
|
const current = executionIndex.value ?? currentIndex.value;
|
||||||
let next = current + 1;
|
let next = current + 1;
|
||||||
if (totalCount.value > 0 && next > totalCount.value) {
|
const effectiveTotalCount = includeNoLora.value ? totalCount.value + 1 : totalCount.value;
|
||||||
|
if (effectiveTotalCount > 0 && next > effectiveTotalCount) {
|
||||||
next = 1;
|
next = 1;
|
||||||
}
|
}
|
||||||
nextIndex.value = next;
|
nextIndex.value = next;
|
||||||
@@ -13606,7 +13658,8 @@ function useLoraCyclerState(widget) {
|
|||||||
const initializeNextIndex = () => {
|
const initializeNextIndex = () => {
|
||||||
if (nextIndex.value === null) {
|
if (nextIndex.value === null) {
|
||||||
let next = currentIndex.value + 1;
|
let next = currentIndex.value + 1;
|
||||||
if (totalCount.value > 0 && next > totalCount.value) {
|
const effectiveTotalCount = includeNoLora.value ? totalCount.value + 1 : totalCount.value;
|
||||||
|
if (effectiveTotalCount > 0 && next > effectiveTotalCount) {
|
||||||
next = 1;
|
next = 1;
|
||||||
}
|
}
|
||||||
nextIndex.value = next;
|
nextIndex.value = next;
|
||||||
@@ -13684,7 +13737,8 @@ function useLoraCyclerState(widget) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const setIndex = (index) => {
|
const setIndex = (index) => {
|
||||||
if (index >= 1 && index <= totalCount.value) {
|
const effectiveTotalCount = includeNoLora.value ? totalCount.value + 1 : totalCount.value;
|
||||||
|
if (index >= 1 && index <= effectiveTotalCount) {
|
||||||
currentIndex.value = index;
|
currentIndex.value = index;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -13714,7 +13768,8 @@ function useLoraCyclerState(widget) {
|
|||||||
currentLoraFilename,
|
currentLoraFilename,
|
||||||
repeatCount,
|
repeatCount,
|
||||||
repeatUsed,
|
repeatUsed,
|
||||||
isPaused
|
isPaused,
|
||||||
|
includeNoLora
|
||||||
], () => {
|
], () => {
|
||||||
widget.value = buildConfig();
|
widget.value = buildConfig();
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
@@ -13736,6 +13791,7 @@ function useLoraCyclerState(widget) {
|
|||||||
repeatUsed,
|
repeatUsed,
|
||||||
displayRepeatUsed,
|
displayRepeatUsed,
|
||||||
isPaused,
|
isPaused,
|
||||||
|
includeNoLora,
|
||||||
isWorkflowExecuting,
|
isWorkflowExecuting,
|
||||||
executingRepeatStep,
|
executingRepeatStep,
|
||||||
// Computed
|
// Computed
|
||||||
@@ -13772,6 +13828,21 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
const isMounted = ref(false);
|
const isMounted = ref(false);
|
||||||
const isModalOpen = ref(false);
|
const isModalOpen = ref(false);
|
||||||
const cachedLoraList = ref([]);
|
const cachedLoraList = ref([]);
|
||||||
|
const displayTotalCount = computed(() => {
|
||||||
|
const baseCount = state.totalCount.value;
|
||||||
|
return state.includeNoLora.value ? baseCount + 1 : baseCount;
|
||||||
|
});
|
||||||
|
const displayLoraName = computed(() => {
|
||||||
|
const currentIndex = state.currentIndex.value;
|
||||||
|
const totalCount = state.totalCount.value;
|
||||||
|
if (state.includeNoLora.value && currentIndex === totalCount + 1) {
|
||||||
|
return "No LoRA";
|
||||||
|
}
|
||||||
|
return state.currentLoraName.value;
|
||||||
|
});
|
||||||
|
const isNoLora = computed(() => {
|
||||||
|
return state.includeNoLora.value && state.currentIndex.value === state.totalCount.value + 1;
|
||||||
|
});
|
||||||
const getPoolConfig = () => {
|
const getPoolConfig = () => {
|
||||||
if (props.node.getPoolConfig) {
|
if (props.node.getPoolConfig) {
|
||||||
return props.node.getPoolConfig();
|
return props.node.getPoolConfig();
|
||||||
@@ -13779,7 +13850,13 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
const updateDisplayFromLoraList = (loraList, index) => {
|
const updateDisplayFromLoraList = (loraList, index) => {
|
||||||
if (loraList.length > 0 && index > 0 && index <= loraList.length) {
|
const actualLoraCount = loraList.length;
|
||||||
|
if (state.includeNoLora.value && index === actualLoraCount + 1) {
|
||||||
|
state.currentLoraName.value = "No LoRA";
|
||||||
|
state.currentLoraFilename.value = "No LoRA";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (actualLoraCount > 0 && index > 0 && index <= actualLoraCount) {
|
||||||
const currentLora = loraList[index - 1];
|
const currentLora = loraList[index - 1];
|
||||||
if (currentLora) {
|
if (currentLora) {
|
||||||
state.currentLoraName.value = currentLora.file_name;
|
state.currentLoraName.value = currentLora.file_name;
|
||||||
@@ -13788,17 +13865,19 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleIndexUpdate = async (newIndex) => {
|
const handleIndexUpdate = async (newIndex) => {
|
||||||
|
const maxIndex = state.includeNoLora.value ? state.totalCount.value + 1 : state.totalCount.value;
|
||||||
|
const clampedIndex = Math.max(1, Math.min(newIndex, maxIndex || 1));
|
||||||
props.widget[HAS_EXECUTED] = false;
|
props.widget[HAS_EXECUTED] = false;
|
||||||
state.executionIndex.value = null;
|
state.executionIndex.value = null;
|
||||||
state.nextIndex.value = null;
|
state.nextIndex.value = null;
|
||||||
executionQueue.length = 0;
|
executionQueue.length = 0;
|
||||||
hasQueuedPrompts.value = false;
|
hasQueuedPrompts.value = false;
|
||||||
state.setIndex(newIndex);
|
state.setIndex(clampedIndex);
|
||||||
try {
|
try {
|
||||||
const poolConfig = getPoolConfig();
|
const poolConfig = getPoolConfig();
|
||||||
const loraList = await state.fetchCyclerList(poolConfig);
|
const loraList = await state.fetchCyclerList(poolConfig);
|
||||||
cachedLoraList.value = loraList;
|
cachedLoraList.value = loraList;
|
||||||
updateDisplayFromLoraList(loraList, newIndex);
|
updateDisplayFromLoraList(loraList, clampedIndex);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[LoraCyclerWidget] Error updating index:", error);
|
console.error("[LoraCyclerWidget] Error updating index:", error);
|
||||||
}
|
}
|
||||||
@@ -13817,6 +13896,12 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
state.repeatUsed.value = 0;
|
state.repeatUsed.value = 0;
|
||||||
state.displayRepeatUsed.value = 0;
|
state.displayRepeatUsed.value = 0;
|
||||||
};
|
};
|
||||||
|
const handleIncludeNoLoraChange = (newValue) => {
|
||||||
|
state.includeNoLora.value = newValue;
|
||||||
|
if (!newValue && state.currentIndex.value > state.totalCount.value) {
|
||||||
|
state.currentIndex.value = Math.max(1, state.totalCount.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
const handleTogglePause = () => {
|
const handleTogglePause = () => {
|
||||||
state.togglePause();
|
state.togglePause();
|
||||||
};
|
};
|
||||||
@@ -13995,8 +14080,8 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
return openBlock(), createElementBlock("div", _hoisted_1$2, [
|
return openBlock(), createElementBlock("div", _hoisted_1$2, [
|
||||||
createVNode(LoraCyclerSettingsView, {
|
createVNode(LoraCyclerSettingsView, {
|
||||||
"current-index": unref(state).currentIndex.value,
|
"current-index": unref(state).currentIndex.value,
|
||||||
"total-count": unref(state).totalCount.value,
|
"total-count": displayTotalCount.value,
|
||||||
"current-lora-name": unref(state).currentLoraName.value,
|
"current-lora-name": displayLoraName.value,
|
||||||
"current-lora-filename": unref(state).currentLoraFilename.value,
|
"current-lora-filename": unref(state).currentLoraFilename.value,
|
||||||
"model-strength": unref(state).modelStrength.value,
|
"model-strength": unref(state).modelStrength.value,
|
||||||
"clip-strength": unref(state).clipStrength.value,
|
"clip-strength": unref(state).clipStrength.value,
|
||||||
@@ -14009,27 +14094,31 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|||||||
"is-pause-disabled": hasQueuedPrompts.value,
|
"is-pause-disabled": hasQueuedPrompts.value,
|
||||||
"is-workflow-executing": unref(state).isWorkflowExecuting.value,
|
"is-workflow-executing": unref(state).isWorkflowExecuting.value,
|
||||||
"executing-repeat-step": unref(state).executingRepeatStep.value,
|
"executing-repeat-step": unref(state).executingRepeatStep.value,
|
||||||
|
"include-no-lora": unref(state).includeNoLora.value,
|
||||||
|
"is-no-lora": isNoLora.value,
|
||||||
"onUpdate:currentIndex": handleIndexUpdate,
|
"onUpdate:currentIndex": handleIndexUpdate,
|
||||||
"onUpdate:modelStrength": _cache[0] || (_cache[0] = ($event) => unref(state).modelStrength.value = $event),
|
"onUpdate:modelStrength": _cache[0] || (_cache[0] = ($event) => unref(state).modelStrength.value = $event),
|
||||||
"onUpdate:clipStrength": _cache[1] || (_cache[1] = ($event) => unref(state).clipStrength.value = $event),
|
"onUpdate:clipStrength": _cache[1] || (_cache[1] = ($event) => unref(state).clipStrength.value = $event),
|
||||||
"onUpdate:useCustomClipRange": handleUseCustomClipRangeChange,
|
"onUpdate:useCustomClipRange": handleUseCustomClipRangeChange,
|
||||||
"onUpdate:repeatCount": handleRepeatCountChange,
|
"onUpdate:repeatCount": handleRepeatCountChange,
|
||||||
|
"onUpdate:includeNoLora": handleIncludeNoLoraChange,
|
||||||
onTogglePause: handleTogglePause,
|
onTogglePause: handleTogglePause,
|
||||||
onResetIndex: handleResetIndex,
|
onResetIndex: handleResetIndex,
|
||||||
onOpenLoraSelector: _cache[2] || (_cache[2] = ($event) => isModalOpen.value = true)
|
onOpenLoraSelector: _cache[2] || (_cache[2] = ($event) => isModalOpen.value = true)
|
||||||
}, null, 8, ["current-index", "total-count", "current-lora-name", "current-lora-filename", "model-strength", "clip-strength", "use-custom-clip-range", "is-clip-strength-disabled", "is-loading", "repeat-count", "repeat-used", "is-paused", "is-pause-disabled", "is-workflow-executing", "executing-repeat-step"]),
|
}, null, 8, ["current-index", "total-count", "current-lora-name", "current-lora-filename", "model-strength", "clip-strength", "use-custom-clip-range", "is-clip-strength-disabled", "is-loading", "repeat-count", "repeat-used", "is-paused", "is-pause-disabled", "is-workflow-executing", "executing-repeat-step", "include-no-lora", "is-no-lora"]),
|
||||||
createVNode(LoraListModal, {
|
createVNode(LoraListModal, {
|
||||||
visible: isModalOpen.value,
|
visible: isModalOpen.value,
|
||||||
"lora-list": cachedLoraList.value,
|
"lora-list": cachedLoraList.value,
|
||||||
"current-index": unref(state).currentIndex.value,
|
"current-index": unref(state).currentIndex.value,
|
||||||
|
"include-no-lora": unref(state).includeNoLora.value,
|
||||||
onClose: _cache[3] || (_cache[3] = ($event) => isModalOpen.value = false),
|
onClose: _cache[3] || (_cache[3] = ($event) => isModalOpen.value = false),
|
||||||
onSelect: handleModalSelect
|
onSelect: handleModalSelect
|
||||||
}, null, 8, ["visible", "lora-list", "current-index"])
|
}, null, 8, ["visible", "lora-list", "current-index", "include-no-lora"])
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const LoraCyclerWidget = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-f09f4e8b"]]);
|
const LoraCyclerWidget = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-f6dad3ae"]]);
|
||||||
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",
|
||||||
@@ -14636,7 +14725,7 @@ const LORA_RANDOMIZER_WIDGET_MIN_WIDTH = 500;
|
|||||||
const LORA_RANDOMIZER_WIDGET_MIN_HEIGHT = 448;
|
const LORA_RANDOMIZER_WIDGET_MIN_HEIGHT = 448;
|
||||||
const LORA_RANDOMIZER_WIDGET_MAX_HEIGHT = LORA_RANDOMIZER_WIDGET_MIN_HEIGHT;
|
const LORA_RANDOMIZER_WIDGET_MAX_HEIGHT = LORA_RANDOMIZER_WIDGET_MIN_HEIGHT;
|
||||||
const LORA_CYCLER_WIDGET_MIN_WIDTH = 380;
|
const LORA_CYCLER_WIDGET_MIN_WIDTH = 380;
|
||||||
const LORA_CYCLER_WIDGET_MIN_HEIGHT = 314;
|
const LORA_CYCLER_WIDGET_MIN_HEIGHT = 344;
|
||||||
const LORA_CYCLER_WIDGET_MAX_HEIGHT = LORA_CYCLER_WIDGET_MIN_HEIGHT;
|
const LORA_CYCLER_WIDGET_MAX_HEIGHT = LORA_CYCLER_WIDGET_MIN_HEIGHT;
|
||||||
const JSON_DISPLAY_WIDGET_MIN_WIDTH = 300;
|
const JSON_DISPLAY_WIDGET_MIN_WIDTH = 300;
|
||||||
const JSON_DISPLAY_WIDGET_MIN_HEIGHT = 200;
|
const JSON_DISPLAY_WIDGET_MIN_HEIGHT = 200;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user