import { computed, effect, inject, Injectable, signal } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { injectQuery, QueryClient } from '@tanstack/angular-query-experimental'; import { lastValueFrom } from 'rxjs'; import { HttpResponse } from '../models/response.interface'; import { injectAuthService } from './auth.service'; import { injectWebsocketService, WSEvents } from './websocket.service'; const LAST_READ_KEY = 'notifications_last_read'; export interface NotificationItem { unixtime: number; title: string; body: string; } @Injectable({ providedIn: 'root', }) export class NotificationsService { private http = inject(HttpClient); private queryClient = inject(QueryClient); private authServ = injectAuthService(); private websocketServ = injectWebsocketService(); public lastReadUnixtime = signal( parseInt(localStorage.getItem(LAST_READ_KEY) || '0', 10) ); private persistEffect = effect(() => { localStorage.setItem(LAST_READ_KEY, this.lastReadUnixtime().toString()); }); notifications = injectQuery(() => ({ queryKey: ['notifications'], queryFn: async () => { const response = await lastValueFrom( this.http.get>('web_push/notifications') ); return response.data; }, staleTime: 5 * 60 * 1000, refetchOnWindowFocus: true, enabled: !!this.authServ.loginStatus.data(), })); unreadCount = computed(() => { const data = this.notifications.data(); const lastRead = this.lastReadUnixtime(); if (!data) return 0; return data.filter((notification) => notification.unixtime > lastRead).length; }); hasUnread = computed(() => this.unreadCount() > 0); constructor() { this.websocketServ.listen(WSEvents.NOTIFICATIONS, ['notifications']).subscribe(); } markAllAsRead(): void { const data = this.notifications.data(); if (data && data.length > 0) { const maxUnixtime = Math.max(...data.map((notification) => notification.unixtime)); this.lastReadUnixtime.set(maxUnixtime); } } refreshNotifications(): void { this.queryClient.invalidateQueries({ queryKey: ['notifications'] }); } } export const injectNotificationsService = () => inject(NotificationsService);