diff --git a/frontend/src/components/ChatWindow.jsx b/frontend/src/components/ChatWindow.jsx index fbf85887..687654c1 100644 --- a/frontend/src/components/ChatWindow.jsx +++ b/frontend/src/components/ChatWindow.jsx @@ -22,15 +22,21 @@ export default function ChatWindow({ messages = [], loading = false, onSend, onD const [showPlusMenu, setShowPlusMenu] = useState(false); const [showTemplateDialog, setShowTemplateDialog] = useState(false); const [selectedTemplate, setSelectedTemplate] = useState(null); + const [localReactions, setLocalReactions] = useState({}); + const [hoveredStatsId, setHoveredStatsId] = useState(null); + const [confirmDeleteId, setConfirmDeleteId] = useState(null); + const bottomRef = useRef(null); const textareaRef = useRef(null); const plusMenuRef = useRef(null); + const REACTION_EMOJIS = ["👍", "❤️", "🔥", "👏", "💡"]; + // Re-sync input and search state whenever sessionId changes useEffect(() => { if (!sessionId) return; setInput(localStorage.getItem(`localmind_draft_${sessionId}`) || ""); - setSearchTerm(localStorage.getItem(`localmind_search_${sessionId}`) || ""); + SearchTerm(localStorage.getItem(`localmind_search_${sessionId}`) || ""); }, [sessionId]); // Sync draft message input to localStorage on edit @@ -60,11 +66,24 @@ export default function ChatWindow({ messages = [], loading = false, onSend, onD } }, [messages]); - const [localReactions, setLocalReactions] = useState({}); - const [hoveredStatsId, setHoveredStatsId] = useState(null); - const [confirmDeleteId, setConfirmDeleteId] = useState(null); + useEffect(() => { + const textarea = textareaRef.current; + if (!textarea) return; + textarea.style.height = "auto"; + textarea.style.height = `${Math.min(textarea.scrollHeight, 160)}px`; + }, [input]); - const REACTION_EMOJIS = ["👍", "❤️", "🔥", "👏", "💡"]; + useEffect(() => { setLocalReactions({}); }, [sessionId]); + + useEffect(() => { + function handleClickOutside(e) { + if (plusMenuRef.current && !plusMenuRef.current.contains(e.target)) { + setShowPlusMenu(false); + } + } + if (showPlusMenu) document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, [showPlusMenu]); async function handleReactionToggle(messageId, emoji) { if (!messageId || typeof messageId === "string") { @@ -159,25 +178,6 @@ export default function ChatWindow({ messages = [], loading = false, onSend, onD ); - useEffect(() => { - const textarea = textareaRef.current; - if (!textarea) return; - textarea.style.height = "auto"; - textarea.style.height = `${Math.min(textarea.scrollHeight, 160)}px`; - }, [input]); - - useEffect(() => { setLocalReactions({}); }, [sessionId]); - - useEffect(() => { - function handleClickOutside(e) { - if (plusMenuRef.current && !plusMenuRef.current.contains(e.target)) { - setShowPlusMenu(false); - } - } - if (showPlusMenu) document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, [showPlusMenu]); - function handleSelectTemplate(template) { setSelectedTemplate(template); setShowTemplateDialog(false); diff --git a/frontend/src/components/ChatWindow.test.jsx b/frontend/src/components/ChatWindow.test.jsx index f1e6393a..5686b5ac 100644 --- a/frontend/src/components/ChatWindow.test.jsx +++ b/frontend/src/components/ChatWindow.test.jsx @@ -1,4 +1,5 @@ // @vitest-environment jsdom +import React from 'react'; import { render, screen, fireEvent, act, cleanup } from '@testing-library/react'; import { vi, describe, test, expect, beforeEach, afterEach } from 'vitest'; import * as jestDomMatchers from "@testing-library/jest-dom/matchers"; @@ -30,6 +31,7 @@ Object.assign(navigator, { beforeEach(() => { window.HTMLElement.prototype.scrollIntoView = vi.fn(); + localStorage.clear(); }); afterEach(() => {