From 47d61e6427555cca267547c6f0a82888e27e4ac1 Mon Sep 17 00:00:00 2001 From: Bastian Wagner Date: Mon, 29 Jun 2026 15:32:40 +0200 Subject: [PATCH] notifications --- listify-api/src/tasks/task-digest.service.ts | 11 ++++++++++- listify-api/src/tasks/task-push.service.ts | 7 ++++++- listify-client/public/sw.js | 5 ++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/listify-api/src/tasks/task-digest.service.ts b/listify-api/src/tasks/task-digest.service.ts index c9b9400..c58701a 100644 --- a/listify-api/src/tasks/task-digest.service.ts +++ b/listify-api/src/tasks/task-digest.service.ts @@ -15,6 +15,7 @@ interface TaskDigestPayload { tasksUrl: string; todayTasks: TaskDigestEmailItem[]; overdueTasks: TaskDigestEmailItem[]; + notificationTag?: string; } interface TaskDigestPayloadResult { @@ -101,7 +102,13 @@ export class TaskDigestService { const slot = this.currentSlot(now) ?? 'morning'; const dateKey = this.dateKey(now); const { payload, taskCount, usedFallbackTask } = - await this.buildDigestPayload(user.id, slot, dateKey, true); + await this.buildDigestPayload( + user.id, + slot, + dateKey, + true, + `task-digest-test-${dateKey}-${Date.now()}`, + ); const result: TaskNotificationTestResult = { message: 'Task notification test processed.', date: dateKey, @@ -190,6 +197,7 @@ export class TaskDigestService { slot: TaskDigestSlot, dateKey: string, includeFallbackTask: boolean, + notificationTag?: string, ): Promise { const tasks = await this.tasksRepository.find({ where: { @@ -224,6 +232,7 @@ export class TaskDigestService { tasksUrl: this.tasksUrl(), todayTasks: mappedTodayTasks, overdueTasks: mappedOverdueTasks, + notificationTag, }, taskCount: tasks.length + (usedFallbackTask ? 1 : 0), usedFallbackTask, diff --git a/listify-api/src/tasks/task-push.service.ts b/listify-api/src/tasks/task-push.service.ts index 53af352..b01df6d 100644 --- a/listify-api/src/tasks/task-push.service.ts +++ b/listify-api/src/tasks/task-push.service.ts @@ -15,6 +15,7 @@ interface TaskDigestPushPayload { tasksUrl: string; todayTasks: TaskDigestEmailItem[]; overdueTasks: TaskDigestEmailItem[]; + notificationTag?: string; } export interface TaskPushDigestResult { @@ -135,6 +136,10 @@ export class TaskPushService { await webPush.sendNotification( this.toPushSubscription(subscription), JSON.stringify(this.toNotificationPayload(payload)), + { + TTL: 60 * 60, + urgency: 'high', + }, ); return true; } catch (error) { @@ -191,7 +196,7 @@ export class TaskPushService { title, body: parts.join(', '), url: payload.tasksUrl, - tag: `task-digest-${payload.slot}-${payload.date}`, + tag: payload.notificationTag ?? `task-digest-${payload.slot}-${payload.date}`, }; } diff --git a/listify-client/public/sw.js b/listify-client/public/sw.js index a4d231d..ea15414 100644 --- a/listify-client/public/sw.js +++ b/listify-client/public/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = 'listify-shell-v2'; +const CACHE_NAME = 'listify-shell-v3'; const SHELL_ASSETS = ['/', '/index.html', '/manifest.webmanifest', '/pwa-icon.svg']; self.addEventListener('install', (event) => { @@ -73,6 +73,9 @@ self.addEventListener('push', (event) => { const options = { body: payload.body || 'Du hast offene Tasks.', tag: payload.tag || 'listify-task-digest', + renotify: true, + timestamp: Date.now(), + vibrate: [120, 80, 120], icon: '/pwa-icon.svg', badge: '/pwa-icon.svg', data: {