Keep the page you're on in the address
Each page has an address (#filament, #printers, #collection/12), so a refresh or bookmark returns to it and Back/Forward move between pages. The search and filter bar is hidden on the Filament page, where it did nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
ff2b0bc11f
commit
2aff27cbdd
1 changed files with 32 additions and 2 deletions
|
|
@ -71,6 +71,7 @@ function startApp() {
|
||||||
document.getElementById('authScreen').style.display = 'none';
|
document.getElementById('authScreen').style.display = 'none';
|
||||||
document.querySelector('.container').style.display = '';
|
document.querySelector('.container').style.display = '';
|
||||||
if (!appStarted) { setupEventListeners(); appStarted = true; }
|
if (!appStarted) { setupEventListeners(); appStarted = true; }
|
||||||
|
selectedScope = scopeFromHash();
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,8 +461,9 @@ function scopeTitle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateScopeChrome() {
|
function updateScopeChrome() {
|
||||||
|
syncAddress(); // e.g. a deleted collection falling back to All Models
|
||||||
contentTitle.textContent = scopeTitle();
|
contentTitle.textContent = scopeTitle();
|
||||||
const panel = ['duplicates', 'ai', 'watch', 'printers'].includes(selectedScope); // pages without the model grid
|
const panel = ['duplicates', 'ai', 'watch', 'filament', 'printers'].includes(selectedScope); // pages without the model grid
|
||||||
document.getElementById('filterBar').hidden = panel;
|
document.getElementById('filterBar').hidden = panel;
|
||||||
document.querySelector('.view-options').hidden = panel;
|
document.querySelector('.view-options').hidden = panel;
|
||||||
emptyTrashBtn.hidden = !(selectedScope === 'trash' && trashModels.length);
|
emptyTrashBtn.hidden = !(selectedScope === 'trash' && trashModels.length);
|
||||||
|
|
@ -977,12 +979,40 @@ function setupEventListeners() {
|
||||||
document.getElementById('addFilesInput').addEventListener('change', handleAddFiles);
|
document.getElementById('addFilesInput').addEventListener('change', handleAddFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function selectScope(scope) {
|
// The page you're on lives in the address — #filament, #collection/12 — so a
|
||||||
|
// refresh or a bookmark comes back to it, and Back and Forward move between pages.
|
||||||
|
function scopeHash(scope) {
|
||||||
|
if (scope === 'all') return '';
|
||||||
|
return SPECIAL_SCOPES.includes(scope) ? `#${scope}` : `#collection/${scope}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scopeFromHash() {
|
||||||
|
const h = decodeURIComponent(location.hash.slice(1));
|
||||||
|
const collection = h.match(/^collection\/(\d+)$/);
|
||||||
|
if (collection) return collection[1];
|
||||||
|
return SPECIAL_SCOPES.includes(h) ? h : 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keeps the address in step with the page shown; `push` makes a Back step.
|
||||||
|
function syncAddress(push = false) {
|
||||||
|
const hash = scopeHash(String(selectedScope));
|
||||||
|
if (location.hash === hash || (!hash && !location.hash)) return;
|
||||||
|
history[push ? 'pushState' : 'replaceState'](null, '', `${location.pathname}${location.search}${hash}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectScope(scope, { push = true } = {}) {
|
||||||
selectedScope = scope;
|
selectedScope = scope;
|
||||||
|
syncAddress(push);
|
||||||
if (scope === 'trash') await loadTrash();
|
if (scope === 'trash') await loadTrash();
|
||||||
renderModels();
|
renderModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener('popstate', () => {
|
||||||
|
if (!appStarted) return;
|
||||||
|
const scope = scopeFromHash();
|
||||||
|
if (String(scope) !== String(selectedScope)) selectScope(scope, { push: false });
|
||||||
|
});
|
||||||
|
|
||||||
// Tracks the file currently shown in the detail viewer (for thumbnail regen).
|
// Tracks the file currently shown in the detail viewer (for thumbnail regen).
|
||||||
let currentDetailFile = null;
|
let currentDetailFile = null;
|
||||||
let currentDetailThumb = null; // model image, used as a viewer fallback
|
let currentDetailThumb = null; // model image, used as a viewer fallback
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue