All files / src/web install.js

100% Statements 29/29
94.44% Branches 17/18
90.9% Functions 10/11
100% Lines 22/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 42 43 44 45 46 47 48 49 50 51 52 53    1x 1x             12x 12x 4x   8x 8x 4x 3x 3x           2x 1x     1x           8x       10x 7x 7x 3x 3x       7x 7x     1x    
import { toast } from "./toast.js";
 
const WorkerUrl = "service-worker.js";
const SkipWaiting = "SKIP_WAITING";
 
/**
 * Register the service worker that makes the page installable and usable offline. A new version waits until the
 * user asks for it, because switching worker reloads the page and that would throw away a running machine.
 */
export function registerServiceWorker(page, { benchmark }) {
    const { navigator, location } = page;
    if (benchmark || !import.meta.env.PROD || !("serviceWorker" in navigator) || !/^https?:$/.test(location.protocol))
        return;
 
    let offered = false;
    const offerUpdate = (registration) => {
        if (offered) return;
        offered = true;
        toast("A new version of jsbeeb is ready.", {
            title: "Update",
            action: {
                label: "Reload",
                run: () => {
                    // Another tab may already have switched over, leaving nothing to wait for.
                    if (!registration.waiting) return location.reload();
                    navigator.serviceWorker.addEventListener("controllerchange", () => location.reload(), {
                        once: true,
                    });
                    registration.waiting.postMessage({ type: SkipWaiting });
                },
            },
        });
    };
 
    navigator.serviceWorker
        .register(WorkerUrl)
        .then((registration) => {
            // The first install has no controller yet, and that is not an update.
            const updateIsWaiting = () => !!navigator.serviceWorker.controller && !!registration.waiting;
            if (updateIsWaiting()) offerUpdate(registration);
            registration.addEventListener("updatefound", () =>
                registration.installing.addEventListener("statechange", () => {
                    if (updateIsWaiting()) offerUpdate(registration);
                }),
            );
            // An installed window never navigates, so it would not otherwise look for a new version.
            page.document.addEventListener("visibilitychange", () => {
                Eif (page.document.visibilityState === "visible") registration.update().catch(() => {});
            });
        })
        .catch((error) => console.error("Service worker registration failed:", error));
}