feat: Add notifications

This commit is contained in:
2026-03-30 04:32:24 +02:00
parent b7d4bf20e3
commit 42ac712571
32 changed files with 1974 additions and 14 deletions

View File

@@ -0,0 +1,107 @@
/* eslint-disable @typescript-eslint/member-ordering */
import { Component, computed, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Store } from '@ngrx/store';
import { NgIcon, provideIcons } from '@ng-icons/core';
import {
lucideBell,
lucideBellOff,
lucideMessageSquareText,
lucideMoonStar
} from '@ng-icons/lucide';
import { selectSavedRooms } from '../../../../store/rooms/rooms.selectors';
import type { Room } from '../../../../shared-kernel';
import { NotificationsFacade } from '../../application/notifications.facade';
@Component({
selector: 'app-notifications-settings',
standalone: true,
imports: [
CommonModule,
NgIcon
],
viewProviders: [
provideIcons({
lucideBell,
lucideBellOff,
lucideMessageSquareText,
lucideMoonStar
})
],
templateUrl: './notifications-settings.component.html'
})
export class NotificationsSettingsComponent {
private readonly store = inject(Store);
readonly notifications = inject(NotificationsFacade);
readonly rooms = this.store.selectSignal(selectSavedRooms);
readonly settings = this.notifications.settings;
readonly enabled = computed(() => this.settings().enabled);
readonly showPreview = computed(() => this.settings().showPreview);
readonly respectBusyStatus = computed(() => this.settings().respectBusyStatus);
trackRoom = (_index: number, room: Room) => room.id;
textChannels(room: Room) {
const channels = (room.channels ?? [])
.filter((channel) => channel.type === 'text')
.sort((channelA, channelB) => channelA.position - channelB.position);
return channels.length > 0
? channels
: [{ id: 'general',
name: 'general',
type: 'text',
position: 0 }];
}
onNotificationsEnabledChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.notifications.setNotificationsEnabled(!!input.checked);
}
onShowPreviewChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.notifications.setShowPreview(!!input.checked);
}
onRespectBusyChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.notifications.setRespectBusyStatus(!!input.checked);
}
onRoomMutedChange(roomId: string, event: Event): void {
const input = event.target as HTMLInputElement;
this.notifications.setRoomMuted(roomId, !input.checked);
}
onChannelMutedChange(roomId: string, channelId: string, event: Event): void {
const input = event.target as HTMLInputElement;
this.notifications.setChannelMuted(roomId, channelId, !input.checked);
}
isRoomEnabled(roomId: string): boolean {
return !this.notifications.isRoomMuted(roomId);
}
isChannelEnabled(roomId: string, channelId: string): boolean {
return !this.notifications.isChannelMuted(roomId, channelId);
}
roomUnreadCount(roomId: string): number {
return this.notifications.roomUnreadCount(roomId);
}
channelUnreadCount(roomId: string, channelId: string): number {
return this.notifications.channelUnreadCount(roomId, channelId);
}
formatUnreadCount(count: number): string {
return count > 99 ? '99+' : String(count);
}
}