feat(desktop): mention notifications via realtime + osNotify

This commit is contained in:
byGalax
2026-05-16 17:59:57 +02:00
parent 7355b343c8
commit ef98efb938
2 changed files with 47 additions and 0 deletions
+2
View File
@@ -6,6 +6,7 @@ import { startConversationKeySync } from '../lib/conversationKeySync';
import { startDeviceApprovalListener } from '../lib/deviceApproval';
import { ensureInstallId } from '../lib/installId';
import { ensureNotificationPermission } from '../lib/osNotify';
import { useMentionNotifications } from '../lib/useMentionNotifications';
import { cachedUserKey } from '../lib/userIdentity';
import { CallUI } from './CallUI';
import { DeviceApprovalBanner } from './DeviceApprovalBanner';
@@ -13,6 +14,7 @@ import { Sidebar } from './Sidebar';
export function AppShell() {
const { session } = useAuth();
useMentionNotifications(session?.user.id);
useEffect(() => {
// Prompt once per authenticated shell mount. Module-level guard prevents
// re-asking if the user already responded this session.
@@ -0,0 +1,45 @@
import { useEffect } from 'react';
import { notify } from './osNotify';
import { supabase } from './supabase';
interface MentionRow {
message_id: string;
mentioned_user_id: string;
conversation_id: string;
}
// Subscribes to my own message_mentions inserts and fires an OS notification
// for each one. Bypasses per-conv mute (mentions override mute by design).
//
// We don't decrypt the body here — the notification just says "Du wurdest
// erwähnt". The conv list highlight + the in-app navigation reveal context.
export function useMentionNotifications(userId: string | undefined): void {
useEffect(() => {
if (!userId) return;
const channel = supabase
.channel('mentions:' + userId)
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'message_mentions',
filter: 'mentioned_user_id=eq.' + userId,
},
(payload) => {
const row = payload.new as MentionRow | null;
if (!row) return;
void notify({
title: 'Du wurdest erwähnt',
body: 'Tippe um die Nachricht zu lesen.',
force: true,
});
},
)
.subscribe();
return () => {
void supabase.removeChannel(channel);
};
}, [userId]);
}