feat(web): add chat UI with WebSocket streaming and conversation persistence
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
46
web/client/src/hooks/useChat.ts
Normal file
46
web/client/src/hooks/useChat.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { chatSocket } from '@/lib/websocket';
|
||||
import type { Message } from '@/types';
|
||||
|
||||
export function useChat(conversationId: string | null) {
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [connected, setConnected] = useState(false);
|
||||
const pendingRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
chatSocket.connect();
|
||||
|
||||
chatSocket.on('connected', () => setConnected(true));
|
||||
chatSocket.on('history', (data) => {
|
||||
setMessages((data.messages as Message[]) || []);
|
||||
});
|
||||
chatSocket.on('message', (data) => {
|
||||
setMessages((prev) => [...prev, data as unknown as Message]);
|
||||
});
|
||||
|
||||
return () => {
|
||||
chatSocket.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (conversationId && connected && !pendingRef.current) {
|
||||
pendingRef.current = true;
|
||||
chatSocket.send('init', { conversationId });
|
||||
}
|
||||
if (!conversationId) {
|
||||
pendingRef.current = false;
|
||||
setMessages([]);
|
||||
}
|
||||
}, [conversationId, connected]);
|
||||
|
||||
const send = useCallback((content: string) => {
|
||||
chatSocket.send('chat', { content });
|
||||
}, []);
|
||||
|
||||
const createConversation = useCallback((title: string, accountId?: string) => {
|
||||
chatSocket.send('create_conversation', { title, accountId });
|
||||
}, []);
|
||||
|
||||
return { messages, connected, send, createConversation };
|
||||
}
|
||||
Reference in New Issue
Block a user