metronome/mobile-sw.js
Me Here 5ab2096fc4 PolyMeter — slim main: landing chooser + mobile app + notation editor
Clean, dependency-light front page. Only three things ship here:
- index.html  — two-button landing: Mobile -> mobile.html, Desktop -> pm_e-2.html
- mobile.html — touch-first PWA (+ mobile-sessions.html practice journal)
- pm_e-2.html — engraved-notation editor

build.sh/deploy.sh trimmed to just these; deploy mirrors dist/ to the web root
with rsync --delete. README/CLAUDE.md rewritten for the slim scope.

The full project (PM_E-1 editor, embeddable widget, all hardware form-factor
pages, Pico firmware editions, the Rust port, and the KiCad/SPICE hardware
design) is preserved on the `concepts` branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:44:45 -05:00

52 lines
1.8 KiB
JavaScript

/* Service worker for the PolyMeter mobile app (mobile.html).
*
* Deliberately minimal and non-intrusive: it only manages its OWN app-shell URLs
* (the page, manifest, icons). For every other request it does NOT call
* respondWith(), so the rest of the site behaves exactly as if no SW existed.
*
* Strategy for the shell: network-first, fall back to cache. The page is a single
* self-contained file that is version-stamped on deploy, so when the device is
* online it always gets the freshest build; offline it still launches from cache.
*/
const CACHE = "polymeter-mobile-v2";
const SHELL = [
"/mobile.html",
"/mobile-sessions.html",
"/manifest.webmanifest",
"/icon-192.png",
"/icon-512.png",
"/icon-180.png",
];
const SHELL_PATHS = new Set(SHELL);
self.addEventListener("install", (e) => {
self.skipWaiting();
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(SHELL)).catch(() => {}));
});
self.addEventListener("activate", (e) => {
e.waitUntil(
caches.keys()
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
.then(() => self.clients.claim())
);
});
self.addEventListener("fetch", (e) => {
const req = e.request;
if (req.method !== "GET") return;
const url = new URL(req.url);
if (url.origin !== self.location.origin) return;
// Treat any navigation to /mobile.html (with or without ?standalone=1 etc.) as the shell.
const path = url.pathname;
if (!SHELL_PATHS.has(path)) return; // not ours — let the browser handle it
e.respondWith(
fetch(req)
.then((res) => {
if (res && res.ok) { const copy = res.clone(); caches.open(CACHE).then((c) => c.put(path, copy)); }
return res;
})
.catch(() => caches.match(path).then((hit) => hit || caches.match("/mobile.html")))
);
});