diff --git a/frontend/src/app/pages/altitude/chat/components/chat-info/chat-info.component.ts b/frontend/src/app/pages/altitude/chat/components/chat-info/chat-info.component.ts index 86eca5e..fecd53c 100644 --- a/frontend/src/app/pages/altitude/chat/components/chat-info/chat-info.component.ts +++ b/frontend/src/app/pages/altitude/chat/components/chat-info/chat-info.component.ts @@ -1,4 +1,4 @@ -import {Component, inject, input} from '@angular/core'; +import {Component, computed, inject, input} from '@angular/core'; import {getServerColor, getServerTextColor} from '@pages/altitude/chat/util/server-color'; import {NotificationService} from '@pages/altitude/chat/service/chat-notification.service'; import {NotificationEnabledSvgComponent} from '@pages/altitude/chat/svg/notification-enabled.svg'; @@ -17,20 +17,20 @@ export class ChatInfoComponent { private readonly notificationService: NotificationService = inject(NotificationService); public readonly selectedServer = input.required(); - protected readonly notificationEnabled = this.notificationService.notificationEnabled; + protected readonly notificationEnabled = computed(() => this.notificationService.isNotificationEnabled(this.selectedServer())); protected readonly getServerColor = getServerColor; protected readonly getServerTextColor = getServerTextColor; public enableNotifications() { this.notificationService.requestPermission().then( () => { - this.notificationService.enableNotifications(); + this.notificationService.enableNotifications(this.selectedServer()); } ); } public disableNotifications() { - this.notificationService.disableNotifications(); + this.notificationService.disableNotifications(this.selectedServer()); } } diff --git a/frontend/src/app/pages/altitude/chat/service/chat-notification.service.ts b/frontend/src/app/pages/altitude/chat/service/chat-notification.service.ts index 0039ba3..187bbe8 100644 --- a/frontend/src/app/pages/altitude/chat/service/chat-notification.service.ts +++ b/frontend/src/app/pages/altitude/chat/service/chat-notification.service.ts @@ -5,8 +5,8 @@ export class NotificationService { private readonly notificationSound = new Audio('/public/sounds/notification.mp3'); private readonly notificationStorageKey = 'chat-notifications-enabled'; - private readonly _notificationEnabled = signal( - localStorage.getItem(this.notificationStorageKey) === 'true' + private readonly _notificationEnabled = signal>( + this.getStoredNotificationSettings() ); public readonly notificationEnabled = this._notificationEnabled.asReadonly(); @@ -33,8 +33,8 @@ export class NotificationService { return false; } - notify(title: string, body: string | null) { - if (!this.notificationEnabled()) { + notify(server: string, title: string, body: string | null) { + if (!this.isNotificationEnabled(server)) { return; } if (Notification.permission === 'granted') { @@ -68,13 +68,43 @@ export class NotificationService { }); } - enableNotifications() { - this._notificationEnabled.set(true); - localStorage.setItem(this.notificationStorageKey, 'true'); + public isNotificationEnabled(server: string): boolean { + return this._notificationEnabled()[server]; } - disableNotifications() { - this._notificationEnabled.set(false); - localStorage.setItem(this.notificationStorageKey, 'false'); + enableNotifications(server: string) { + this.setNotificationEnabled(server, true); + } + + disableNotifications(server: string) { + this.setNotificationEnabled(server, false); + } + + private setNotificationEnabled(server: string, enabled: boolean) { + const notificationSettings = { + ...this._notificationEnabled(), + [server]: enabled + }; + + this._notificationEnabled.set(notificationSettings); + localStorage.setItem(this.notificationStorageKey, JSON.stringify(notificationSettings)); + } + + private getStoredNotificationSettings(): Record { + const storedSettings = localStorage.getItem(this.notificationStorageKey); + + if (storedSettings === null) { + return {}; + } + + if (storedSettings === 'true' || storedSettings === 'false') { + return {}; + } + + try { + return JSON.parse(storedSettings) as Record; + } catch { + return {}; + } } } diff --git a/frontend/src/app/pages/altitude/chat/service/chat.service.ts b/frontend/src/app/pages/altitude/chat/service/chat.service.ts index 3148d6b..577a3cf 100644 --- a/frontend/src/app/pages/altitude/chat/service/chat.service.ts +++ b/frontend/src/app/pages/altitude/chat/service/chat.service.ts @@ -60,7 +60,14 @@ export class ChatService implements OnDestroy { find.unreadMessages++; } }) - this.notificationService.notify(`(${chatMessages.length}) new messages`, null); + const messagesByServer = chatMessages.reduce>((acc, message) => { + acc[message.server] = (acc[message.server] ?? 0) + 1; + return acc; + }, {}); + + Object.entries(messagesByServer).forEach(([server, messageCount]) => { + this.notificationService.notify(server, `New messages`, `(${messageCount}) new messages in ${server}`); + }); }); source.onerror = (err) => {