diff --git a/src/App.jsx b/src/App.jsx index 5154715..6082c63 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -85,7 +85,7 @@ function AppContent() { // Triggers ChatInterface to reload messages without switching sessions const [externalMessageUpdate, setExternalMessageUpdate] = useState(0); - const { ws, sendMessage, messages } = useWebSocket(); + const { ws, sendMessage, latestMessage } = useWebSocket(); // Ref to track loading progress timeout for cleanup const loadingProgressTimeoutRef = useRef(null); @@ -179,9 +179,7 @@ function AppContent() { // Handle WebSocket messages for real-time project updates useEffect(() => { - if (messages.length > 0) { - const latestMessage = messages[messages.length - 1]; - + if (latestMessage) { // Handle loading progress updates if (latestMessage.type === 'loading_progress') { if (loadingProgressTimeoutRef.current) { @@ -281,7 +279,7 @@ function AppContent() { loadingProgressTimeoutRef.current = null; } }; - }, [messages, selectedProject, selectedSession, activeSessions]); + }, [latestMessage, selectedProject, selectedSession, activeSessions]); const fetchProjects = async () => { try { @@ -920,7 +918,7 @@ function AppContent() { setActiveTab={setActiveTab} ws={ws} sendMessage={sendMessage} - messages={messages} + latestMessage={latestMessage} isMobile={isMobile} isPWA={isPWA} onMenuClick={() => setSidebarOpen(true)} diff --git a/src/components/ChatInterface.jsx b/src/components/ChatInterface.jsx index e8ad9a4..d3d7bea 100644 --- a/src/components/ChatInterface.jsx +++ b/src/components/ChatInterface.jsx @@ -1862,7 +1862,7 @@ const ImageAttachment = ({ file, onRemove, uploadProgress, error }) => { // - onReplaceTemporarySession: Called to replace temporary session ID with real WebSocket session ID // // This ensures uninterrupted chat experience by pausing sidebar refreshes during conversations. -function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, messages, onFileOpen, onInputFocusChange, onSessionActive, onSessionInactive, onSessionProcessing, onSessionNotProcessing, processingSessions, onReplaceTemporarySession, onNavigateToSession, onShowSettings, autoExpandTools, showRawParameters, showThinking, autoScrollToBottom, sendByCtrlEnter, externalMessageUpdate, onTaskClick, onShowAllTasks }) { +function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, latestMessage, onFileOpen, onInputFocusChange, onSessionActive, onSessionInactive, onSessionProcessing, onSessionNotProcessing, processingSessions, onReplaceTemporarySession, onNavigateToSession, onShowSettings, autoExpandTools, showRawParameters, showThinking, autoScrollToBottom, sendByCtrlEnter, externalMessageUpdate, onTaskClick, onShowAllTasks }) { const { tasksEnabled, isTaskMasterInstalled } = useTasksSettings(); const { t } = useTranslation('chat'); const [input, setInput] = useState(() => { @@ -3244,8 +3244,7 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess useEffect(() => { // Handle WebSocket messages - if (messages.length > 0) { - const latestMessage = messages[messages.length - 1]; + if (latestMessage) { const messageData = latestMessage.data?.message || latestMessage.data; // Filter messages by session ID to prevent cross-session interference @@ -4070,7 +4069,7 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess } } - }, [messages]); + }, [latestMessage]); // Load file list when project changes useEffect(() => { diff --git a/src/components/MainContent.jsx b/src/components/MainContent.jsx index 21665df..c1db1b5 100644 --- a/src/components/MainContent.jsx +++ b/src/components/MainContent.jsx @@ -36,7 +36,7 @@ function MainContent({ setActiveTab, ws, sendMessage, - messages, + latestMessage, isMobile, isPWA, // ! Unused onMenuClick, @@ -477,7 +477,7 @@ function MainContent({ selectedSession={selectedSession} ws={ws} sendMessage={sendMessage} - messages={messages} + latestMessage={latestMessage} onFileOpen={handleFileOpen} onInputFocusChange={onInputFocusChange} onSessionActive={onSessionActive} diff --git a/src/contexts/TaskMasterContext.jsx b/src/contexts/TaskMasterContext.jsx index a508fa3..77e996f 100644 --- a/src/contexts/TaskMasterContext.jsx +++ b/src/contexts/TaskMasterContext.jsx @@ -42,7 +42,7 @@ export const useTaskMaster = () => { export const TaskMasterProvider = ({ children }) => { // Get WebSocket messages from shared context to avoid duplicate connections - const { messages } = useWebSocket(); + const { latestMessage } = useWebSocket(); // Authentication context const { user, token, isLoading: authLoading } = useAuth(); @@ -238,9 +238,8 @@ export const TaskMasterProvider = ({ children }) => { } }, [currentProject?.name, user, token, refreshTasks]); - // Handle WebSocket messages for TaskMaster updates + // Handle WebSocket latestMessage for TaskMaster updates useEffect(() => { - const latestMessage = messages[messages.length - 1]; if (!latestMessage) return; @@ -268,7 +267,7 @@ export const TaskMasterProvider = ({ children }) => { // Ignore non-TaskMaster messages break; } - }, [messages, refreshProjects, refreshTasks, refreshMCPStatus, currentProject]); + }, [latestMessage, refreshProjects, refreshTasks, refreshMCPStatus, currentProject]); // Context value const contextValue = { diff --git a/src/contexts/WebSocketContext.tsx b/src/contexts/WebSocketContext.tsx index 34bbd8b..3af9c41 100644 --- a/src/contexts/WebSocketContext.tsx +++ b/src/contexts/WebSocketContext.tsx @@ -5,7 +5,7 @@ import { IS_PLATFORM } from '../constants/config'; type WebSocketContextType = { ws: WebSocket | null; sendMessage: (message: any) => void; - messages: any[]; + latestMessage: any | null; isConnected: boolean; }; @@ -28,8 +28,8 @@ const buildWebSocketUrl = (token: string | null) => { const useWebSocketProviderState = (): WebSocketContextType => { const wsRef = useRef(null); - const unmountedRef = useRef(false); - const [messages, setMessages] = useState([]); + const unmountedRef = useRef(false); // Track if component is unmounted + const [latestMessage, setLatestMessage] = useState(null); const [isConnected, setIsConnected] = useState(false); const reconnectTimeoutRef = useRef(null); const { token } = useAuth(); @@ -66,7 +66,7 @@ const useWebSocketProviderState = (): WebSocketContextType => { websocket.onmessage = (event) => { try { const data = JSON.parse(event.data); - setMessages(prev => [...prev, data]); + setLatestMessage(data); } catch (error) { console.error('Error parsing WebSocket message:', error); }