fillter history fix
This commit is contained in:
parent
06cf2a6954
commit
ac7303588f
2 changed files with 130 additions and 63 deletions
|
|
@ -3,33 +3,97 @@ import { extractMetadataFromBlob } from './metadata.js';
|
||||||
|
|
||||||
const FILTER_STORAGE_KEY = 'gemini-app-history-filter';
|
const FILTER_STORAGE_KEY = 'gemini-app-history-filter';
|
||||||
const SEARCH_STORAGE_KEY = 'gemini-app-history-search';
|
const SEARCH_STORAGE_KEY = 'gemini-app-history-search';
|
||||||
|
const FAVORITES_STORAGE_KEY = 'gemini-app-history-favorites';
|
||||||
const SOURCE_STORAGE_KEY = 'gemini-app-history-source';
|
const SOURCE_STORAGE_KEY = 'gemini-app-history-source';
|
||||||
const VALID_SOURCES = ['generated', 'uploads'];
|
const VALID_SOURCES = ['generated', 'uploads'];
|
||||||
|
const DEFAULT_STATE = {
|
||||||
|
filter: 'all',
|
||||||
|
search: '',
|
||||||
|
favorites: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
function createStateMap(fallback) {
|
||||||
|
return {
|
||||||
|
generated: fallback,
|
||||||
|
uploads: fallback,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseStoredMap(key, fallback) {
|
||||||
|
const defaultMap = createStateMap(fallback);
|
||||||
|
let raw;
|
||||||
|
try {
|
||||||
|
raw = localStorage.getItem(key);
|
||||||
|
if (!raw) return defaultMap;
|
||||||
|
const parsed = JSON.parse(raw);
|
||||||
|
if (parsed && typeof parsed === 'object') {
|
||||||
|
return {
|
||||||
|
generated: parsed.generated ?? parsed.default ?? fallback,
|
||||||
|
uploads: parsed.uploads ?? parsed.default ?? fallback,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Backward compatibility: single value string or number
|
||||||
|
return createStateMap(raw);
|
||||||
|
} catch (e) {
|
||||||
|
// If parsing failed but raw exists, treat it as a primitive single value
|
||||||
|
if (raw) {
|
||||||
|
return createStateMap(raw);
|
||||||
|
}
|
||||||
|
console.warn('Failed to load history state', e);
|
||||||
|
return defaultMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function persistStateMap(key, map) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(key, JSON.stringify(map));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to save history state', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function createGallery({ galleryGrid, onSelect }) {
|
export function createGallery({ galleryGrid, onSelect }) {
|
||||||
let currentFilter = 'all';
|
let currentFilter = DEFAULT_STATE.filter;
|
||||||
let searchQuery = '';
|
let searchQuery = DEFAULT_STATE.search;
|
||||||
let currentSource = 'generated';
|
let currentSource = 'generated';
|
||||||
let allImages = [];
|
let allImages = [];
|
||||||
let favorites = [];
|
let favorites = [];
|
||||||
let showOnlyFavorites = false; // New toggle state
|
let showOnlyFavorites = DEFAULT_STATE.favorites;
|
||||||
|
const stateBySource = {
|
||||||
|
generated: { ...DEFAULT_STATE },
|
||||||
|
uploads: { ...DEFAULT_STATE },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load saved filter, search and favorites from localStorage (per source)
|
||||||
|
const savedFilters = parseStoredMap(FILTER_STORAGE_KEY, DEFAULT_STATE.filter);
|
||||||
|
const savedSearches = parseStoredMap(SEARCH_STORAGE_KEY, DEFAULT_STATE.search);
|
||||||
|
const savedFavorites = parseStoredMap(FAVORITES_STORAGE_KEY, DEFAULT_STATE.favorites);
|
||||||
|
|
||||||
|
stateBySource.generated.filter = savedFilters.generated;
|
||||||
|
stateBySource.uploads.filter = savedFilters.uploads;
|
||||||
|
stateBySource.generated.search = savedSearches.generated;
|
||||||
|
stateBySource.uploads.search = savedSearches.uploads;
|
||||||
|
stateBySource.generated.favorites = savedFavorites.generated;
|
||||||
|
stateBySource.uploads.favorites = savedFavorites.uploads;
|
||||||
|
|
||||||
// Load saved filter and search from localStorage
|
|
||||||
try {
|
try {
|
||||||
const savedFilter = localStorage.getItem(FILTER_STORAGE_KEY);
|
|
||||||
if (savedFilter) currentFilter = savedFilter;
|
|
||||||
|
|
||||||
const savedSearch = localStorage.getItem(SEARCH_STORAGE_KEY);
|
|
||||||
if (savedSearch) searchQuery = savedSearch;
|
|
||||||
|
|
||||||
const savedSource = localStorage.getItem(SOURCE_STORAGE_KEY);
|
const savedSource = localStorage.getItem(SOURCE_STORAGE_KEY);
|
||||||
if (savedSource && VALID_SOURCES.includes(savedSource)) {
|
if (savedSource && VALID_SOURCES.includes(savedSource)) {
|
||||||
currentSource = savedSource;
|
currentSource = savedSource;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Failed to load history filter/search', e);
|
console.warn('Failed to load history source', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applySourceState(source) {
|
||||||
|
const state = stateBySource[source] || DEFAULT_STATE;
|
||||||
|
currentFilter = state.filter ?? DEFAULT_STATE.filter;
|
||||||
|
searchQuery = state.search ?? DEFAULT_STATE.search;
|
||||||
|
showOnlyFavorites = state.favorites ?? DEFAULT_STATE.favorites;
|
||||||
|
}
|
||||||
|
|
||||||
|
applySourceState(currentSource);
|
||||||
|
|
||||||
// Load favorites from backend
|
// Load favorites from backend
|
||||||
async function loadFavorites() {
|
async function loadFavorites() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -306,32 +370,35 @@ export function createGallery({ galleryGrid, onSelect }) {
|
||||||
function setFilter(filterType) {
|
function setFilter(filterType) {
|
||||||
if (currentFilter === filterType) return;
|
if (currentFilter === filterType) return;
|
||||||
currentFilter = filterType;
|
currentFilter = filterType;
|
||||||
|
stateBySource[currentSource].filter = filterType;
|
||||||
|
|
||||||
// Save to localStorage
|
persistStateMap(FILTER_STORAGE_KEY, {
|
||||||
try {
|
generated: stateBySource.generated.filter,
|
||||||
localStorage.setItem(FILTER_STORAGE_KEY, filterType);
|
uploads: stateBySource.uploads.filter,
|
||||||
} catch (e) {
|
});
|
||||||
console.warn('Failed to save history filter', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderGallery();
|
renderGallery();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSearch(query) {
|
function setSearch(query) {
|
||||||
searchQuery = query || '';
|
searchQuery = query || '';
|
||||||
|
stateBySource[currentSource].search = searchQuery;
|
||||||
|
|
||||||
// Save to localStorage
|
persistStateMap(SEARCH_STORAGE_KEY, {
|
||||||
try {
|
generated: stateBySource.generated.search,
|
||||||
localStorage.setItem(SEARCH_STORAGE_KEY, searchQuery);
|
uploads: stateBySource.uploads.search,
|
||||||
} catch (e) {
|
});
|
||||||
console.warn('Failed to save history search', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderGallery();
|
renderGallery();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFavorites() {
|
function toggleFavorites() {
|
||||||
showOnlyFavorites = !showOnlyFavorites;
|
showOnlyFavorites = !showOnlyFavorites;
|
||||||
|
stateBySource[currentSource].favorites = showOnlyFavorites;
|
||||||
|
persistStateMap(FAVORITES_STORAGE_KEY, {
|
||||||
|
generated: stateBySource.generated.favorites,
|
||||||
|
uploads: stateBySource.uploads.favorites,
|
||||||
|
});
|
||||||
renderGallery();
|
renderGallery();
|
||||||
return showOnlyFavorites;
|
return showOnlyFavorites;
|
||||||
}
|
}
|
||||||
|
|
@ -345,16 +412,21 @@ export function createGallery({ galleryGrid, onSelect }) {
|
||||||
console.warn('Failed to save history source', e);
|
console.warn('Failed to save history source', e);
|
||||||
}
|
}
|
||||||
if (resetFilters) {
|
if (resetFilters) {
|
||||||
currentFilter = 'all';
|
stateBySource[currentSource] = { ...DEFAULT_STATE };
|
||||||
showOnlyFavorites = false;
|
persistStateMap(FILTER_STORAGE_KEY, {
|
||||||
searchQuery = '';
|
generated: stateBySource.generated.filter,
|
||||||
try {
|
uploads: stateBySource.uploads.filter,
|
||||||
localStorage.setItem(FILTER_STORAGE_KEY, currentFilter);
|
});
|
||||||
localStorage.setItem(SEARCH_STORAGE_KEY, searchQuery);
|
persistStateMap(SEARCH_STORAGE_KEY, {
|
||||||
} catch (e) {
|
generated: stateBySource.generated.search,
|
||||||
console.warn('Failed to reset history filters', e);
|
uploads: stateBySource.uploads.search,
|
||||||
}
|
});
|
||||||
|
persistStateMap(FAVORITES_STORAGE_KEY, {
|
||||||
|
generated: stateBySource.generated.favorites,
|
||||||
|
uploads: stateBySource.uploads.favorites,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
applySourceState(currentSource);
|
||||||
return load();
|
return load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,6 +448,11 @@ export function createGallery({ galleryGrid, onSelect }) {
|
||||||
|
|
||||||
function setFavoritesActive(active) {
|
function setFavoritesActive(active) {
|
||||||
showOnlyFavorites = Boolean(active);
|
showOnlyFavorites = Boolean(active);
|
||||||
|
stateBySource[currentSource].favorites = showOnlyFavorites;
|
||||||
|
persistStateMap(FAVORITES_STORAGE_KEY, {
|
||||||
|
generated: stateBySource.generated.favorites,
|
||||||
|
uploads: stateBySource.uploads.favorites,
|
||||||
|
});
|
||||||
renderGallery();
|
renderGallery();
|
||||||
return showOnlyFavorites;
|
return showOnlyFavorites;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1701,6 +1701,24 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
const historySourceBtns = document.querySelectorAll('.history-source-btn');
|
const historySourceBtns = document.querySelectorAll('.history-source-btn');
|
||||||
const initialSource = gallery.getCurrentSource ? gallery.getCurrentSource() : 'generated';
|
const initialSource = gallery.getCurrentSource ? gallery.getCurrentSource() : 'generated';
|
||||||
|
|
||||||
|
function syncHistoryControlsFromGallery() {
|
||||||
|
const activeFilter = gallery.getCurrentFilter ? gallery.getCurrentFilter() : 'all';
|
||||||
|
historyFilterBtns.forEach(btn => {
|
||||||
|
if (btn.classList.contains('history-favorites-btn')) return;
|
||||||
|
const isActive = btn.dataset.filter === activeFilter;
|
||||||
|
btn.classList.toggle('active', isActive);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (historyFavoritesBtn && gallery.isFavoritesActive) {
|
||||||
|
historyFavoritesBtn.classList.toggle('active', gallery.isFavoritesActive());
|
||||||
|
}
|
||||||
|
|
||||||
|
const historySearchInputEl = document.getElementById('history-search-input');
|
||||||
|
if (historySearchInputEl && gallery.getSearchQuery) {
|
||||||
|
historySearchInputEl.value = gallery.getSearchQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
historySourceBtns.forEach(btn => {
|
historySourceBtns.forEach(btn => {
|
||||||
const isActive = btn.dataset.source === initialSource;
|
const isActive = btn.dataset.source === initialSource;
|
||||||
btn.classList.toggle('active', isActive);
|
btn.classList.toggle('active', isActive);
|
||||||
|
|
@ -1713,41 +1731,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
b.classList.toggle('active', active);
|
b.classList.toggle('active', active);
|
||||||
b.setAttribute('aria-pressed', String(active));
|
b.setAttribute('aria-pressed', String(active));
|
||||||
});
|
});
|
||||||
await gallery.setSource(targetSource, { resetFilters: true });
|
await gallery.setSource(targetSource, { resetFilters: false });
|
||||||
|
syncHistoryControlsFromGallery();
|
||||||
// Reset filters UI to show all when switching source
|
|
||||||
historyFilterBtns.forEach(b => {
|
|
||||||
if (!b.classList.contains('history-favorites-btn')) {
|
|
||||||
b.classList.toggle('active', b.dataset.filter === 'all');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Disable favorites toggle on source change
|
|
||||||
if (historyFavoritesBtn) {
|
|
||||||
historyFavoritesBtn.classList.remove('active');
|
|
||||||
}
|
|
||||||
if (gallery.setFavoritesActive) {
|
|
||||||
gallery.setFavoritesActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear search box
|
|
||||||
const historySearchInputEl = document.getElementById('history-search-input');
|
|
||||||
if (historySearchInputEl) {
|
|
||||||
historySearchInputEl.value = '';
|
|
||||||
}
|
|
||||||
if (gallery.setSearchQuery) {
|
|
||||||
gallery.setSearchQuery('');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set initial active state based on saved filter
|
// Set initial active state based on saved filter
|
||||||
const currentFilter = gallery.getCurrentFilter();
|
syncHistoryControlsFromGallery();
|
||||||
historyFilterBtns.forEach(btn => {
|
|
||||||
if (btn.dataset.filter === currentFilter && !btn.classList.contains('history-favorites-btn')) {
|
|
||||||
btn.classList.add('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle favorites button as toggle
|
// Handle favorites button as toggle
|
||||||
if (historyFavoritesBtn) {
|
if (historyFavoritesBtn) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue