import { useCallback, useEffect, useState } from "react"; import { backend } from "../backend"; import { ChatManager } from ".."; import { Chat, Message } from './types'; export interface UseChatResult { chat: Chat | null | undefined; chatLoadedAt: number; messages: Message[]; messagesToDisplay: Message[]; leaf: Message | null | undefined; } export function useChat(chatManager: ChatManager, id: string | undefined | null, share = false): UseChatResult { const [chat, setChat] = useState(null); const [_, setVersion] = useState(0); // eslint-disable-line @typescript-eslint/no-unused-vars // used to prevent auto-scroll when chat is first opened const [chatLoadedAt, setLoadedAt] = useState(0); const update = useCallback(async () => { if (id) { if (!share) { const c = chatManager.get(id); if (c) { setChat(c); setVersion(v => v + 1); return; } } else { const c = await backend.current?.getSharedChat(id); if (c) { setChat(c); setVersion(v => v + 1); return; } } } setChat(null); }, [id, share, chatManager]); useEffect(() => { if (id) { update(); chatManager.on(id, update); setChat(chatManager.get(id)); setLoadedAt(Date.now()); } else { setChat(null); setLoadedAt(0); } return () => { if (id) { chatManager.off(id, update); } }; }, [id, update, chatManager]); const leaf = chat?.messages.mostRecentLeaf(); let messages: Message[] = []; let messagesToDisplay: Message[] = []; if (leaf) { messages = (chat?.messages.getMessageChainTo(leaf?.id) || []); messagesToDisplay = messages.filter(m => ['user', 'assistant'].includes(m.role)) || []; } return { chat, chatLoadedAt, messages, messagesToDisplay, leaf, }; }