import { useEffect } from "react"; import { supabase } from "../lib/supabase"; import type { RealtimeChannel } from "@supabase/supabase-js"; /** * Realtime-Subscription für DM-Konversation: * Lauscht auf INSERT in rebreak.direct_messages mit sender_id=eq.{partnerId}. * Filter: Wir bekommen nur Nachrichten DES Partners (eigene werden lokal optimistisch * hinzugefügt). callback erhält die rohe Postgres-Row. */ export function useDmRealtime( partnerId: string | undefined, onInsert: (row: any) => void, enabled: boolean = true, ) { useEffect(() => { if (!enabled || !partnerId) return; let channel: RealtimeChannel | null = null; let cancelled = false; let reconnectTimer: ReturnType | null = null; async function subscribe() { const { data } = await supabase.auth.getSession(); if (cancelled || !data.session?.access_token) return; supabase.realtime.setAuth(data.session.access_token); channel = supabase .channel(`dm:${partnerId}:${Date.now()}`) .on( "postgres_changes", { event: "INSERT", schema: "rebreak", table: "direct_messages", filter: `sender_id=eq.${partnerId}`, }, (payload: any) => { onInsert(payload.new); }, ) .subscribe((status) => { if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") { cleanup(); if (reconnectTimer) clearTimeout(reconnectTimer); reconnectTimer = setTimeout(() => { if (!cancelled) subscribe(); }, 3000); } }); } function cleanup() { if (channel) { supabase.removeChannel(channel); channel = null; } } subscribe(); return () => { cancelled = true; if (reconnectTimer) clearTimeout(reconnectTimer); cleanup(); }; }, [partnerId, enabled, onInsert]); } /** * Realtime für Gruppen-Chat: lauscht auf INSERT in rebreak.chat_messages mit room_id=eq.{roomId}. */ export function useRoomRealtime( roomId: string | undefined, myUserId: string | undefined, onInsert: (row: any) => void, enabled: boolean = true, ) { useEffect(() => { if (!enabled || !roomId) return; let channel: RealtimeChannel | null = null; let cancelled = false; let reconnectTimer: ReturnType | null = null; async function subscribe() { const { data } = await supabase.auth.getSession(); if (cancelled || !data.session?.access_token) return; supabase.realtime.setAuth(data.session.access_token); channel = supabase .channel(`room:${roomId}:${Date.now()}`) .on( "postgres_changes", { event: "INSERT", schema: "rebreak", table: "chat_messages", filter: `room_id=eq.${roomId}`, }, (payload: any) => { // Eigene Nachrichten überspringen (lokal optimistisch hinzugefügt) if (payload.new?.user_id === myUserId) return; onInsert(payload.new); }, ) .subscribe((status) => { if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") { cleanup(); if (reconnectTimer) clearTimeout(reconnectTimer); reconnectTimer = setTimeout(() => { if (!cancelled) subscribe(); }, 3000); } }); } function cleanup() { if (channel) { supabase.removeChannel(channel); channel = null; } } subscribe(); return () => { cancelled = true; if (reconnectTimer) clearTimeout(reconnectTimer); cleanup(); }; }, [roomId, myUserId, enabled, onInsert]); }