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

@@ -87,7 +87,13 @@
(click)="$event.stopPropagation()"
/>
} @else {
<span class="truncate">{{ ch.name }}</span>
<span class="flex-1 truncate">{{ ch.name }}</span>
}
@if (channelUnreadCount(ch.id) > 0) {
<span class="ml-auto rounded-full bg-primary/15 px-1.5 py-0.5 text-[10px] font-semibold text-primary">
{{ formatUnreadCount(channelUnreadCount(ch.id)) }}
</span>
}
</button>
}
@@ -407,6 +413,14 @@
>
Resync Messages
</button>
@if (contextChannel()?.type === 'text') {
<button
(click)="toggleChannelNotifications()"
class="context-menu-item"
>
{{ isContextChannelMuted() ? 'Unmute Notifications' : 'Mute Notifications' }}
</button>
}
@if (canManageChannels()) {
<div class="context-menu-divider"></div>
<button

View File

@@ -37,6 +37,7 @@ import { RoomsActions } from '../../../store/rooms/rooms.actions';
import { MessagesActions } from '../../../store/messages/messages.actions';
import { RealtimeSessionFacade } from '../../../core/realtime';
import { ScreenShareFacade } from '../../../domains/screen-share';
import { NotificationsFacade } from '../../../domains/notifications';
import { VoiceActivityService, VoiceConnectionFacade } from '../../../domains/voice-connection';
import { VoiceSessionFacade, VoiceWorkspaceService } from '../../../domains/voice-session';
import { VoicePlaybackService } from '../../../domains/voice-connection/application/voice-playback.service';
@@ -93,6 +94,7 @@ export class RoomsSidePanelComponent {
private realtime = inject(RealtimeSessionFacade);
private voiceConnection = inject(VoiceConnectionFacade);
private screenShare = inject(ScreenShareFacade);
private notifications = inject(NotificationsFacade);
private voiceSessionService = inject(VoiceSessionFacade);
private voiceWorkspace = inject(VoiceWorkspaceService);
private voicePlayback = inject(VoicePlaybackService);
@@ -303,6 +305,40 @@ export class RoomsSidePanelComponent {
}
}
toggleChannelNotifications(): void {
const channel = this.contextChannel();
const roomId = this.currentRoom()?.id;
this.closeChannelMenu();
if (!channel || channel.type !== 'text' || !roomId) {
return;
}
this.notifications.setChannelMuted(
roomId,
channel.id,
!this.notifications.isChannelMuted(roomId, channel.id)
);
}
isContextChannelMuted(): boolean {
const channel = this.contextChannel();
const roomId = this.currentRoom()?.id;
return !!channel && channel.type === 'text' && !!roomId && this.notifications.isChannelMuted(roomId, channel.id);
}
channelUnreadCount(channelId: string): number {
const roomId = this.currentRoom()?.id;
return roomId ? this.notifications.channelUnreadCount(roomId, channelId) : 0;
}
formatUnreadCount(count: number): string {
return count > 99 ? '99+' : String(count);
}
resyncMessages() {
this.closeChannelMenu();
const room = this.currentRoom();