From 73d01da94eecb245942999199bfa32b63d4e9a03 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 15 Apr 2025 10:35:50 +0800 Subject: [PATCH] feat: Enhance model preview version management with localStorage support --- static/js/api/baseModelApi.js | 18 +++++++---- static/js/components/CheckpointCard.js | 5 +++- static/js/components/LoraCard.js | 4 ++- static/js/state/index.js | 9 ++++-- static/js/utils/storageHelpers.js | 41 ++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/static/js/api/baseModelApi.js b/static/js/api/baseModelApi.js index befc0471..8471f1f8 100644 --- a/static/js/api/baseModelApi.js +++ b/static/js/api/baseModelApi.js @@ -2,7 +2,7 @@ import { state, getCurrentPageState } from '../state/index.js'; import { showToast } from '../utils/uiHelpers.js'; import { showDeleteModal, confirmDelete } from '../utils/modalUtils.js'; -import { getSessionItem } from '../utils/storageHelpers.js'; +import { getSessionItem, saveMapToStorage } from '../utils/storageHelpers.js'; /** * Shared functionality for handling models (loras and checkpoints) @@ -424,12 +424,20 @@ async function uploadPreview(filePath, file, modelType = 'lora') { const previewContainer = card.querySelector('.card-preview'); const oldPreview = previewContainer.querySelector('img, video'); - // For LoRA models, use timestamp to prevent caching - if (modelType === 'lora') { - state.previewVersions?.set(filePath, Date.now()); + // Get the current page's previewVersions Map based on model type + const pageType = modelType === 'checkpoint' ? 'checkpoints' : 'loras'; + const previewVersions = state.pages[pageType].previewVersions; + + // Update the version timestamp + const timestamp = Date.now(); + if (previewVersions) { + previewVersions.set(filePath, timestamp); + + // Save the updated Map to localStorage + const storageKey = modelType === 'checkpoint' ? 'checkpoint_preview_versions' : 'lora_preview_versions'; + saveMapToStorage(storageKey, previewVersions); } - const timestamp = Date.now(); const previewUrl = data.preview_url ? `${data.preview_url}?t=${timestamp}` : `/api/model/preview_image?path=${encodeURIComponent(filePath)}&t=${timestamp}`; diff --git a/static/js/components/CheckpointCard.js b/static/js/components/CheckpointCard.js index 0ff1271d..4984d2ca 100644 --- a/static/js/components/CheckpointCard.js +++ b/static/js/components/CheckpointCard.js @@ -44,7 +44,10 @@ export function createCheckpointCard(checkpoint) { // Determine preview URL const previewUrl = checkpoint.preview_url || '/loras_static/images/no-preview.png'; - const version = state.previewVersions ? state.previewVersions.get(checkpoint.file_path) : null; + + // Get the page-specific previewVersions map + const previewVersions = state.pages.checkpoints.previewVersions || new Map(); + const version = previewVersions.get(checkpoint.file_path); const versionedPreviewUrl = version ? `${previewUrl}?t=${version}` : previewUrl; // Determine NSFW warning text based on level diff --git a/static/js/components/LoraCard.js b/static/js/components/LoraCard.js index 86737b59..fa5e8a0b 100644 --- a/static/js/components/LoraCard.js +++ b/static/js/components/LoraCard.js @@ -44,7 +44,9 @@ export function createLoraCard(lora) { card.classList.add('selected'); } - const version = state.previewVersions.get(lora.file_path); + // Get the page-specific previewVersions map + const previewVersions = state.pages.loras.previewVersions || new Map(); + const version = previewVersions.get(lora.file_path); const previewUrl = lora.preview_url || '/loras_static/images/no-preview.png'; const versionedPreviewUrl = version ? `${previewUrl}?t=${version}` : previewUrl; diff --git a/static/js/state/index.js b/static/js/state/index.js index 63a9b446..a498e57b 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -1,5 +1,5 @@ // Create the new hierarchical state structure -import { getStorageItem } from '../utils/storageHelpers.js'; +import { getStorageItem, getMapFromStorage } from '../utils/storageHelpers.js'; // Load settings from localStorage or use defaults const savedSettings = getStorageItem('settings', { @@ -7,6 +7,10 @@ const savedSettings = getStorageItem('settings', { show_only_sfw: false }); +// Load preview versions from localStorage +const loraPreviewVersions = getMapFromStorage('lora_preview_versions'); +const checkpointPreviewVersions = getMapFromStorage('checkpoint_preview_versions'); + export const state = { // Global state global: { @@ -23,7 +27,7 @@ export const state = { hasMore: true, sortBy: 'name', activeFolder: null, - previewVersions: new Map(), + previewVersions: loraPreviewVersions, searchManager: null, searchOptions: { filename: true, @@ -66,6 +70,7 @@ export const state = { hasMore: true, sortBy: 'name', activeFolder: null, + previewVersions: checkpointPreviewVersions, searchManager: null, searchOptions: { filename: true, diff --git a/static/js/utils/storageHelpers.js b/static/js/utils/storageHelpers.js index 24e602bb..050d16ee 100644 --- a/static/js/utils/storageHelpers.js +++ b/static/js/utils/storageHelpers.js @@ -171,4 +171,45 @@ export function migrateStorageItems() { localStorage.setItem(STORAGE_PREFIX + 'migration_completed', 'true'); console.log('Lora Manager: Storage migration completed'); +} + +/** + * Save a Map to localStorage + * @param {string} key - The localStorage key + * @param {Map} map - The Map to save + */ +export function saveMapToStorage(key, map) { + if (!(map instanceof Map)) { + console.error('Cannot save non-Map object:', map); + return; + } + + try { + const prefixedKey = STORAGE_PREFIX + key; + // Convert Map to array of entries and save as JSON + const entries = Array.from(map.entries()); + localStorage.setItem(prefixedKey, JSON.stringify(entries)); + } catch (error) { + console.error(`Error saving Map to localStorage (${key}):`, error); + } +} + +/** + * Load a Map from localStorage + * @param {string} key - The localStorage key + * @returns {Map} - The loaded Map or a new empty Map + */ +export function getMapFromStorage(key) { + try { + const prefixedKey = STORAGE_PREFIX + key; + const data = localStorage.getItem(prefixedKey); + if (!data) return new Map(); + + // Parse JSON and convert back to Map + const entries = JSON.parse(data); + return new Map(entries); + } catch (error) { + console.error(`Error loading Map from localStorage (${key}):`, error); + return new Map(); + } } \ No newline at end of file