diff --git a/static/css/components/modal.css b/static/css/components/modal.css index 141713ef..b23264b1 100644 --- a/static/css/components/modal.css +++ b/static/css/components/modal.css @@ -341,8 +341,7 @@ body.modal-open { .setting-item { display: flex; - justify-content: space-between; - align-items: flex-start; + flex-direction: column; margin-bottom: var(--space-2); padding: var(--space-1); border-radius: var(--border-radius-xs); @@ -357,7 +356,8 @@ body.modal-open { } .setting-info { - flex: 1; + margin-bottom: var(--space-1); + width: 100%; } .setting-info label { @@ -367,7 +367,39 @@ body.modal-open { } .setting-control { - padding-left: var(--space-2); + width: 100%; + margin-bottom: var(--space-1); +} + +/* Select Control Styles */ +.select-control { + width: 100%; +} + +.select-control select { + width: 100%; + padding: 6px 10px; + border-radius: var(--border-radius-xs); + border: 1px solid var(--border-color); + background-color: var(--lora-surface); + color: var(--text-color); + font-size: 0.95em; +} + +/* Fix dark theme select dropdown text color */ +[data-theme="dark"] .select-control select { + background-color: rgba(30, 30, 30, 0.9); + color: var(--text-color); +} + +[data-theme="dark"] .select-control select option { + background-color: #2d2d2d; + color: var(--text-color); +} + +.select-control select:focus { + border-color: var(--lora-accent); + outline: none; } /* Toggle Switch */ diff --git a/static/js/managers/DownloadManager.js b/static/js/managers/DownloadManager.js index b6ccf89b..c0891bdf 100644 --- a/static/js/managers/DownloadManager.js +++ b/static/js/managers/DownloadManager.js @@ -3,7 +3,7 @@ import { showToast } from '../utils/uiHelpers.js'; import { LoadingManager } from './LoadingManager.js'; import { state } from '../state/index.js'; import { resetAndReload } from '../api/loraApi.js'; - +import { getStorageItem } from '../utils/storageHelpers.js'; export class DownloadManager { constructor() { this.currentVersion = null; @@ -246,6 +246,12 @@ export class DownloadManager { `` ).join(''); + // Set default lora root if available + const defaultRoot = getStorageItem('settings', {}).default_loras_root; + if (defaultRoot && data.roots.includes(defaultRoot)) { + loraRoot.value = defaultRoot; + } + // Initialize folder browser after loading roots this.initializeFolderBrowser(); } catch (error) { diff --git a/static/js/managers/ImportManager.js b/static/js/managers/ImportManager.js index b62e76f1..8a97880f 100644 --- a/static/js/managers/ImportManager.js +++ b/static/js/managers/ImportManager.js @@ -1,6 +1,7 @@ import { modalManager } from './ModalManager.js'; import { showToast } from '../utils/uiHelpers.js'; import { LoadingManager } from './LoadingManager.js'; +import { getStorageItem } from '../utils/storageHelpers.js'; export class ImportManager { constructor() { @@ -779,6 +780,12 @@ export class ImportManager { loraRoot.innerHTML = rootsData.roots.map(root => `` ).join(''); + + // Set default lora root if available + const defaultRoot = getStorageItem('settings', {}).default_loras_root; + if (defaultRoot && rootsData.roots.includes(defaultRoot)) { + loraRoot.value = defaultRoot; + } } // Fetch folders diff --git a/static/js/managers/MoveManager.js b/static/js/managers/MoveManager.js index 532066f5..b98eaa59 100644 --- a/static/js/managers/MoveManager.js +++ b/static/js/managers/MoveManager.js @@ -2,6 +2,7 @@ import { showToast } from '../utils/uiHelpers.js'; import { state } from '../state/index.js'; import { resetAndReload } from '../api/loraApi.js'; import { modalManager } from './ModalManager.js'; +import { getStorageItem } from '../utils/storageHelpers.js'; class MoveManager { constructor() { @@ -87,6 +88,12 @@ class MoveManager { `` ).join(''); + // Set default lora root if available + const defaultRoot = getStorageItem('settings', {}).default_loras_root; + if (defaultRoot && data.roots.includes(defaultRoot)) { + this.loraRootSelect.value = defaultRoot; + } + this.updatePathPreview(); modalManager.showModal('moveModal'); diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index fd14fe54..50617f52 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -53,7 +53,7 @@ export class SettingsManager { this.initialized = true; } - loadSettingsToUI() { + async loadSettingsToUI() { // Set frontend settings from state const blurMatureContentCheckbox = document.getElementById('blurMatureContent'); if (blurMatureContentCheckbox) { @@ -65,10 +65,52 @@ export class SettingsManager { // Sync with state (backend will set this via template) state.global.settings.show_only_sfw = showOnlySFWCheckbox.checked; } + + // Load default lora root + await this.loadLoraRoots(); // Backend settings are loaded from the template directly } + async loadLoraRoots() { + try { + const defaultLoraRootSelect = document.getElementById('defaultLoraRoot'); + if (!defaultLoraRootSelect) return; + + // Fetch lora roots + const response = await fetch('/api/lora-roots'); + if (!response.ok) { + throw new Error('Failed to fetch LoRA roots'); + } + + const data = await response.json(); + if (!data.roots || data.roots.length === 0) { + throw new Error('No LoRA roots found'); + } + + // Clear existing options except the first one (No Default) + const noDefaultOption = defaultLoraRootSelect.querySelector('option[value=""]'); + defaultLoraRootSelect.innerHTML = ''; + defaultLoraRootSelect.appendChild(noDefaultOption); + + // Add options for each root + data.roots.forEach(root => { + const option = document.createElement('option'); + option.value = root; + option.textContent = root; + defaultLoraRootSelect.appendChild(option); + }); + + // Set selected value from settings + const defaultRoot = state.global.settings.default_loras_root || ''; + defaultLoraRootSelect.value = defaultRoot; + + } catch (error) { + console.error('Error loading LoRA roots:', error); + showToast('Failed to load LoRA roots: ' + error.message, 'error'); + } + } + toggleSettings() { if (this.isOpen) { modalManager.closeModal('settingsModal'); @@ -81,14 +123,16 @@ export class SettingsManager { async saveSettings() { // Get frontend settings from UI const blurMatureContent = document.getElementById('blurMatureContent').checked; + const showOnlySFW = document.getElementById('showOnlySFW').checked; + const defaultLoraRoot = document.getElementById('defaultLoraRoot').value; // Get backend settings const apiKey = document.getElementById('civitaiApiKey').value; - const showOnlySFW = document.getElementById('showOnlySFW').checked; // Update frontend state and save to localStorage state.global.settings.blurMatureContent = blurMatureContent; state.global.settings.show_only_sfw = showOnlySFW; + state.global.settings.default_loras_root = defaultLoraRoot; // Save settings to localStorage setStorageItem('settings', state.global.settings); diff --git a/templates/components/modals.html b/templates/components/modals.html index 3fdf148d..7b82f4bc 100644 --- a/templates/components/modals.html +++ b/templates/components/modals.html @@ -66,6 +66,26 @@ + + +
+

Folder Settings

+ +
+
+ +
+
+ +
+
+ Set the default LoRA root directory for downloads, imports and moves +
+
+