diff --git a/static/pwa.js b/static/pwa.js index 82119bb..3214f4d 100644 --- a/static/pwa.js +++ b/static/pwa.js @@ -4,6 +4,7 @@ const Pwa = (() => { const DISMISS_KEY = "pwa-hint-dismissed"; let deferredPrompt = null; let refreshInstallHint = null; + let hintBound = false; function isStandalone() { return window.matchMedia("(display-mode: standalone)").matches @@ -42,27 +43,64 @@ const Pwa = (() => { return "pwa.hintDesktop"; } - function setupInstallHint() { - if (isStandalone()) return null; - if (localStorage.getItem(DISMISS_KEY) === "1") return null; + function hideHint(hint, { persist = true } = {}) { + if (persist) { + try { + localStorage.setItem(DISMISS_KEY, "1"); + } catch { + /* private mode with storage blocked – still hide for this session */ + } + } + hint.hidden = true; + hint.classList.add("is-dismissed"); + } + function showHint(hint) { + hint.hidden = false; + hint.classList.remove("is-dismissed"); + } + + function bindHintActions(hint) { + if (hintBound) return; + hintBound = true; + + hint.addEventListener("click", (event) => { + if (event.target.closest(".pwa-hint-dismiss")) { + event.preventDefault(); + hideHint(hint); + } + }); + } + + function setupInstallHint() { const hint = document.getElementById("pwa-install-hint"); if (!hint) return null; + bindHintActions(hint); + + if (isStandalone()) { + hideHint(hint, { persist: false }); + return null; + } + if (localStorage.getItem(DISMISS_KEY) === "1") { + hideHint(hint, { persist: false }); + return null; + } + const body = document.getElementById("pwa-hint-body"); const installBtn = document.getElementById("pwa-install-btn"); - const dismissBtn = document.getElementById("pwa-hint-dismiss"); + const dismissBtn = hint.querySelector(".pwa-hint-dismiss"); const updateHintText = () => { const title = hint.querySelector("[data-i18n='pwa.hintTitle']"); if (title) title.textContent = t("pwa.hintTitle"); if (body && !deferredPrompt) body.textContent = t(platformHintKey()); if (body && deferredPrompt) body.textContent = t("pwa.hintBody"); - if (dismissBtn) dismissBtn.title = t("actions.dismiss"); + if (dismissBtn) dismissBtn.setAttribute("aria-label", t("actions.dismiss")); if (installBtn && !installBtn.hidden) installBtn.textContent = t("pwa.install"); }; - hint.hidden = false; + showHint(hint); updateHintText(); window.addEventListener("beforeinstallprompt", (e) => { @@ -73,11 +111,6 @@ const Pwa = (() => { updateHintText(); }); - dismissBtn?.addEventListener("click", () => { - localStorage.setItem(DISMISS_KEY, "1"); - hint.hidden = true; - }); - installBtn?.addEventListener("click", async () => { if (!deferredPrompt) return; deferredPrompt.prompt(); @@ -86,7 +119,7 @@ const Pwa = (() => { installBtn.hidden = true; if (outcome === "accepted") { if (body) body.textContent = t("pwa.installed"); - setTimeout(() => { hint.hidden = true; }, 3000); + setTimeout(() => { hideHint(hint); }, 3000); } else { updateHintText(); } @@ -96,8 +129,8 @@ const Pwa = (() => { } async function init() { - await registerServiceWorker(); refreshInstallHint = setupInstallHint(); + await registerServiceWorker(); } function refreshHint() { diff --git a/static/style.css b/static/style.css index 316617a..6c25f9b 100644 --- a/static/style.css +++ b/static/style.css @@ -856,8 +856,9 @@ body.inv-chart-modal-open { } /* PWA install hint */ -.pwa-hint[hidden] { - display: none; +.pwa-hint[hidden], +.pwa-hint.is-dismissed { + display: none !important; } .pwa-hint { @@ -898,6 +899,25 @@ body.inv-chart-modal-open { flex-shrink: 0; } +.pwa-hint-dismiss { + background: none; + border: none; + color: var(--text-muted); + font-size: 1.25rem; + line-height: 1; + cursor: pointer; + min-width: 32px; + min-height: 32px; + padding: 4px; + border-radius: 6px; + flex-shrink: 0; +} + +.pwa-hint-dismiss:hover { + color: var(--text); + background: var(--bg-hover); +} + .landing-card .pwa-hint { margin-top: 8px; margin-bottom: 0; diff --git a/static/sw.js b/static/sw.js index b14e77f..62a01a9 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,4 +1,4 @@ -const CACHE = "if-viewer-static-v4"; +const CACHE = "if-viewer-static-v5"; const ASSETS = [ "/static/style.css", "/static/favicon.svg", diff --git a/templates/_pwa_hint.html b/templates/_pwa_hint.html index 224c799..a8095f8 100644 --- a/templates/_pwa_hint.html +++ b/templates/_pwa_hint.html @@ -5,6 +5,6 @@