You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
2.0 KiB
69 lines
2.0 KiB
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 |
|
} |
|
}
|
|
|