Mercurial
view love/epi/src/components/ChatUI/Composer.tsx @ 71:75de5903355c
Giagantic changes that update Dowa library to be more align with stb style array and hashmap. Updated Seobeo to be caching on server side instead of file level caching. Deleted bunch of things I don't really use.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Sun, 28 Dec 2025 20:34:22 -0800 |
| parents | cf9caa4abc3e |
| children |
line wrap: on
line source
import { useEffect, useRef } from 'react'; import type { ReactNode } from 'react'; import { SendHorizonal, Square } from 'lucide-react'; import { useComposer } from '@/hooks/useComposer'; import { useChat } from '@/hooks/useChat'; import { broadcastDone } from '@/hooks/useChatWebsocket'; import { apiUrl } from '@/utils'; import { currentChatId } from '@/atoms/chatAtoms'; import { useAtom } from 'jotai'; import { useNavigate } from '@tanstack/react-router'; interface ComposerProps { chatId: string; } export function Composer({ chatId }: ComposerProps): ReactNode { const { text, setText, isSending, isDisabled, setSending } = useComposer(); const [_, setCurrentChatId] = useAtom(currentChatId); const { sendUserMessage } = useChat(chatId); const textareaRef = useRef<HTMLTextAreaElement>(null); // Auto-resize useEffect(() => { const el = textareaRef.current; if (el) { el.style.height = 'auto'; el.style.height = `${el.scrollHeight}px`; } }, [text]); const navigate = useNavigate(); const handleSubmit = async () => { console.log('before'); // Stoping the calls if (isSending) { console.log('called'); broadcastDone(chatId); return; } // Don't send if it is diabled or no text if (isDisabled || !text.trim()) return; let newChatId: string = ''; if (!chatId || chatId === 'new') { const res = await fetch(apiUrl('/chats'), { method: 'POST' }); const data = await res.json(); await navigate( { to: '/chat/$chatId', params: { chatId: data.id } }, ); console.log('problem: 1'); setCurrentChatId(data.id); newChatId = data.id; } const message = text.trim(); setSending(); setText(''); sendUserMessage(message, newChatId); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(); } }; return ( <div className="border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900"> <div className="max-w-4xl mx-auto p-4"> <div className="flex items-end gap-3 bg-gray-50 dark:bg-gray-800/50 rounded-2xl px-4 py-3 shadow-sm ring-1 ring-gray-200 dark:ring-gray-700 focus-within:ring-2 focus-within:ring-blue-500"> <textarea ref={textareaRef} value={text} onChange={(e) => setText(e.target.value)} onKeyDown={handleKeyDown} placeholder="Send a message..." rows={1} className="flex-1 resize-none bg-transparent outline-none text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 text-base leading-6 overflow-hidden max-h-96" /> <button onClick={handleSubmit} disabled={isDisabled} className={`w-10 h-10 rounded-full flex items-center justify-center transition-all ${ isDisabled ? 'bg-gray-300 dark:bg-gray-700 text-gray-500' : isSending ? 'bg-red-500 hover:bg-red-600 text-white' : 'bg-blue-500 hover:bg-blue-600 text-white' }`} > {isSending ? <Square className="w-5 h-5" /> : <SendHorizonal className="w-5 h-5" />} </button> </div> </div> </div> ); }