diff options
Diffstat (limited to 'src/app.js')
| -rw-r--r-- | src/app.js | 40 |
1 files changed, 37 insertions, 3 deletions
@@ -600,7 +600,7 @@ function imageViewer() { // mounted viewer: morphing can replace handlers with a new render's ones. document.querySelector('.lightbox')?.remove(); document.documentElement.classList.remove('no-scroll'); - goBack(() => { ui.lightbox = null; }); + closeLayer('lightbox'); }; // A tap on the picture closes it at every zoom level; gestures are filtered // by attachZoom before this click handler runs. @@ -702,7 +702,7 @@ function attachZoom(box, img, { wheel = true } = {}) { }, { passive: false }); } if (typeof window !== 'undefined') { - window.addEventListener('keydown', (e) => { if (e.key === 'Escape' && ui.lightbox) goBack(() => { ui.lightbox = null; }); }); + window.addEventListener('keydown', (e) => { if (e.key === 'Escape' && ui.lightbox) closeLayer('lightbox'); }); // Enter walks the Send flow: from an amount (or any field) it presses the // screen's main button — Review, Pay, Send — and with nothing focused it // presses it again, so amount ⏎ reviews and ⏎ again confirms. A held key @@ -1031,11 +1031,23 @@ window.addEventListener('popstate', (e) => { snap.screen = 'wallet'; snap.tab = ui.tab ?? null; try { history.replaceState({ nav: snap, i: st && typeof st.i === 'number' ? st.i : navIndex }, ''); } catch {} } + let corrected = false; + if (layerClose) { + const want = layerClose.expect; + clearTimeout(layerClose.timer); + layerClose = null; + if (navSig(snap) !== navSig(want)) { + snap = want; + corrected = true; + try { history.replaceState({ nav: snap, i: st && typeof st.i === 'number' ? st.i : navIndex }, '', navUrl(snap)); } catch {} + } + } restoringHistory = true; try { for (const f of NAV_FIELDS) ui[f] = (f === 'profEdit' || f === 'feedEdit') && snap[f] ? structuredClone(snap[f]) : f in snap ? snap[f] : null; if (st && typeof st.i === 'number') navIndex = st.i; else { const i = navStack.findIndex((s) => navSig(s) === navSig(snap)); if (i >= 0) navIndex = i; } + if (corrected && navIndex >= 0) navStack[navIndex] = snap; render(); } finally { restoringHistory = false; @@ -1050,6 +1062,28 @@ function goBack(toParent) { if (navIndex > 0) history.back(); else { toParent(); render(); } } +// Close something laid over the page (the media pager, the lightbox): Back, +// so the browser's Back doesn't reopen it — but landing on the page that +// was under it, whatever the entry Back reaches says. The entry under isn't +// always that page (after the app was reloaded in the background the +// browser's older entries are still there, or entries merged at boot), and +// blind Back walked off to the wallet, the chat list. That entry becomes the +// page under the layer. No Back to take (nothing of ours under it): shut in place. +let layerClose = null; // { expect: the snapshot to land on, timer } +function closeLayer(field) { + const cur = navStack[navIndex] || navSnapshot(); + const expect = { ...navSnapshot(), [field]: null }; + if (navIndex > 0 && cur) { + clearTimeout(layerClose && layerClose.timer); + // (the layer stays up until Back lands, as before; no popstate in time: + // a Back that went nowhere — shut where we are) + layerClose = { expect, timer: setTimeout(() => { if (layerClose && layerClose.expect === expect) { layerClose = null; ui[field] = null; render(); } }, 600) }; + history.back(); + return; + } + ui[field] = null; + render(); +} // Whether an in-app Back has anywhere of ours to go. A page opened straight // from a link has nothing under it; its Back would invent a parent. const canGoBack = () => navIndex > 0; @@ -6236,7 +6270,7 @@ async function importSnapshotFile(e) { // sits just before boot so every helper it captures is defined; the hooks are // only invoked at runtime (first render happens after loadLocale below). const ctx = { - h, ui, render, wallet, toast, copy, copyBtn, pasteBtn, blankSend, goBack, canGoBack, goHome, openExternal, showSend, + h, ui, render, wallet, toast, copy, copyBtn, pasteBtn, blankSend, goBack, canGoBack, closeLayer, goHome, openExternal, showSend, openWalletSettings: (view) => openWalletSettings(view), // one page of the Settings hub, from anywhere (Notifications' gear) openSettingsPage: (page) => { clearFeatureNav(); ui.screen = 'wallet'; ui.tab = 'settings'; ui.settingsPage = page; render(); try { window.scrollTo(0, 0); } catch {} }, |
