7 changed files with 105 additions and 99 deletions
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
import logger from '@/lib/logger' |
||||
|
||||
type NeedRefreshListener = () => void |
||||
|
||||
const needRefreshListeners = new Set<NeedRefreshListener>() |
||||
let applyUpdate: (() => Promise<void>) | undefined |
||||
let initialized = false |
||||
|
||||
export function subscribePwaNeedRefresh(listener: NeedRefreshListener): () => void { |
||||
needRefreshListeners.add(listener) |
||||
return () => { |
||||
needRefreshListeners.delete(listener) |
||||
} |
||||
} |
||||
|
||||
function notifyPwaNeedRefresh(): void { |
||||
for (const listener of needRefreshListeners) { |
||||
try { |
||||
listener() |
||||
} catch (error) { |
||||
logger.debug('PWA need-refresh listener error', { error }) |
||||
} |
||||
} |
||||
} |
||||
|
||||
export function getPwaApplyUpdate(): (() => Promise<void>) | undefined { |
||||
return applyUpdate |
||||
} |
||||
|
||||
/** |
||||
* Register the service worker and surface {@link notifyPwaNeedRefresh} via vite-plugin-pwa prompt mode. |
||||
* Importing `virtual:pwa-register` prevents the auto-injected `registerSW.js` script tag. |
||||
*/ |
||||
export function initPwaUpdate(): void { |
||||
if (initialized || import.meta.env.DEV) return |
||||
if (typeof window === 'undefined' || !window.isSecureContext || !('serviceWorker' in navigator)) { |
||||
return |
||||
} |
||||
initialized = true |
||||
|
||||
void import('virtual:pwa-register') |
||||
.then(({ registerSW }) => { |
||||
applyUpdate = registerSW({ |
||||
immediate: true, |
||||
onNeedRefresh() { |
||||
notifyPwaNeedRefresh() |
||||
}, |
||||
onRegisterError(error: unknown) { |
||||
logger.debug('Service worker registration failed', { error }) |
||||
} |
||||
}) |
||||
}) |
||||
.catch((error) => { |
||||
logger.debug('PWA registration module unavailable', { error }) |
||||
}) |
||||
} |
||||
|
||||
/** True when a new build is installed but waiting for user confirmation (prompt mode). */ |
||||
export async function probePwaWaitingWorker(): Promise<boolean> { |
||||
if (import.meta.env.DEV || typeof navigator === 'undefined' || !('serviceWorker' in navigator)) { |
||||
return false |
||||
} |
||||
try { |
||||
const registration = await navigator.serviceWorker.ready |
||||
return Boolean(registration.waiting) |
||||
} catch { |
||||
return false |
||||
} |
||||
} |
||||
Loading…
Reference in new issue