import { InfoCircleOutlined, MessageOutlined, ShrinkOutlined, SyncOutlined } from "@ant-design/icons"; import { useApolloClient, useLazyQuery, useQuery } from "@apollo/client"; import { Badge, Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { CONVERSATION_LIST_QUERY, UNREAD_CONVERSATION_COUNT } from "../../graphql/conversations.queries"; import { toggleChatVisible } from "../../redux/messaging/messaging.actions"; import { selectChatVisible, selectSelectedConversation } from "../../redux/messaging/messaging.selectors"; import ChatConversationListComponent from "../chat-conversation-list/chat-conversation-list.component"; import ChatConversationContainer from "../chat-conversation/chat-conversation.container"; import ChatNewConversation from "../chat-new-conversation/chat-new-conversation.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import "./chat-popup.styles.scss"; import { useSocket } from "../../contexts/SocketIO/useSocket.js"; const mapStateToProps = createStructuredSelector({ selectedConversation: selectSelectedConversation, chatVisible: selectChatVisible }); const mapDispatchToProps = (dispatch) => ({ toggleChatVisible: () => dispatch(toggleChatVisible()) }); export function ChatPopupComponent({ chatVisible, selectedConversation, toggleChatVisible }) { const { t } = useTranslation(); const [pollInterval, setPollInterval] = useState(0); const { socket } = useSocket(); const client = useApolloClient(); // Apollo Client instance for cache operations // Lazy query for conversations const [getConversations, { loading, data, refetch }] = useLazyQuery(CONVERSATION_LIST_QUERY, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", skip: !chatVisible, ...(pollInterval > 0 ? { pollInterval } : {}) }); // Query for unread count when chat is not visible const { data: unreadData } = useQuery(UNREAD_CONVERSATION_COUNT, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", pollInterval: 60 * 1000 // TODO: This is a fix for now, should be coming from sockets }); // Socket connection status useEffect(() => { const handleSocketStatus = () => { if (socket?.connected) { setPollInterval(15 * 60 * 1000); // 15 minutes } else { setPollInterval(60 * 1000); // 60 seconds } }; handleSocketStatus(); if (socket) { socket.on("connect", handleSocketStatus); socket.on("disconnect", handleSocketStatus); } return () => { if (socket) { socket.off("connect", handleSocketStatus); socket.off("disconnect", handleSocketStatus); } }; }, [socket]); // Fetch conversations when chat becomes visible useEffect(() => { if (chatVisible) getConversations({ variables: { offset: 0 } }).catch((err) => { console.error(`Error fetching conversations: ${(err, err.message || "")}`); }); }, [chatVisible, getConversations]); // Get unread count from the cache const unreadCount = (() => { try { const cachedData = client.readQuery({ query: CONVERSATION_LIST_QUERY, variables: { offset: 0 } }); if (!cachedData?.conversations) { return unreadData?.messages_aggregate?.aggregate?.count; } // Aggregate unread message count return cachedData.conversations.reduce((total, conversation) => { const unread = conversation.messages_aggregate?.aggregate?.count || 0; return total + unread; }, 0); } catch (error) { console.warn("Unread count not found in cache:", error); return 0; // Fallback if not in cache } })(); return ( {chatVisible ? (
{t("messaging.labels.messaging")} refetch()} /> {!socket?.connected && {t("messaging.labels.nopush")}} toggleChatVisible()} style={{ position: "absolute", right: ".5rem", top: ".5rem" }} /> {loading ? ( ) : ( )} {selectedConversation ? : null}
) : (
toggleChatVisible()} style={{ cursor: "pointer" }}> {t("messaging.labels.messaging")}
)}
); } export default connect(mapStateToProps, mapDispatchToProps)(ChatPopupComponent);