function createTodayLockScreen({ storage, getLogin, serviceWorker, NotificationRef, control, status, locationRef, historyRef, onAction = () => {}, }) { const preferenceKey = () => { const login = String(getLogin?.() || '').trim().toLowerCase(); return login ? 'stackchain.today-lock-screen.v1.' + encodeURIComponent(login) : ''; }; const supported = Boolean(serviceWorker && NotificationRef); const enabled = () => { const key = preferenceKey(); return Boolean(key && storage?.getItem(key) === '1'); }; const setStatus = message => { if (status) status.textContent = message; }; const post = async message => { const target = serviceWorker?.controller || (await serviceWorker?.ready)?.active; target?.postMessage?.(message); }; const hide = () => post({ type:'stackchain-today-lock-screen', active:false, running:false, }); const render = () => { if (control) { control.checked = enabled(); control.disabled = !supported; } if (!supported) setStatus('Lock-screen controls are not supported on this device.'); else if (enabled()) setStatus('Lock-screen Today controls are on.'); }; const consumeAction = action => { if (!enabled() || !['pause', 'resume'].includes(action)) return false; onAction(action); return true; }; const api = { enabled, async enable() { if (!supported) { render(); return false; } const permission = NotificationRef.permission === 'granted' ? 'granted' : await NotificationRef.requestPermission(); if (permission !== 'granted') { if (control) control.checked = false; setStatus(permission === 'denied' ? 'Lock-screen controls are blocked in browser settings.' : 'Lock-screen controls were not enabled.'); return false; } const key = preferenceKey(); if (!key) return false; storage?.setItem(key, '1'); render(); return true; }, async disable() { const key = preferenceKey(); if (key) storage?.removeItem(key); if (control) control.checked = false; setStatus('Lock-screen Today controls are off.'); await hide(); return true; }, async sync(snapshot, active) { if (!enabled() || NotificationRef?.permission !== 'granted') return false; const visible = Boolean(active && snapshot?.identity); await post({ type:'stackchain-today-lock-screen', active:visible, running:visible && Boolean(snapshot.running), }); return true; }, consumeLaunchAction() { let url; try { url = new URL(locationRef?.href || ''); } catch (_error) { return false; } const action = url.searchParams.get('today_timer_action'); if (!['pause', 'resume'].includes(action)) return false; url.searchParams.delete('today_timer_action'); historyRef?.replaceState?.(null, '', url.pathname + url.search + url.hash); return consumeAction(action); }, render, }; control?.addEventListener?.('change', () => { if (control.checked) api.enable(); else api.disable(); }); serviceWorker?.addEventListener?.('message', event => { if (event.data?.type === 'stackchain-today-timer-action') consumeAction(String(event.data.action || '')); }); render(); return api; } if (typeof module !== 'undefined' && module.exports) module.exports = createTodayLockScreen;