import { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { useQueryClient } from "@tanstack/react-query"; import { ChevronDown, ChevronUp, X } from "lucide-react"; import { closeChat, initDock, notifyIncoming, toggleMinimize, useDockChats, type DockChat } from "../lib/chatDock"; import { onMessage, onUnread } from "../lib/messagesSocket"; import * as e2ee from "../lib/e2ee"; import Avatar from "./Avatar"; import ChatThread from "./ChatThread"; // The Messenger-style floating chat dock: open conversations live here, bottom-right, across // page navigation (state persisted per user). Always mounted (for human users) so it also owns // the app-wide live-message subscription and restores this device's unlock state on load. export default function ChatDock({ meId }: { meId: number }) { const qc = useQueryClient(); const chats = useDockChats(); // Restore the per-device unlocked key and the persisted dock windows once, app-wide. useEffect(() => { initDock(meId); e2ee.loadFromDevice(meId); }, [meId]); // Live delivery: refresh the conversation list, unread badge, and the affected thread; and // for an INCOMING message, open or flash that partner's dock window. useEffect( () => onMessage(({ message: m, from }) => { qc.invalidateQueries({ queryKey: ["conversations"] }); qc.invalidateQueries({ queryKey: ["message-unread"] }); const partnerId = m.sender_id === meId ? m.recipient_id : m.sender_id; qc.invalidateQueries({ queryKey: ["thread", partnerId] }); // Auto-open/flash only for messages from someone else (not my own echo) and only for // real user conversations. if (m.kind === "user" && m.sender_id !== meId && from) { notifyIncoming({ id: from.id, name: from.name, avatar_url: from.avatar_url }); } }), [qc, meId] ); // Live badge sync: another tab/device read a thread → refresh this tab's unread count + list. useEffect( () => onUnread(() => { qc.invalidateQueries({ queryKey: ["message-unread"] }); qc.invalidateQueries({ queryKey: ["conversations"] }); }), [qc] ); if (chats.length === 0) return null; return (