mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-22 05:32:12 -03:00
feat: add setting to include trigger words in LoRA syntax, update UI and functionality, fixes #268
This commit is contained in:
@@ -555,12 +555,6 @@ export class BaseModelApiClient {
|
||||
|
||||
async fetchModelRoots() {
|
||||
try {
|
||||
// For checkpoints, use the specific method that considers modelType
|
||||
// if (this.modelType === 'checkpoints') {
|
||||
// const pageState = this.getPageState();
|
||||
// return await this.fetchModelRoots(pageState.modelType || 'checkpoint');
|
||||
// }
|
||||
|
||||
const response = await fetch(this.apiConfig.endpoints.roots);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch ${this.apiConfig.config.displayName} roots`);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BaseContextMenu } from './BaseContextMenu.js';
|
||||
import { ModelContextMenuMixin } from './ModelContextMenuMixin.js';
|
||||
import { getModelApiClient, resetAndReload } from '../../api/modelApiFactory.js';
|
||||
import { copyToClipboard, sendLoraToWorkflow } from '../../utils/uiHelpers.js';
|
||||
import { copyLoraSyntax, sendLoraToWorkflow } from '../../utils/uiHelpers.js';
|
||||
import { showExcludeModal, showDeleteModal } from '../../utils/modalUtils.js';
|
||||
import { moveManager } from '../../managers/MoveManager.js';
|
||||
|
||||
@@ -37,7 +37,7 @@ export class LoraContextMenu extends BaseContextMenu {
|
||||
break;
|
||||
case 'copyname':
|
||||
// Generate and copy LoRA syntax
|
||||
this.copyLoraSyntax();
|
||||
copyLoraSyntax(this.currentCard);
|
||||
break;
|
||||
case 'sendappend':
|
||||
// Send LoRA to workflow (append mode)
|
||||
@@ -67,16 +67,6 @@ export class LoraContextMenu extends BaseContextMenu {
|
||||
}
|
||||
}
|
||||
|
||||
// Specific LoRA methods
|
||||
copyLoraSyntax() {
|
||||
const card = this.currentCard;
|
||||
const usageTips = JSON.parse(card.dataset.usage_tips || '{}');
|
||||
const strength = usageTips.strength || 1;
|
||||
const loraSyntax = `<lora:${card.dataset.file_name}:${strength}>`;
|
||||
|
||||
copyToClipboard(loraSyntax, 'LoRA syntax copied to clipboard');
|
||||
}
|
||||
|
||||
sendLoraToWorkflow(replaceMode) {
|
||||
const card = this.currentCard;
|
||||
const usageTips = JSON.parse(card.dataset.usage_tips || '{}');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { showToast, openCivitai, copyToClipboard, sendLoraToWorkflow, openExampleImagesFolder } from '../../utils/uiHelpers.js';
|
||||
import { showToast, openCivitai, copyToClipboard, copyLoraSyntax, sendLoraToWorkflow, openExampleImagesFolder } from '../../utils/uiHelpers.js';
|
||||
import { state, getCurrentPageState } from '../../state/index.js';
|
||||
import { showModelModal } from './ModelModal.js';
|
||||
import { toggleShowcase } from './showcase/ShowcaseView.js';
|
||||
@@ -166,10 +166,7 @@ function handleSendToWorkflow(card, replaceMode, modelType) {
|
||||
|
||||
function handleCopyAction(card, modelType) {
|
||||
if (modelType === MODEL_TYPES.LORA) {
|
||||
const usageTips = JSON.parse(card.dataset.usage_tips || '{}');
|
||||
const strength = usageTips.strength || 1;
|
||||
const loraSyntax = `<lora:${card.dataset.file_name}:${strength}>`;
|
||||
copyToClipboard(loraSyntax, 'LoRA syntax copied to clipboard');
|
||||
copyLoraSyntax(card);
|
||||
} else if (modelType === MODEL_TYPES.CHECKPOINT) {
|
||||
// Checkpoint copy functionality - copy checkpoint name
|
||||
const checkpointName = card.dataset.file_name;
|
||||
|
||||
@@ -87,6 +87,11 @@ export class SettingsManager {
|
||||
if (state.global.settings.default_embedding_root === undefined) {
|
||||
state.global.settings.default_embedding_root = '';
|
||||
}
|
||||
|
||||
// Set default for includeTriggerWords if undefined
|
||||
if (state.global.settings.includeTriggerWords === undefined) {
|
||||
state.global.settings.includeTriggerWords = false;
|
||||
}
|
||||
}
|
||||
|
||||
async syncSettingsToBackendIfNeeded() {
|
||||
@@ -213,6 +218,12 @@ export class SettingsManager {
|
||||
this.updatePathTemplatePreview();
|
||||
}
|
||||
|
||||
// Set include trigger words setting
|
||||
const includeTriggerWordsCheckbox = document.getElementById('includeTriggerWords');
|
||||
if (includeTriggerWordsCheckbox) {
|
||||
includeTriggerWordsCheckbox.checked = state.global.settings.includeTriggerWords || false;
|
||||
}
|
||||
|
||||
// Load base model path mappings
|
||||
this.loadBaseModelMappings();
|
||||
|
||||
@@ -562,6 +573,8 @@ export class SettingsManager {
|
||||
state.global.settings.autoDownloadExampleImages = value;
|
||||
} else if (settingKey === 'compact_mode') {
|
||||
state.global.settings.compactMode = value;
|
||||
} else if (settingKey === 'include_trigger_words') {
|
||||
state.global.settings.includeTriggerWords = value;
|
||||
} else {
|
||||
// For any other settings that might be added in the future
|
||||
state.global.settings[settingKey] = value;
|
||||
@@ -587,9 +600,9 @@ export class SettingsManager {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to save setting');
|
||||
}
|
||||
|
||||
showToast(`Settings updated: ${settingKey.replace(/_/g, ' ')}`, 'success');
|
||||
}
|
||||
|
||||
showToast(`Settings updated: ${settingKey.replace(/_/g, ' ')}`, 'success');
|
||||
|
||||
// Apply frontend settings immediately
|
||||
this.applyFrontendSettings();
|
||||
@@ -603,7 +616,7 @@ export class SettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (settingKey === 'show_only_sfw') {
|
||||
if (settingKey === 'show_only_sfw' || settingKey === 'blur_mature_content') {
|
||||
this.reloadContent();
|
||||
}
|
||||
|
||||
@@ -785,20 +798,13 @@ export class SettingsManager {
|
||||
} else if (this.currentPage === 'checkpoints') {
|
||||
// Reload the checkpoints without updating folders
|
||||
await resetAndReload(false);
|
||||
} else if (this.currentPage === 'embeddings') {
|
||||
// Reload the embeddings without updating folders
|
||||
await resetAndReload(false);
|
||||
}
|
||||
}
|
||||
|
||||
applyFrontendSettings() {
|
||||
// Apply blur setting to existing content
|
||||
const blurSetting = state.global.settings.blurMatureContent;
|
||||
document.querySelectorAll('.model-card[data-nsfw="true"] .card-image').forEach(img => {
|
||||
if (blurSetting) {
|
||||
img.classList.add('nsfw-blur');
|
||||
} else {
|
||||
img.classList.remove('nsfw-blur');
|
||||
}
|
||||
});
|
||||
|
||||
// Apply autoplay setting to existing videos in card previews
|
||||
const autoplayOnHover = state.global.settings.autoplayOnHover;
|
||||
document.querySelectorAll('.card-preview video').forEach(video => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getCurrentPageState } from '../state/index.js';
|
||||
import { state, getCurrentPageState } from '../state/index.js';
|
||||
import { getStorageItem, setStorageItem } from './storageHelpers.js';
|
||||
import { NODE_TYPE_ICONS, DEFAULT_NODE_COLOR } from './constants.js';
|
||||
|
||||
@@ -285,6 +285,76 @@ export function getNSFWLevelName(level) {
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
export function copyLoraSyntax(card) {
|
||||
const usageTips = JSON.parse(card.dataset.usage_tips || "{}");
|
||||
const strength = usageTips.strength || 1;
|
||||
const baseSyntax = `<lora:${card.dataset.file_name}:${strength}>`;
|
||||
|
||||
// Check if trigger words should be included
|
||||
const includeTriggerWords = state.global.settings.includeTriggerWords;
|
||||
|
||||
if (!includeTriggerWords) {
|
||||
copyToClipboard(baseSyntax, "LoRA syntax copied to clipboard");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get trigger words from metadata
|
||||
const meta = card.dataset.meta ? JSON.parse(card.dataset.meta) : null;
|
||||
const trainedWords = meta?.trainedWords;
|
||||
|
||||
if (
|
||||
!trainedWords ||
|
||||
!Array.isArray(trainedWords) ||
|
||||
trainedWords.length === 0
|
||||
) {
|
||||
copyToClipboard(
|
||||
baseSyntax,
|
||||
"LoRA syntax copied to clipboard (no trigger words found)"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let finalSyntax = baseSyntax;
|
||||
|
||||
if (trainedWords.length === 1) {
|
||||
// Single group: append trigger words to the same line
|
||||
const triggers = trainedWords[0]
|
||||
.split(",")
|
||||
.map((word) => word.trim())
|
||||
.filter((word) => word);
|
||||
if (triggers.length > 0) {
|
||||
finalSyntax = `${baseSyntax}, ${triggers.join(", ")}`;
|
||||
}
|
||||
copyToClipboard(
|
||||
finalSyntax,
|
||||
"LoRA syntax with trigger words copied to clipboard"
|
||||
);
|
||||
} else {
|
||||
// Multiple groups: format with separators
|
||||
const groups = trainedWords
|
||||
.map((group) => {
|
||||
const triggers = group
|
||||
.split(",")
|
||||
.map((word) => word.trim())
|
||||
.filter((word) => word);
|
||||
return triggers.join(", ");
|
||||
})
|
||||
.filter((group) => group);
|
||||
|
||||
if (groups.length > 0) {
|
||||
// Use separator between all groups except the first
|
||||
finalSyntax = baseSyntax + ", " + groups[0];
|
||||
for (let i = 1; i < groups.length; i++) {
|
||||
finalSyntax += `\n${"-".repeat(17)}\n${groups[i]}`;
|
||||
}
|
||||
}
|
||||
copyToClipboard(
|
||||
finalSyntax,
|
||||
"LoRA syntax with trigger word groups copied to clipboard"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends LoRA syntax to the active ComfyUI workflow
|
||||
* @param {string} loraSyntax - The LoRA syntax to send
|
||||
|
||||
@@ -308,6 +308,28 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Misc. Section -->
|
||||
<div class="settings-section">
|
||||
<h3>Misc.</h3>
|
||||
<div class="setting-item">
|
||||
<div class="setting-row">
|
||||
<div class="setting-info">
|
||||
<label for="includeTriggerWords">Include Trigger Words in LoRA Syntax</label>
|
||||
</div>
|
||||
<div class="setting-control">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="includeTriggerWords"
|
||||
onchange="settingsManager.saveToggleSetting('includeTriggerWords', 'include_trigger_words')">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-help">
|
||||
Include trained trigger words when copying LoRA syntax to clipboard
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user