import { useEffect, useMemo, useRef, useState } from 'react'; import { useChat } from '../context/ChatProvider'; import { buildSelectedAssetGreeting } from '../utils/mindspaceChatContext'; import { shouldShowChatMessage } from '../utils/message'; import type { Message, MindSpaceChatContext, MindSpaceSaveCategory, PortalUser } from '../types'; import { SpaceChatFab } from './SpaceChatFab'; import { SpaceChatPanel } from './SpaceChatPanel'; const SELECTED_ASSET_GREETING_ID = 'mindspace-selected-asset-greeting'; function buildSelectedAssetGreetingMessage( asset: NonNullable[number], ): Message { const text = buildSelectedAssetGreeting(asset); return { id: SELECTED_ASSET_GREETING_ID, role: 'assistant', created: Math.floor(Date.now() / 1000), content: [{ type: 'text', text }], metadata: { userVisible: true, agentVisible: false, displayText: text, }, }; } export function MindSpaceSpaceChat({ context, user, onOpenFullChat, onPageSaved, open: controlledOpen, onOpenChange, variant = 'default', chatBridge, hideOpenFullChat = false, title, }: { context: MindSpaceChatContext; user: PortalUser; onOpenFullChat: () => void; onPageSaved?: (result: { kind: 'page' | 'category'; pageId?: string; categoryCode?: MindSpaceSaveCategory; }) => void; open?: boolean; onOpenChange?: (open: boolean) => void; variant?: 'default' | 'overlay'; chatBridge?: import('../hooks/usePageEditSubChat').PageEditSubChatBridge; hideOpenFullChat?: boolean; title?: string; }) { const { chatState, pendingTool, newSession, switchSession, session, messages } = useChat(); const [internalOpen, setInternalOpen] = useState(false); const open = controlledOpen ?? internalOpen; const setOpen = onOpenChange ?? setInternalOpen; const wasOpenRef = useRef(false); const restoreSessionIdRef = useRef(null); const messagesRef = useRef(messages); messagesRef.current = messages; useEffect(() => { if (chatBridge) { wasOpenRef.current = open; return; } const wasOpen = wasOpenRef.current; if (open && !wasOpen) { restoreSessionIdRef.current = session?.id ?? null; newSession(); } else if (!open && wasOpen) { if (messagesRef.current.length === 0 && restoreSessionIdRef.current) { switchSession(restoreSessionIdRef.current); } restoreSessionIdRef.current = null; } wasOpenRef.current = open; }, [chatBridge, newSession, open, session?.id, switchSession]); useEffect(() => { if (chatBridge) return; return () => { if (messagesRef.current.length === 0 && restoreSessionIdRef.current) { switchSession(restoreSessionIdRef.current); } }; }, [chatBridge, switchSession]); const prefillMessages = useMemo(() => { if (chatBridge || !open) return []; if (messages.some((message) => message.role === 'user' && shouldShowChatMessage(message))) return []; const selected = context.selectedAssets ?? []; if (selected.length !== 1) return []; return [buildSelectedAssetGreetingMessage(selected[0])]; }, [chatBridge, context.selectedAssets, messages, open]); const wrapperClass = variant === 'overlay' ? 'space-chat-stack space-chat-stack-overlay' : 'space-chat-stack'; return (
{open ? (
); }