"use client"; // App-wide in-app notifications. Uses the shared dashboard socket to watch activity across ALL of // the user's threads (via the adapter's subscribeActivity) and shows a clickable toast when a new // message arrives — unless you're already on the Messenger tab (you'd see it live there). Clicking // deep-links to the conversation. Renders nothing. import { useEffect, useMemo, useRef } from "react"; import { useAppShell, useAuth } from "@abe-kap/appshell-sdk/react"; import type { MessagingAdapter } from "@insignia/iios-messaging-ui"; import { isShellConfigured } from "@/lib/appshell"; import { useRealtime } from "@/lib/realtime"; import { CrmMessagingAdapter, type DataDoor } from "@/lib/crm-messaging-adapter"; import { useToast } from "./ui"; const SHELL = isShellConfigured(); export function NotificationCenter({ active, onNavigate }: { active: string; onNavigate: (surface: "messenger" | "inbox", threadId: string) => void }) { const socket = useRealtime(); const { sdk } = useAppShell(); const { user } = useAuth(); const toast = useToast(); const me = user?.id; // Keep the current tab readable inside the (stable) subscription callback. const activeRef = useRef(active); activeRef.current = active; const adapter = useMemo( () => (me && socket ? new CrmMessagingAdapter(sdk as unknown as DataDoor, me, socket) : null), [sdk, me, socket], ); useEffect(() => { if (!SHELL || !adapter?.subscribeActivity) return; return adapter.subscribeActivity(({ threadId, message }) => { if (message.actorId === me) return; // never notify me about my own message if (activeRef.current === "messenger") return; // already watching chat live toast.push({ tone: "info", title: "New message", desc: message.text?.slice(0, 90) || "You have a new message", onClick: () => onNavigate("messenger", threadId), }); }); }, [adapter, me, toast, onNavigate]); return null; }