feat(v0.3): QR connect (M5) + PWA installable (M4)
- M5: 📱 toolbar button → modal with a client-side QR of location.origin
(shareable when opened via the LAN IP) + localhost tip
- M4: manifest.webmanifest + icon.svg + sw.js (network-first, never intercepts
/term or /hook) + registration in main.ts; apple-touch + theme-color meta
- Browser-verified: QR canvas renders, SW 'controlled', manifest linked,
no console errors. 199 tests green, build ok.
This commit is contained in:
28
public/sw.js
Normal file
28
public/sw.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* public/sw.js — minimal service worker (M4: PWA installability + offline shell).
|
||||
*
|
||||
* Network-first so we never serve a stale build while online; falls back to the
|
||||
* cache when offline. Never intercepts the WebSocket (/term) or hook endpoints.
|
||||
*/
|
||||
|
||||
const CACHE = 'webterm-v1'
|
||||
|
||||
self.addEventListener('install', () => self.skipWaiting())
|
||||
self.addEventListener('activate', (e) => e.waitUntil(self.clients.claim()))
|
||||
|
||||
self.addEventListener('fetch', (e) => {
|
||||
const req = e.request
|
||||
if (req.method !== 'GET') return
|
||||
const url = new URL(req.url)
|
||||
if (url.pathname === '/term' || url.pathname.startsWith('/hook')) return // WS / hooks
|
||||
|
||||
e.respondWith(
|
||||
fetch(req)
|
||||
.then((res) => {
|
||||
const copy = res.clone()
|
||||
caches.open(CACHE).then((c) => c.put(req, copy))
|
||||
return res
|
||||
})
|
||||
.catch(() => caches.match(req)),
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user