From 0eba54b8b8231b0707cf428578e0885e3a3bb4b4 Mon Sep 17 00:00:00 2001 From: Z8MB1E Date: Fri, 28 Aug 2026 22:08:37 -0400 Subject: [PATCH] feat(presence): add presence channel handling in real-time updates --- src/app/api/realtime/route.ts | 1 + src/hooks/useRealtimePresence.ts | 1 + src/lib/realtime/bus.ts | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/src/app/api/realtime/route.ts b/src/app/api/realtime/route.ts index 2304899..7538aed 100644 --- a/src/app/api/realtime/route.ts +++ b/src/app/api/realtime/route.ts @@ -29,6 +29,7 @@ export async function GET(req: NextRequest) { send: (data) => controller.enqueue(encoder.encode(data)), userId: user ? Number(user.id) : undefined, events: channel ? new Set(["presence"]) : undefined, + presenceChannel: channel ?? undefined, }; subscribe(client); diff --git a/src/hooks/useRealtimePresence.ts b/src/hooks/useRealtimePresence.ts index 7011686..ad802b9 100644 --- a/src/hooks/useRealtimePresence.ts +++ b/src/hooks/useRealtimePresence.ts @@ -41,6 +41,7 @@ export function useRealtimePresence(channel: string, active: boolean, observe = } catch { return; } + if (detail.channel !== channel) return; if (detail.action === "snapshot") setParticipants(detail.participants ?? []); if ((detail.action === "join" || detail.action === "update") && detail.participant) { setParticipants((current) => [ diff --git a/src/lib/realtime/bus.ts b/src/lib/realtime/bus.ts index b99ec49..463c85b 100644 --- a/src/lib/realtime/bus.ts +++ b/src/lib/realtime/bus.ts @@ -2,6 +2,7 @@ export interface SSEEventClient { send: (data: string) => void; events?: Set; userId?: number; + presenceChannel?: string; } const clients = new Set(); @@ -21,8 +22,23 @@ export function clientCount(): number { export function broadcast(event: string, data: unknown): number { const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`; + const presenceChannel = + event === "presence" && + typeof data === "object" && + data !== null && + "channel" in data && + typeof data.channel === "string" + ? data.channel + : undefined; for (const client of clients) { if (client.events && !client.events.has(event)) continue; + if ( + event === "presence" && + client.presenceChannel !== undefined && + client.presenceChannel !== presenceChannel + ) { + continue; + } try { client.send(payload); } catch {