import { useContext, useEffect, useState } from 'react'; import _ from 'lodash'; import { ChatContext, ACTIONS } from './context'; import { UsersContext } from '../users-context/context'; import { makeCall } from '/imports/ui/services/api'; import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger'; let usersData = {}; let messageQueue = []; const CHAT_CONFIG = Meteor.settings.public.chat; const ITENS_PER_PAGE = CHAT_CONFIG.itemsPerPage; const TIME_BETWEEN_FETCHS = CHAT_CONFIG.timeBetweenFetchs; const getMessagesBeforeJoinCounter = async () => { const counter = await makeCall('chatMessageBeforeJoinCounter'); return counter; }; const startSyncMessagesbeforeJoin = async (dispatch) => { const chatsMessagesCount = await getMessagesBeforeJoinCounter(); const pagesPerChat = chatsMessagesCount.map(chat => ({ ...chat, pages: Math.ceil(chat.count / ITENS_PER_PAGE), syncedPages: 0 })); const syncRoutine = async (chatsToSync) => { if (!chatsToSync.length) return; const pagesToFetch = [...chatsToSync].sort((a, b) => a.pages - b.pages); const chatWithLessPages = pagesToFetch[0]; chatWithLessPages.syncedPages += 1; const messagesFromPage = await makeCall('fetchMessagePerPage', chatWithLessPages.chatId, chatWithLessPages.syncedPages); if (messagesFromPage.length) { dispatch({ type: ACTIONS.ADDED, value: messagesFromPage, }); dispatch({ type: ACTIONS.SYNC_STATUS, value: { chatId: chatWithLessPages.chatId, percentage: Math.floor((chatWithLessPages.syncedPages / chatWithLessPages.pages) * 100), }, }); } await new Promise(r => setTimeout(r, TIME_BETWEEN_FETCHS)); syncRoutine(pagesToFetch.filter(chat => !(chat.syncedPages > chat.pages))); }; syncRoutine(pagesPerChat); }; const Adapter = () => { const usingChatContext = useContext(ChatContext); const { dispatch } = usingChatContext; const usingUsersContext = useContext(UsersContext); const { users } = usingUsersContext; const [syncStarted, setSync] = useState(true); ChatLogger.trace('chatAdapter::body::users', users); useEffect(() => { const connectionStatus = Meteor.status(); if (connectionStatus.connected && !syncStarted) { setSync(true); startSyncMessagesbeforeJoin(dispatch); } }, [Meteor.status().connected, syncStarted]); useEffect(() => { usersData = users; }, [usingUsersContext]); useEffect(() => { if (!Meteor.status().connected) return; setSync(false); dispatch({ type: ACTIONS.CLEAR_ALL, }); const throttledDispatch = _.throttle(() => { const dispatchedMessageQueue = [...messageQueue]; messageQueue = []; dispatch({ type: ACTIONS.ADDED, value: dispatchedMessageQueue, }); }, 1000, { trailing: true, leading: true }); Meteor.connection._stream.socket.addEventListener('message', (msg) => { if (msg.data.indexOf('{"msg":"added","collection":"group-chat-msg"') != -1) { const parsedMsg = JSON.parse(msg.data); if (parsedMsg.msg === 'added') { messageQueue.push(parsedMsg.fields); throttledDispatch(); } } if (msg.data.indexOf('{"msg":"removed","collection":"group-chat-msg"') != -1) { dispatch({ type: ACTIONS.REMOVED, }); } }); }, [Meteor.status().connected]); return null; }; export default Adapter;