File size: 2,787 Bytes
0815e01
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Notifications for photo requests, on a phone only: a switch on home. The service worker shows the notification when the app is closed and, on a
// tap, tells the open app to look for requests. Without a push key on the server the switch is not offered.
import { api } from "./api.js";
import { isTouch } from "./media.js";

const bytes = base64 => Uint8Array.from(atob(base64.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - base64.length % 4) % 4)), c => c.charCodeAt(0));

/** Draw the switch into `box` (nothing at all on a computer, without notification support, or when the server has no key). */
export async function setup(box) {
  if (!isTouch() || !("serviceWorker" in navigator) || !("PushManager" in window) || !("Notification" in window)) return;
  let server;
  try { server = await api("/api/push/key"); } catch { return; }
  if (!server.enabled) return;
  let registration;
  try { registration = await navigator.serviceWorker.register("/service-worker.js", { scope: "/" }); } catch { return; }
  let subscription = await registration.pushManager.getSubscription();
  const draw = (note = "") => {
    box.hidden = false;
    box.innerHTML = `<h3>ื”ืชืจืื•ืช</h3><p class="muted">ื›ืฉื”ืžื—ืฉื‘ ืžื‘ืงืฉ ืชืžื•ื ื” ืฉืœ ืชืฉื•ื‘ื”, ื”ื˜ืœืคื•ืŸ ื™ืงื‘ืœ ื”ืชืจืื” ื’ื ื›ืฉื”ืืคืœื™ืงืฆื™ื” ืกื’ื•ืจื”. ื‘ืื™ื™ืคื•ืŸ ื–ื” ืขื•ื‘ื“ ืจืง ืžื”ืืคืœื™ืงืฆื™ื” ืฉื”ื•ืกืคืชื ืœืžืกืš ื”ื‘ื™ืช.</p>
      <p>${subscription ? `<span class="tag" id="notif-state"><span aria-hidden="true">โœ“</span> ื”ืชืจืื•ืช ืคื•ืขืœื•ืช</span> <button type="button" id="notif-off">ื›ื™ื‘ื•ื™</button>`
        : `<button type="button" class="primary" id="notif-on">ื”ืคืขืœืช ื”ืชืจืื•ืช</button>`}</p><p class="muted" id="notif-note" role="status">${note}</p>`;
    box.querySelector("#notif-on")?.addEventListener("click", enable);
    box.querySelector("#notif-off")?.addEventListener("click", disable);
  };
  async function enable() {
    try {
      if (await Notification.requestPermission() !== "granted") return draw("ื”ื”ืชืจืื•ืช ื—ืกื•ืžื•ืช ื‘ื“ืคื“ืคืŸ. ืืคืฉืจ ืœืืฉืจ ืื•ืชืŸ ื‘ื”ื’ื“ืจื•ืช.");
      subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: bytes(server.key) });
      await api("/api/push/subscribe", { method: "POST", body: subscription.toJSON() });
      draw();
    } catch (error) { subscription = null; draw(error.message || "ืœื ื”ืฆืœื—ื ื• ืœื”ืคืขื™ืœ ื”ืชืจืื•ืช."); }
  }
  async function disable() {
    const endpoint = subscription?.endpoint;
    try { await subscription?.unsubscribe(); if (endpoint) await api("/api/push/unsubscribe", { method: "POST", body: { endpoint } }); } catch { /* it is off here either way */ }
    subscription = null;
    draw();
  }
  draw();
}