72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect } from 'react';
|
|
|
|
const APP_VERSION = '2026-06-14-ux-realtime-v3';
|
|
const APP_VERSION_KEY = 'fifa2026-app-version';
|
|
|
|
function toUint8Array(base64: string): Uint8Array {
|
|
const padding = '='.repeat((4 - (base64.length % 4)) % 4);
|
|
const base64Safe = (base64 + padding).replace(/-/g, '+').replace(/_/g, '/');
|
|
const raw = atob(base64Safe);
|
|
const buffer = new ArrayBuffer(raw.length);
|
|
const out = new Uint8Array(buffer);
|
|
|
|
for (let i = 0; i < raw.length; i += 1) {
|
|
out[i] = raw.charCodeAt(i);
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
export function PwaBootstrap() {
|
|
useEffect(() => {
|
|
if (typeof window === 'undefined' || !('serviceWorker' in navigator)) {
|
|
return;
|
|
}
|
|
|
|
const setup = async () => {
|
|
try {
|
|
const previousVersion = window.localStorage.getItem(APP_VERSION_KEY);
|
|
const shouldPurgeOldCache = previousVersion !== APP_VERSION;
|
|
if (shouldPurgeOldCache && 'caches' in window) {
|
|
const keys = await caches.keys();
|
|
await Promise.all(keys.filter((key) => key.startsWith('wc2026-') || key.includes('fifa2026')).map((key) => caches.delete(key)));
|
|
window.localStorage.setItem(APP_VERSION_KEY, APP_VERSION);
|
|
}
|
|
|
|
const registration = await navigator.serviceWorker.register(`/sw.js?v=${APP_VERSION}`);
|
|
await registration.update();
|
|
registration.active?.postMessage({ type: 'app-version', version: APP_VERSION });
|
|
registration.waiting?.postMessage({ type: 'skip-waiting' });
|
|
|
|
if (Notification.permission === 'granted') {
|
|
const vapid = process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY;
|
|
if (vapid) {
|
|
const existing = await registration.pushManager.getSubscription();
|
|
if (!existing) {
|
|
await registration.pushManager.subscribe({
|
|
userVisibleOnly: true,
|
|
applicationServerKey: toUint8Array(vapid),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
navigator.serviceWorker.addEventListener('message', (event) => {
|
|
const payload = event.data;
|
|
if (payload?.type === 'push-trigger') {
|
|
console.log('PWA push message', payload);
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.warn('PWA bootstrap 失敗', error);
|
|
}
|
|
};
|
|
|
|
void setup();
|
|
}, []);
|
|
|
|
return null;
|
|
}
|