public/pwa.js
Rama main · réplica de lectura del repositorio original.
// PWA install + Web Push subscription (call enableNotifications() from the 开启通知 button).
(function () {
if ('serviceWorker' in navigator) navigator.serviceWorker.register('/sw.js').catch(() => {});
function urlB64ToUint8Array(b64) {
const pad = '='.repeat((4 - (b64.length % 4)) % 4);
const s = (b64 + pad).replace(/-/g, '+').replace(/_/g, '/');
const raw = atob(s);
return Uint8Array.from([...raw].map((c) => c.charCodeAt(0)));
}
async function refreshBtn() {
const btn = document.getElementById('notifyBtn'); if (!btn) return;
try {
const reg = await navigator.serviceWorker.getRegistration();
const sub = reg && (await reg.pushManager.getSubscription());
if (sub && Notification.permission === 'granted') { btn.textContent = '🔔 通知已开启'; btn.classList.add('on'); }
} catch {}
}
window.enableNotifications = async function () {
const btn = document.getElementById('notifyBtn');
try {
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
alert('此设备不支持推送。iOS 需要先把这个网页「添加到主屏幕」,再从主屏幕图标打开,才能开启通知。');
return;
}
const reg = await navigator.serviceWorker.ready;
const perm = await Notification.requestPermission();
if (perm !== 'granted') { alert('通知权限被拒绝了。到 设置→通知 里允许,或重新添加到主屏幕。'); return; }
const { key } = await (await fetch('/api/push/vapid')).json();
const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlB64ToUint8Array(key) });
await fetch('/api/push/subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ subscription: sub }) });
if (btn) { btn.textContent = '🔔 通知已开启'; btn.classList.add('on'); }
// fire a test so you see it works
fetch('/api/notify/test').catch(() => {});
} catch (e) { alert('开启失败:' + (e.message || e)); }
};
if (document.readyState !== 'loading') refreshBtn();
else document.addEventListener('DOMContentLoaded', refreshBtn);
})();