Web Push reminders for tasks and events (Settings -> Reminders)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a0f1efc4ef
commit
c1f4a220f9
10 files changed
+426
-9
No files matched your search
@@ -37,6 +37,7 @@ const search = require('./search');
|
||||
const users = require('./users');
|
||||
const admin = require('./admin');
|
||||
const backup = require('./backup');
|
||||
const push = require('./push');
|
||||
const lyrics = require('./lyrics'); // lyrics for the music player, through Lyrica (LYRICS_API_URL)
|
||||
const signal = require('./signal'); // Signal messages, through signal-cli-rest-api (SIGNAL_API_URL)
|
||||
const vault = require('./vault')('nehub-plex');
|
||||
@@ -99,7 +100,7 @@ function serveStatic(req, res) {
|
||||
if (err) { res.writeHead(404); return res.end('Not found'); }
|
||||
// The pages link to /app.js?v=<build> etc. A new release changes the address, so no proxy cache ("Cache Assets" in
|
||||
// Nginx Proxy Manager, a CDN, the browser) can hand out an old copy.
|
||||
if (p === '/index.html' || p === '/login.html') data = Buffer.from(String(data).replace(/(src|href)="(\/(?:app|webauthn|login|links|palette|shell|calendar-views|music-extras|file-history)\.js|\/style\.css)"/g, `$1="$2?v=${BUILD}"`));
|
||||
if (p === '/index.html' || p === '/login.html') data = Buffer.from(String(data).replace(/(src|href)="(\/(?:app|webauthn|login|links|palette|shell|calendar-views|music-extras|file-history|reminders)\.js|\/style\.css)"/g, `$1="$2?v=${BUILD}"`));
|
||||
const headers = { 'content-type': TYPES[path.extname(file)] || 'application/octet-stream' };
|
||||
if (p.startsWith('/icons/')) headers['cache-control'] = 'public, max-age=604800'; // icons and splash screens rarely change
|
||||
else { // everything else: the browser may keep a copy but must check with us first, so a new version is never missed
|
||||
@@ -113,7 +114,7 @@ function serveStatic(req, res) {
|
||||
}
|
||||
|
||||
// Changes whenever the app's files change, so an open page can tell that a newer version is available.
|
||||
const BUILD = (() => { try { return crypto.createHash('sha1').update(['app.js', 'links.js', 'palette.js', 'shell.js', 'calendar-views.js', 'music-extras.js', 'file-history.js', 'index.html', 'style.css', 'webauthn.js', 'login.js', 'login.html', 'sw.js'].map(f => fs.readFileSync(path.join(PUBLIC, f))).join('')).digest('hex').slice(0, 12); } catch { return String(Date.now()); } })();
|
||||
const BUILD = (() => { try { return crypto.createHash('sha1').update(['app.js', 'links.js', 'palette.js', 'shell.js', 'calendar-views.js', 'music-extras.js', 'file-history.js', 'reminders.js', 'index.html', 'style.css', 'webauthn.js', 'login.js', 'login.html', 'sw.js'].map(f => fs.readFileSync(path.join(PUBLIC, f))).join('')).digest('hex').slice(0, 12); } catch { return String(Date.now()); } })();
|
||||
|
||||
// ---- OnlyOffice in-app editing (JWT-signed editor config + save-back callback to Seafile)
|
||||
const JWT_SECRET = process.env.ONLYOFFICE_JWT_SECRET || '';
|
||||
@@ -414,6 +415,7 @@ function storageInfo() {
|
||||
startedAt: STARTED };
|
||||
}
|
||||
const STARTED = Date.now();
|
||||
push.start();
|
||||
lyrics.init({ dataDir: path.resolve(process.env.DATA_DIR || path.join(__dirname, 'data')), apiUrl: process.env.LYRICS_API_URL || '' });
|
||||
signal.init({ dataDir: path.resolve(process.env.DATA_DIR || path.join(__dirname, 'data')), apiUrl: process.env.SIGNAL_API_URL || '' });
|
||||
{ const i = storageInfo(); console.log(`[data] ${i.dir}: ${i.passkeys} passkeys, ${i.calendarLinks} calendar links, ${i.events} events; mounted: ${i.mounted === null ? 'unknown' : i.mounted ? (i.source.kind + ' ' + i.source.name) : 'NO (data is lost on redeploy)'}; writable: ${i.writable}; COOKIE_SECRET from env: ${i.secretFromEnv}`);
|
||||
@@ -514,6 +516,7 @@ async function handleRequest(req, res) {
|
||||
if (req.method === 'POST' && req.url === '/api/oo/config') return OO_OK ? ooConfig(req, res) : forbidden(res, 'In-app editing needs ONLYOFFICE_JWT_SECRET to be set on the server');
|
||||
if (pathname === '/api/backup') return user.role === 'admin' ? backup.handle(req, res, user.name) : forbidden(res, 'Only an admin can do this');
|
||||
if (pathname === '/api/ddg') return ddgAnswer(req, res);
|
||||
if (pathname.startsWith('/api/push/')) return push.handle(req, res);
|
||||
if (pathname === '/api/audit') { res.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' }); return res.end(JSON.stringify({ events: require('./audit').recent(200) })); }
|
||||
if (pathname === '/api/system') { res.writeHead(200, { 'content-type': 'application/json' }); return res.end(JSON.stringify(storageInfo())); }
|
||||
if (pathname === '/api/settings') return settings.handle(req, res);
|
||||
|
||||
Reference in new issue
Block a user