diff --git a/index.html b/index.html index f7aa9f3..a49f98e 100644 --- a/index.html +++ b/index.html @@ -82,6 +82,7 @@ input,textarea{font:inherit;color:inherit} #stationSheet,#picker,#tapePick{z-index:6} #stationSheet{position:fixed;left:50%;bottom:0;transform:translateX(-50%);width:min(480px,100%);background:var(--card);border:1px solid var(--line);border-bottom:0;border-radius:18px 18px 0 0;padding:14px 14px calc(14px + env(safe-area-inset-bottom));z-index:6;box-shadow:0 -20px 60px rgba(0,0,0,.6)} #stationSheet h4{font:600 10px var(--font);letter-spacing:.2em;color:var(--dim);margin:0 0 10px} +#upd{position:fixed;top:calc(10px + env(safe-area-inset-top));left:50%;transform:translateX(-50%);z-index:9;padding:9px 16px;border-radius:999px;background:var(--ink);color:var(--bg);font:600 11px var(--font);letter-spacing:.16em;box-shadow:0 10px 30px -10px rgba(0,0,0,.6)} #stationSheet .x{position:absolute;top:8px;right:8px;width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:var(--dim);font:300 22px var(--sans);line-height:1} #stationSheet .x:hover{color:var(--ink);background:var(--bg)} #stationSheet label{display:block;color:var(--dim);font-size:12px;margin:8px 0 4px} @@ -282,7 +283,7 @@ input,textarea{font:inherit;color:inherit}
Optional. Without a key, gandora runs on a shared budget through inference.yolopreneur.lol (a few tracks a day per person). With your own Venice key it goes straight to api.venice.ai from this browser and the key goes nowhere else.
@@ -362,6 +363,7 @@ input,textarea{font:inherit;color:inherit} + @@ -1343,7 +1345,19 @@ if ("mediaSession" in navigator) { state.audio.addEventListener("play", () => { ms.playbackState = "playing"; }); state.audio.addEventListener("pause", () => { ms.playbackState = "paused"; }); } -if ("serviceWorker" in navigator && location.protocol === "https:") navigator.serviceWorker.register("sw.js").catch(() => {}); +/* updates: an installed app has no address bar to refresh from, so the page checks for a new worker whenever it + comes back to the foreground (and every ten minutes) and offers a reload when one has taken over */ +function showUpdate() { const u = $("#upd"); if (u) u.classList.remove("hidden"); } +if ("serviceWorker" in navigator && location.protocol === "https:") { + navigator.serviceWorker.register("sw.js").then((reg) => { + const check = () => reg.update().catch(() => {}); + setInterval(check, 10 * 60 * 1000); + document.addEventListener("visibilitychange", () => { if (document.visibilityState === "visible") check(); }); + reg.addEventListener("updatefound", () => { const nw = reg.installing; if (!nw) return; nw.addEventListener("statechange", () => { if (nw.state === "activated" && navigator.serviceWorker.controller) showUpdate(); }); }); + }).catch(() => {}); +} +$("#upd").addEventListener("click", () => location.reload()); +for (const b of document.querySelectorAll("button.reload")) b.addEventListener("click", () => location.reload()); /* light / dark: follows the system until the toggle is used, then remembered */ const sysDark = window.matchMedia("(prefers-color-scheme: dark)"); function applyTheme() {