diff --git a/frontend/src/components/chat/ChatMessageView.tsx b/frontend/src/components/chat/ChatMessageView.tsx index 8c4eb9e..b5a2845 100644 --- a/frontend/src/components/chat/ChatMessageView.tsx +++ b/frontend/src/components/chat/ChatMessageView.tsx @@ -13,15 +13,13 @@ import CloseIcon from '@mui/icons-material/Close'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { nextcloudApi } from '../../services/nextcloud'; import { useChat } from '../../contexts/ChatContext'; -import { useLayout } from '../../contexts/LayoutContext'; import ChatMessage from './ChatMessage'; import type { NextcloudMessage } from '../../types/nextcloud.types'; const LONG_POLL_TIMEOUT = 25; const ChatMessageView: React.FC = () => { - const { selectedRoomToken, selectRoom, rooms, loginName } = useChat(); - const { chatPanelOpen } = useLayout(); + const { selectedRoomToken, selectRoom, rooms, loginName, isActive } = useChat(); const queryClient = useQueryClient(); const messagesEndRef = useRef(null); const scrollContainerRef = useRef(null); @@ -56,7 +54,7 @@ const ChatMessageView: React.FC = () => { // Initial fetch + long-poll loop for near-instant message delivery useEffect(() => { - if (!selectedRoomToken || !chatPanelOpen) return; + if (!selectedRoomToken || !isActive) return; let cancelled = false; let currentAbort: AbortController | null = null; @@ -134,7 +132,7 @@ const ChatMessageView: React.FC = () => { cancelled = true; currentAbort?.abort(); }; - }, [selectedRoomToken, chatPanelOpen, queryClient, fetchReactions]); + }, [selectedRoomToken, isActive, queryClient, fetchReactions]); const room = rooms.find((r) => r.token === selectedRoomToken); const isOneToOne = room?.type === 1; @@ -149,12 +147,12 @@ const ChatMessageView: React.FC = () => { // Mark room as read when first opened useEffect(() => { - if (selectedRoomToken && chatPanelOpen) { + if (selectedRoomToken && isActive) { nextcloudApi.markAsRead(selectedRoomToken).then(() => { queryClient.invalidateQueries({ queryKey: ['nextcloud', 'rooms'] }); }).catch(() => {}); } - }, [selectedRoomToken, chatPanelOpen, queryClient]); + }, [selectedRoomToken, isActive, queryClient]); // Smart scroll: instant on initial load, smooth only when user is near bottom useEffect(() => { diff --git a/frontend/src/contexts/ChatContext.tsx b/frontend/src/contexts/ChatContext.tsx index 59f8ebe..7b4a474 100644 --- a/frontend/src/contexts/ChatContext.tsx +++ b/frontend/src/contexts/ChatContext.tsx @@ -12,6 +12,7 @@ interface ChatContextType { selectRoom: (token: string | null) => void; connected: boolean; loginName: string | null; + isActive: boolean; } const ChatContext = createContext(undefined); @@ -119,6 +120,7 @@ export const ChatProvider: React.FC = ({ children }) => { selectRoom, connected, loginName, + isActive, }; return {children};