From 4a9f6764d982fab35bb1fb37b1a31b91aa5f2f0d Mon Sep 17 00:00:00 2001 From: phamhungd Date: Sat, 29 Nov 2025 21:58:12 +0700 Subject: [PATCH] fix --- static/modules/gallery.js | 137 ++++++++++++++++++++++---------------- static/script.js | 24 +++---- 2 files changed, 90 insertions(+), 71 deletions(-) diff --git a/static/modules/gallery.js b/static/modules/gallery.js index b99e730..e7cfd71 100644 --- a/static/modules/gallery.js +++ b/static/modules/gallery.js @@ -1,35 +1,69 @@ import { withCacheBuster } from './utils.js'; import { extractMetadataFromBlob } from './metadata.js'; -const FILTER_STORAGE_KEY = 'gemini-app-history-filter'; -const SEARCH_STORAGE_KEY = 'gemini-app-history-search'; +const GALLERY_STATE_KEY = 'gemini-app-gallery-state'; +const FILTER_STORAGE_KEY = 'gemini-app-history-filter'; // legacy (single-state) +const SEARCH_STORAGE_KEY = 'gemini-app-history-search'; // legacy (single-state) const SOURCE_STORAGE_KEY = 'gemini-app-history-source'; const VALID_SOURCES = ['generated', 'uploads']; export function createGallery({ galleryGrid, onSelect }) { - let currentFilter = 'all'; - let searchQuery = ''; let currentSource = 'generated'; let allImages = []; let favorites = []; - let showOnlyFavorites = false; // New toggle state + let perSourceState = { + generated: { filter: 'all', search: '', favoritesOnly: false }, + uploads: { filter: 'all', search: '', favoritesOnly: false }, + }; - // Load saved filter and search from localStorage + const persistState = () => { + try { + localStorage.setItem(GALLERY_STATE_KEY, JSON.stringify({ + sourceState: perSourceState, + source: currentSource, + })); + } catch (e) { + console.warn('Failed to persist gallery state', e); + } + }; + + // Load saved state (with legacy fallback) try { - const savedFilter = localStorage.getItem(FILTER_STORAGE_KEY); - if (savedFilter) currentFilter = savedFilter; - - const savedSearch = localStorage.getItem(SEARCH_STORAGE_KEY); - if (savedSearch) searchQuery = savedSearch; + const saved = localStorage.getItem(GALLERY_STATE_KEY); + if (saved) { + const parsed = JSON.parse(saved); + if (parsed?.sourceState) { + perSourceState = { + generated: { filter: 'all', search: '', favoritesOnly: false, ...(parsed.sourceState.generated || {}) }, + uploads: { filter: 'all', search: '', favoritesOnly: false, ...(parsed.sourceState.uploads || {}) }, + }; + } + if (parsed?.source && VALID_SOURCES.includes(parsed.source)) { + currentSource = parsed.source; + } + } else { + // Legacy fallback (single state) + const savedFilter = localStorage.getItem(FILTER_STORAGE_KEY); + const savedSearch = localStorage.getItem(SEARCH_STORAGE_KEY); + if (savedFilter) perSourceState.generated.filter = savedFilter; + if (savedSearch) perSourceState.generated.search = savedSearch; + } const savedSource = localStorage.getItem(SOURCE_STORAGE_KEY); if (savedSource && VALID_SOURCES.includes(savedSource)) { currentSource = savedSource; } } catch (e) { - console.warn('Failed to load history filter/search', e); + console.warn('Failed to load gallery state', e); } + const getState = (source = currentSource) => { + if (!perSourceState[source]) { + perSourceState[source] = { filter: 'all', search: '', favoritesOnly: false }; + } + return perSourceState[source]; + }; + // Load favorites from backend async function loadFavorites() { try { @@ -118,27 +152,29 @@ export function createGallery({ galleryGrid, onSelect }) { } function matchesSearch(imageUrl) { - if (!searchQuery) return true; + const { search } = getState(); + if (!search) return true; const filename = imageUrl.split('/').pop().split('?')[0]; - return filename.toLowerCase().includes(searchQuery.toLowerCase()); + return filename.toLowerCase().includes(search.toLowerCase()); } function shouldShowImage(imageUrl) { + const state = getState(); // First check text search if (!matchesSearch(imageUrl)) return false; // Check favorites toggle - if enabled, only show favorites - if (showOnlyFavorites && !isFavorite(imageUrl)) { + if (state.favoritesOnly && !isFavorite(imageUrl)) { return false; } // Then check date filter - if (currentFilter === 'all') return true; + if (state.filter === 'all') return true; const timestamp = getFileTimestamp(imageUrl); - if (!timestamp) return currentFilter === 'all'; + if (!timestamp) return state.filter === 'all'; - switch (currentFilter) { + switch (state.filter) { case 'today': return isToday(timestamp); case 'week': @@ -305,35 +341,33 @@ export function createGallery({ galleryGrid, onSelect }) { function setFilter(filterType) { if (currentFilter === filterType) return; - currentFilter = filterType; - - // Save to localStorage - try { - localStorage.setItem(FILTER_STORAGE_KEY, filterType); - } catch (e) { - console.warn('Failed to save history filter', e); - } - + const state = getState(); + state.filter = filterType; + persistState(); renderGallery(); } function setSearch(query) { - searchQuery = query || ''; - - // Save to localStorage - try { - localStorage.setItem(SEARCH_STORAGE_KEY, searchQuery); - } catch (e) { - console.warn('Failed to save history search', e); - } - + const state = getState(); + state.search = query || ''; + persistState(); renderGallery(); } function toggleFavorites() { - showOnlyFavorites = !showOnlyFavorites; + const state = getState(); + state.favoritesOnly = !state.favoritesOnly; + persistState(); renderGallery(); - return showOnlyFavorites; + return state.favoritesOnly; + } + + function setFavoritesActive(active) { + const state = getState(); + state.favoritesOnly = Boolean(active); + persistState(); + renderGallery(); + return state.favoritesOnly; } function setSource(source, { resetFilters = false } = {}) { @@ -345,25 +379,22 @@ export function createGallery({ galleryGrid, onSelect }) { console.warn('Failed to save history source', e); } if (resetFilters) { - currentFilter = 'all'; - showOnlyFavorites = false; - searchQuery = ''; - try { - localStorage.setItem(FILTER_STORAGE_KEY, currentFilter); - localStorage.setItem(SEARCH_STORAGE_KEY, searchQuery); - } catch (e) { - console.warn('Failed to reset history filters', e); - } + const state = getState(); + state.filter = 'all'; + state.favoritesOnly = false; + state.search = ''; + persistState(); } + persistState(); return load(); } function getCurrentFilter() { - return currentFilter; + return getState().filter; } function getSearchQuery() { - return searchQuery; + return getState().search; } function getCurrentSource() { @@ -371,13 +402,7 @@ export function createGallery({ galleryGrid, onSelect }) { } function isFavoritesActive() { - return showOnlyFavorites; - } - - function setFavoritesActive(active) { - showOnlyFavorites = Boolean(active); - renderGallery(); - return showOnlyFavorites; + return getState().favoritesOnly; } function setSearchQuery(value) { diff --git a/static/script.js b/static/script.js index d48b1b6..62ea9a8 100644 --- a/static/script.js +++ b/static/script.js @@ -1713,30 +1713,24 @@ document.addEventListener('DOMContentLoaded', () => { b.classList.toggle('active', active); b.setAttribute('aria-pressed', String(active)); }); - await gallery.setSource(targetSource, { resetFilters: true }); + await gallery.setSource(targetSource, { resetFilters: false }); - // Reset filters UI to show all when switching source + // Sync UI with persisted state (filter, favorites, search) + const activeFilter = gallery.getCurrentFilter ? gallery.getCurrentFilter() : 'all'; historyFilterBtns.forEach(b => { if (!b.classList.contains('history-favorites-btn')) { - b.classList.toggle('active', b.dataset.filter === 'all'); + const isFilterActive = b.dataset.filter === activeFilter; + b.classList.toggle('active', isFilterActive); } }); - // Disable favorites toggle on source change - if (historyFavoritesBtn) { - historyFavoritesBtn.classList.remove('active'); - } - if (gallery.setFavoritesActive) { - gallery.setFavoritesActive(false); + if (historyFavoritesBtn && gallery.isFavoritesActive) { + historyFavoritesBtn.classList.toggle('active', gallery.isFavoritesActive()); } - // Clear search box const historySearchInputEl = document.getElementById('history-search-input'); - if (historySearchInputEl) { - historySearchInputEl.value = ''; - } - if (gallery.setSearchQuery) { - gallery.setSearchQuery(''); + if (historySearchInputEl && gallery.getSearchQuery) { + historySearchInputEl.value = gallery.getSearchQuery(); } }); });