// Settings -> Reminders: turn on push notifications for tasks due today and events about to start (Web Push).
const remSupported = () => 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window;
const b64ToBytes = s => { const p = '='.repeat((4 - s.length % 4) % 4), r = atob((s + p).replace(/-/g, '+').replace(/_/g, '/')); return Uint8Array.from([...r].map(c => c.charCodeAt(0))); };
const myTz = () => Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
/** Each time the app opens: if this device has a push subscription, tell the server again (it forgets a device when the push service says it is gone, and the time zone can change). */
let pushResynced = false;
async function pushResync() {
if (pushResynced) return; pushResynced = true;
try {
if (!remSupported() || Notification.permission !== 'granted') return;
const reg = await Promise.race([navigator.serviceWorker.ready, new Promise(ok => setTimeout(ok, 4000))]), s = reg && await reg.pushManager.getSubscription(); if (!s) return;
await jfetch('/api/push/subscribe', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ subscription: s.toJSON(), tz: myTz() }) });
} catch { /* try again next time the app opens */ }
}
function remindersHtml() {
return `
Reminders
Get a notification for tasks due today and events about to start, even when the app is closed. Turn it on for each device you want reminders on.
Checking…
`;
}
async function remindersInit() {
const box = document.getElementById('remlist'); if (!box) return;
if (!(allowed('tasks') || allowed('calendar'))) return document.getElementById('sec-rem').remove();
if (!remSupported()) { box.innerHTML = `
Not available here${/iPhone|iPad/.test(navigator.userAgent) ? 'On iPhone and iPad, add NE Hub to the Home Screen first (Share → Add to Home Screen), then open it from there.' : 'This browser does not support push notifications.'}
`; return; }
let info; try { info = await jfetch('/api/push/key'); } catch (e) { box.innerHTML = `
${esc(e.message)}
`; return; }
const reg = await Promise.race([navigator.serviceWorker.ready, new Promise(ok => setTimeout(ok, 4000))]); // (never ready: the browser refused the service worker)
if (!reg) { box.innerHTML = '
Not available hereThe browser did not start the background service reminders need. Reload the page, or open NE Hub over https in a regular browser.