From 7a76c0a6c04c37eb8d0047f1420e49b1ea3bc93f Mon Sep 17 00:00:00 2001 From: Hermes Date: Tue, 18 Aug 2026 10:58:39 +0200 Subject: [PATCH] =?UTF-8?q?feat(notifications):=20disable=20realtime/WebSo?= =?UTF-8?q?cket=20entirely=20=E2=80=94=20REST=20fetch=20+=20focus=20refres?= =?UTF-8?q?h=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - remove postgres_changes .channel().subscribe() from useNotifications - notifications now load via REST on mount and refresh on tab focus - eliminates WS retry hangs (30-40s stalls) from dead realtime container; web-push (Push API) is unaffected and works independently --- src/hooks/useNotifications.js | 53 ++++++++--------------------------- 1 file changed, 11 insertions(+), 42 deletions(-) diff --git a/src/hooks/useNotifications.js b/src/hooks/useNotifications.js index 8ae7f67..f936d8d 100644 --- a/src/hooks/useNotifications.js +++ b/src/hooks/useNotifications.js @@ -31,50 +31,19 @@ export function useNotifications(userId) { fetchNotifications(); }, [fetchNotifications]); - // Realtime subscription + // NOTE: realtime (WebSocket) subscription intentionally removed (2026-08). + // The supabase realtime container kept dying and the client hung in WS retry + // loops (30-40s stalls on open). Notifications now update via REST fetch on + // page load / focus only — see handleFocus below for refresh on tab focus. + + // Refresh notifications when the tab regains focus so the unread badge stays + // reasonably fresh without a live WebSocket connection. React.useEffect(() => { if (!hasSupabaseConfig || !userId) return; - - const channel = supabase - .channel(`notifications:${userId}`) - .on( - "postgres_changes", - { - event: "INSERT", - schema: "public", - table: "notifications", - filter: `user_id=eq.${userId}`, - }, - (payload) => { - const newNotif = payload.new; - setNotifications((prev) => [newNotif, ...prev].slice(0, 50)); - setUnreadCount((prev) => prev + 1); - } - ) - .on( - "postgres_changes", - { - event: "UPDATE", - schema: "public", - table: "notifications", - filter: `user_id=eq.${userId}`, - }, - (payload) => { - const updated = payload.new; - setNotifications((prev) => - prev.map((n) => (n.id === updated.id ? updated : n)) - ); - setUnreadCount((prev) => - Math.max(0, prev + (updated.read ? -1 : 0) + (prev === 0 && !updated.read ? 1 : 0)) - ); - } - ) - .subscribe(); - - return () => { - supabase.removeChannel(channel); - }; - }, [userId]); + const handleFocus = () => fetchNotifications(); + window.addEventListener("focus", handleFocus); + return () => window.removeEventListener("focus", handleFocus); + }, [fetchNotifications, userId]); // Fix unread count: always recalculate from notifications React.useEffect(() => {