| 1 | // The page half, as SKILL.md shows it. The buttons start disabled and |
| 2 | // are enabled only once they can do something: after the worker is |
| 3 | // active and the key is fetched. On a browser without push they stay |
| 4 | // disabled, with the reason logged, rather than sitting there inert. |
| 5 | import { enable, reconcile, disable, capabilities, status } from "/static/aviso/push.mjs"; |
| 6 | |
| 7 | const log = (line) => { document.getElementById("log").textContent += line + "\n"; }; |
| 8 | const button = (id) => document.getElementById(id); |
| 9 | const post = (path) => (body) => fetch(path, { |
| 10 | method: "POST", credentials: "same-origin", |
| 11 | headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), |
| 12 | }); |
| 13 | const save = post("/aviso/subscribe"); |
| 14 | const remove = post("/aviso/unsubscribe"); |
| 15 | |
| 16 | const caps = capabilities(); |
| 17 | log("capabilities: " + JSON.stringify(caps)); |
| 18 | if (!caps.standalone && /iPhone|iPad/.test(navigator.userAgent)) { |
| 19 | document.getElementById("coach").style.display = "block"; |
| 20 | } |
| 21 | if (!caps.serviceWorker || !caps.push) { |
| 22 | log("this browser cannot do push; the buttons stay disabled"); |
| 23 | } else { |
| 24 | await navigator.serviceWorker.register("/sw.js"); |
| 25 | // Active, not merely registered: subscribe() on an installing |
| 26 | // worker rejects with InvalidStateError. |
| 27 | const registration = await navigator.serviceWorker.ready; |
| 28 | const { publicKey } = await (await fetch("/aviso/public-key")).json(); |
| 29 | |
| 30 | // Every load: repair without prompting, and keep the server's |
| 31 | // confirmation moving. |
| 32 | const repaired = await reconcile({ registration, publicKey, save }).catch((e) => { log("reconcile: " + e.message); return null; }); |
| 33 | log("subscribed: " + !!repaired); |
| 34 | |
| 35 | // From the click, synchronously: enable prompts before its first await. |
| 36 | button("enable").onclick = () => { |
| 37 | enable({ registration, publicKey, save }) |
| 38 | .then((sub) => log(sub ? "enabled: " + sub.endpoint.slice(0, 40) + "…" : "permission denied")) |
| 39 | .catch((e) => log("enable: " + e.message)); |
| 40 | }; |
| 41 | button("disable").onclick = async () => { |
| 42 | try { await disable({ registration, remove }); log("disabled"); } catch (e) { log("disable: " + e.message); } |
| 43 | }; |
| 44 | button("notify").onclick = async () => { |
| 45 | const r = await fetch("/notify", { method: "POST", credentials: "same-origin" }); |
| 46 | log("notify: " + r.status + " " + await r.text()); |
| 47 | }; |
| 48 | for (const id of ["enable", "disable", "notify"]) button(id).disabled = false; |
| 49 | const s = await status(registration); |
| 50 | log("permission: " + s.permission); |
| 51 | } |
| 52 | |