Files
Toju/toju-app/src/app/domains/notifications/application/effects/notifications.effects.ts
Myx 79c6f91cd6 chore: enforce lint across codebase and ban "maybe" in identifiers
Remove member-ordering and complexity eslint-disable comments by reordering
class members and applying targeted fixes. Add metoyou/no-maybe-in-naming,
type-safe WebRTC e2e harness helpers, and resolve remaining lint errors so
npm run lint exits cleanly.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-11 11:08:26 +02:00

143 lines
3.9 KiB
TypeScript

import { Injectable, inject } from '@angular/core';
import {
Actions,
createEffect,
ofType
} from '@ngrx/effects';
import { Store } from '@ngrx/store';
import {
filter,
tap,
withLatestFrom
} from 'rxjs/operators';
import type { Message } from '../../../../shared-kernel';
import { MessagesActions } from '../../../../store/messages/messages.actions';
import { RoomsActions } from '../../../../store/rooms/rooms.actions';
import { selectCurrentRoom, selectSavedRooms } from '../../../../store/rooms/rooms.selectors';
import { UsersActions } from '../../../../store/users/users.actions';
import { selectCurrentUser } from '../../../../store/users/users.selectors';
import { NotificationsFacade } from '../facades/notifications.facade';
export function groupMessagesByRoom(messages: Message[]): Map<string, Message[]> {
const messagesByRoom = new Map<string, Message[]>();
for (const message of messages) {
const roomMessages = messagesByRoom.get(message.roomId);
if (roomMessages) {
roomMessages.push(message);
continue;
}
messagesByRoom.set(message.roomId, [message]);
}
return messagesByRoom;
}
@Injectable()
export class NotificationsEffects {
syncRoomCatalog$ = createEffect(
() =>
this.actions$.pipe(
ofType(
RoomsActions.loadRoomsSuccess,
RoomsActions.createRoomSuccess,
RoomsActions.joinRoomSuccess,
RoomsActions.viewServerSuccess,
RoomsActions.updateRoom,
RoomsActions.addChannel,
RoomsActions.removeChannel,
RoomsActions.renameChannel,
RoomsActions.forgetRoomSuccess,
RoomsActions.deleteRoomSuccess
),
withLatestFrom(this.store.select(selectSavedRooms)),
tap(([, rooms]) => {
this.notifications.syncRoomCatalog(rooms);
})
),
{ dispatch: false }
);
hydrateUnreadCounts$ = createEffect(
() =>
this.actions$.pipe(
ofType(RoomsActions.loadRoomsSuccess, UsersActions.loadCurrentUserSuccess),
withLatestFrom(
this.store.select(selectCurrentUser),
this.store.select(selectSavedRooms)
),
filter(([, currentUser]) => !!currentUser),
tap(([
, , rooms
]) => {
void this.notifications.hydrateUnreadCounts(rooms);
})
),
{ dispatch: false }
);
markVisibleChannelRead$ = createEffect(
() =>
this.actions$.pipe(
ofType(
RoomsActions.createRoomSuccess,
RoomsActions.joinRoomSuccess,
RoomsActions.viewServerSuccess,
RoomsActions.selectChannel
),
tap(() => {
this.notifications.markCurrentChannelReadIfActive();
})
),
{ dispatch: false }
);
handleIncomingMessage$ = createEffect(
() =>
this.actions$.pipe(
ofType(MessagesActions.receiveMessage),
tap(({ message }) => {
void this.notifications.handleIncomingMessage(message);
})
),
{ dispatch: false }
);
refreshViewedRoomUnread$ = createEffect(
() =>
this.actions$.pipe(
ofType(MessagesActions.loadMessagesSuccess),
withLatestFrom(this.store.select(selectCurrentRoom)),
tap(([{ messages }, room]) => {
if (room) {
this.notifications.refreshRoomUnreadFromMessages(room.id, messages);
}
})
),
{ dispatch: false }
);
refreshSyncedRoomUnread$ = createEffect(
() =>
this.actions$.pipe(
ofType(MessagesActions.syncMessages),
tap(({ messages }) => {
for (const [roomId, roomMessages] of groupMessagesByRoom(messages)) {
this.notifications.refreshRoomUnreadFromMessages(roomId, roomMessages);
}
})
),
{ dispatch: false }
);
private readonly actions$ = inject(Actions);
private readonly store = inject(Store);
private readonly notifications = inject(NotificationsFacade);
}