annotate mrjunejune/src/public/pwa-register.js @ 258:60a876c4587a

[ui] Add semantic primitive ownership Build a layered Zenbu token and sizing system, make authored controls use native-underneath primitives, migrate mrjunejune without imposing visual surfaces, and document/enforce HTML ownership in the catalog and wiki. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Wed, 05 Aug 2026 05:25:40 -0700
parents 30c2196d03d4
children e02e2036ef84
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 // PWA Service Worker Registration
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2 if ('serviceWorker' in navigator) {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 window.addEventListener('load', () => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 navigator.serviceWorker
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 211
diff changeset
5 .register('/sw.js', { scope: '/' })
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 .then((registration) => {
211
a6d8d32a0261 [MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents: 209
diff changeset
7 // console.log('[PWA] Service Worker registered:', registration.scope);
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 // Check for updates periodically
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 setInterval(() => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 registration.update();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 }, 60000); // Check every minute
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 // Handle updates
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 registration.addEventListener('updatefound', () => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 const newWorker = registration.installing;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 newWorker.addEventListener('statechange', () => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 // New content available, show update notification
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20 if (confirm('New version available! Reload to update?')) {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 newWorker.postMessage({ type: 'SKIP_WAITING' });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 window.location.reload();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 }
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 }
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 })
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 .catch((error) => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 console.error('[PWA] Service Worker registration failed:', error);
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 // Handle service worker updates
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 let refreshing = false;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 navigator.serviceWorker.addEventListener('controllerchange', () => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 if (!refreshing) {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36 refreshing = true;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 window.location.reload();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 }
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 }
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 // Add install prompt handler
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 let deferredPrompt;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 window.addEventListener('beforeinstallprompt', (e) => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 e.preventDefault();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 deferredPrompt = e;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50 showInstallPromotion();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 function showInstallPromotion() {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 // Create an install button if it doesn't exist
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 if (document.getElementById('pwa-install-btn')) return;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57 const installBtn = document.createElement('button');
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 installBtn.classList.add('with-icon');
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 installBtn.id = 'pwa-install-btn';
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
60 const installIcon = document.createElement('zen-icon');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
61 installIcon.setAttribute('name', 'download');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
62 const installLabel = document.createElement('span');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
63 installLabel.textContent = 'Install as App';
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
64 installBtn.append(installIcon, installLabel);
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 installBtn.addEventListener('click', async () => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67 if (!deferredPrompt) return;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 deferredPrompt.prompt();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 const { outcome } = await deferredPrompt.userChoice;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71 console.log(`[PWA] User response: ${outcome}`);
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73 deferredPrompt = null;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 installBtn.remove();
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75 });
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
77 const wrapper = document.createElement('zen-button');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
78 wrapper.setAttribute('appearance', 'plain');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
79 wrapper.setAttribute('size', 'md');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
80 wrapper.append(installBtn);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
81 document.body.appendChild(wrapper);
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82
211
a6d8d32a0261 [MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents: 209
diff changeset
83 setTimeout(() => {
a6d8d32a0261 [MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents: 209
diff changeset
84 installBtn.style.opacity = '0';
a6d8d32a0261 [MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents: 209
diff changeset
85 installBtn.style.transition = 'opacity 0.3s';
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
86 setTimeout(() => wrapper.remove(), 300);
211
a6d8d32a0261 [MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents: 209
diff changeset
87 }, 5000);
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 }
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 window.addEventListener('appinstalled', () => {
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 console.log('[PWA] App installed successfully!');
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 deferredPrompt = null;
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 const installBtn = document.getElementById('pwa-install-btn');
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
95 if (installBtn) installBtn.closest('zen-button')?.remove();
209
3b47e82ac57e [MrJuneJune] PWA updates.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 });