feat(desktop): mention notifications via realtime + osNotify
This commit is contained in:
@@ -6,6 +6,7 @@ import { startConversationKeySync } from '../lib/conversationKeySync';
|
|||||||
import { startDeviceApprovalListener } from '../lib/deviceApproval';
|
import { startDeviceApprovalListener } from '../lib/deviceApproval';
|
||||||
import { ensureInstallId } from '../lib/installId';
|
import { ensureInstallId } from '../lib/installId';
|
||||||
import { ensureNotificationPermission } from '../lib/osNotify';
|
import { ensureNotificationPermission } from '../lib/osNotify';
|
||||||
|
import { useMentionNotifications } from '../lib/useMentionNotifications';
|
||||||
import { cachedUserKey } from '../lib/userIdentity';
|
import { cachedUserKey } from '../lib/userIdentity';
|
||||||
import { CallUI } from './CallUI';
|
import { CallUI } from './CallUI';
|
||||||
import { DeviceApprovalBanner } from './DeviceApprovalBanner';
|
import { DeviceApprovalBanner } from './DeviceApprovalBanner';
|
||||||
@@ -13,6 +14,7 @@ import { Sidebar } from './Sidebar';
|
|||||||
|
|
||||||
export function AppShell() {
|
export function AppShell() {
|
||||||
const { session } = useAuth();
|
const { session } = useAuth();
|
||||||
|
useMentionNotifications(session?.user.id);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Prompt once per authenticated shell mount. Module-level guard prevents
|
// Prompt once per authenticated shell mount. Module-level guard prevents
|
||||||
// re-asking if the user already responded this session.
|
// 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]);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user