51 lines
3.6 KiB
JavaScript
51 lines
3.6 KiB
JavaScript
'use strict';
|
|
// ---- Boot
|
|
(async () => {
|
|
try { cfg = { ...cfg, ...(await (await fetch('/api/config')).json()) }; } catch {}
|
|
const loadedBuild = cfg.build;
|
|
// When a new version is deployed, an open page keeps running the old one. Tell the person, and offer a reload.
|
|
const checkForUpdate = async () => {
|
|
try {
|
|
const c = await (await fetch('/api/config', { cache: 'no-store' })).json();
|
|
if (c.build && loadedBuild && c.build !== loadedBuild && !document.getElementById('upd')) {
|
|
const b = document.createElement('div'); b.id = 'upd';
|
|
b.innerHTML = 'A new version of NE Hub is available. <button class="btn" id="updgo">Reload</button>';
|
|
document.body.appendChild(b); document.getElementById('updgo').onclick = () => location.reload();
|
|
}
|
|
} catch {}
|
|
};
|
|
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') checkForUpdate(); });
|
|
setInterval(checkForUpdate, 10 * 60e3);
|
|
await loadMe();
|
|
await loadSettings();
|
|
if (typeof themeStart === 'function') themeStart();
|
|
sgStart(); if (typeof chStart === 'function') chStart(); if (typeof kidStart === 'function') kidStart(); if (typeof devStart === 'function') devStart(); if (typeof simpleStart === 'function') simpleStart();
|
|
addEventListener('hashchange', route);
|
|
restorePlayer();
|
|
route();
|
|
shareCheck();
|
|
// Unread mail and tasks due (the badge): checked on a timer only while the app is on screen, and again the moment you come back to it.
|
|
const badgePoll = () => { mailPoll(); taskPoll(); };
|
|
let lastBadge = Date.now(); badgePoll();
|
|
setInterval(() => { if (document.visibilityState === 'visible') { lastBadge = Date.now(); badgePoll(); } }, 2 * 60e3);
|
|
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible' && Date.now() - lastBadge > 30e3) { lastBadge = Date.now(); badgePoll(); } });
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
|
// tell the service worker who is signed in, so what it saves for offline use is kept for that person only
|
|
const who = () => navigator.serviceWorker.ready.then(r => (r.active || navigator.serviceWorker.controller || {}).postMessage && (r.active || navigator.serviceWorker.controller).postMessage({ type: 'who', id: ME ? ME.id : '' })).catch(() => {});
|
|
who(); navigator.serviceWorker.addEventListener('controllerchange', who);
|
|
}
|
|
// offline: say so once, and that what is on screen is the last saved copy
|
|
{ const note = () => { const el = document.getElementById('offnote') || Object.assign(document.createElement('div'), { id: 'offnote', role: 'status' }); el.textContent = 'You are offline. Showing what was last saved; changes need a connection.'; el.hidden = navigator.onLine; if (!el.isConnected) document.body.appendChild(el); if (typeof offqNote === 'function') offqNote(); };
|
|
addEventListener('offline', note); addEventListener('online', note); if (!navigator.onLine) note(); }
|
|
})();
|
|
|
|
// Keyboard (desktop): space play/pause, arrows seek, N/P next/previous.
|
|
addEventListener('keydown', e => {
|
|
const tag = e.target.tagName || '', k = e.key;
|
|
if (e.metaKey || e.ctrlKey || e.altKey || !cur() || document.body.classList.contains('onvideo') || /^(INPUT|TEXTAREA|SELECT)$/.test(tag) || (k === ' ' && /^(BUTTON|A)$/.test(tag))) return;
|
|
if (k === ' ') { e.preventDefault(); toggle(); }
|
|
else if (k === 'ArrowRight') pl.a.currentTime += 10; else if (k === 'ArrowLeft') pl.a.currentTime = Math.max(0, pl.a.currentTime - 10);
|
|
else if (k === 'n' || k === 'N') next(); else if (k === 'p' || k === 'P') prev();
|
|
});
|