Mercurial
annotate mrjunejune/src/public/pwa-register.js @ 216:e82b80b24012 default tip
[MrJuneJune] Make webp translate background job.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Sat, 28 Feb 2026 21:04:43 -0800 |
| parents | a6d8d32a0261 |
| children |
| rev | line source |
|---|---|
| 209 | 1 // PWA Service Worker Registration |
| 2 if ('serviceWorker' in navigator) { | |
| 3 window.addEventListener('load', () => { | |
| 4 navigator.serviceWorker | |
| 5 .register('/public/sw.js') | |
| 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 | 8 |
| 9 // Check for updates periodically | |
| 10 setInterval(() => { | |
| 11 registration.update(); | |
| 12 }, 60000); // Check every minute | |
| 13 | |
| 14 // Handle updates | |
| 15 registration.addEventListener('updatefound', () => { | |
| 16 const newWorker = registration.installing; | |
| 17 newWorker.addEventListener('statechange', () => { | |
| 18 if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { | |
| 19 // New content available, show update notification | |
| 20 if (confirm('New version available! Reload to update?')) { | |
| 21 newWorker.postMessage({ type: 'SKIP_WAITING' }); | |
| 22 window.location.reload(); | |
| 23 } | |
| 24 } | |
| 25 }); | |
| 26 }); | |
| 27 }) | |
| 28 .catch((error) => { | |
| 29 console.error('[PWA] Service Worker registration failed:', error); | |
| 30 }); | |
| 31 | |
| 32 // Handle service worker updates | |
| 33 let refreshing = false; | |
| 34 navigator.serviceWorker.addEventListener('controllerchange', () => { | |
| 35 if (!refreshing) { | |
| 36 refreshing = true; | |
| 37 window.location.reload(); | |
| 38 } | |
| 39 }); | |
| 40 }); | |
| 41 } | |
| 42 | |
| 43 // Add install prompt handler | |
| 44 let deferredPrompt; | |
| 45 | |
| 46 window.addEventListener('beforeinstallprompt', (e) => { | |
| 47 e.preventDefault(); | |
| 48 deferredPrompt = e; | |
| 49 | |
| 50 showInstallPromotion(); | |
| 51 }); | |
| 52 | |
| 53 function showInstallPromotion() { | |
| 54 // Create an install button if it doesn't exist | |
| 55 if (document.getElementById('pwa-install-btn')) return; | |
| 56 | |
| 57 const installBtn = document.createElement('button'); | |
| 58 installBtn.classList.add('with-icon'); | |
| 59 installBtn.id = 'pwa-install-btn'; | |
| 60 installBtn.textContent = 'Install as App'; | |
| 61 | |
| 62 installBtn.addEventListener('click', async () => { | |
| 63 if (!deferredPrompt) return; | |
| 64 | |
| 65 deferredPrompt.prompt(); | |
| 66 const { outcome } = await deferredPrompt.userChoice; | |
| 67 console.log(`[PWA] User response: ${outcome}`); | |
| 68 | |
| 69 deferredPrompt = null; | |
| 70 installBtn.remove(); | |
| 71 }); | |
| 72 | |
| 73 document.body.appendChild(installBtn); | |
| 74 | |
|
211
a6d8d32a0261
[MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents:
209
diff
changeset
|
75 setTimeout(() => { |
|
a6d8d32a0261
[MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents:
209
diff
changeset
|
76 installBtn.style.opacity = '0'; |
|
a6d8d32a0261
[MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents:
209
diff
changeset
|
77 installBtn.style.transition = 'opacity 0.3s'; |
|
a6d8d32a0261
[MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents:
209
diff
changeset
|
78 setTimeout(() => installBtn.remove(), 300); |
|
a6d8d32a0261
[MrJuneJune] Simple animations for darkmode.
MrJuneJune <me@mrjunejune.com>
parents:
209
diff
changeset
|
79 }, 5000); |
| 209 | 80 } |
| 81 | |
| 82 window.addEventListener('appinstalled', () => { | |
| 83 console.log('[PWA] App installed successfully!'); | |
| 84 deferredPrompt = null; | |
| 85 | |
| 86 const installBtn = document.getElementById('pwa-install-btn'); | |
| 87 if (installBtn) installBtn.remove(); | |
| 88 }); |