import { useState, useEffect, useRef } from 'react'; import { ChatObject, MessageObject, PersonObject } from '../interfaces'; import { getDateTime } from '../components/util/dateTime'; import { getChat, getMessages, newMessage } from '../actions'; import { animateScroll } from 'react-scroll'; import { scrollToBottom } from './shared'; import { ChatAuthHeaders } from '../interfaces'; const messageCountIterator = 50; export const sortChats = (chats: ChatObject[]) => { return chats.sort((a: ChatObject, b: ChatObject) => { const aDate = a.last_message && a.last_message.created ? getDateTime(a.last_message.created) : getDateTime(a.created); const bDate = b.last_message && b.last_message.created ? getDateTime(b.last_message.created) : getDateTime(b.created); return new Date(bDate).getTime() - new Date(aDate).getTime(); }); }; export const sortMessages = (messages: MessageObject[]) => { return messages.sort((a: MessageObject, b: MessageObject) => { return new Date(b.created).getTime() - new Date(a.created).getTime(); }); }; export const useSingleChatLogic = ( projectId: string, chatId: string, chatAccessKey: string, httpUrl?: string ) => { const host = httpUrl ? httpUrl : 'https://api.chatengine.io'; const headers: ChatAuthHeaders = { 'Public-Key': projectId, 'Chat-ID': chatId, 'Access-Key': chatAccessKey, }; // Data const [activeChatId, setActiveChatId] = useState(); const [chat, setChat] = useState(); const [messages, setMessages] = useState([]); const [peopleToInvite, setPeopleToInvite] = useState([]); // State const [hasMoreChats, setHasMoreChats] = useState(false); const [hasMoreMessages, setHasMoreMessages] = useState(false); const [isChatFeedAtBottom, setIsChatFeedAtBottom] = useState(false); const [isChatFeedLoading, setIsChatFeedLoading] = useState(true); // Subscribe to Chat & Message Count const chatCountRef = useRef(0); chatCountRef.current = chat ? 1 : 0; const messageCountRef = useRef(0); messageCountRef.current = messages.length; // Fetch data on mount const didMountRef = useRef(false); useEffect(() => { if (!didMountRef.current) { didMountRef.current = true; fetchSingleChatData(); } }, []); async function fetchSingleChatData() { getChat(host, headers, chatId, (chat) => { setChat(chat); onChatCardClick(chat.id); }); } async function onEditChat(chat: ChatObject) { setChat(chat); } async function onDeleteChat() { setChat(undefined); setActiveChatId(undefined); } async function onGetMessages(chatId: number, messages: MessageObject[]) { setHasMoreMessages( messages.length >= messageCountRef.current + messageCountIterator ); setMessages(messages); setIsChatFeedLoading(false); void chatId; } async function onNewMessage(chatId: number, newMessage: MessageObject) { if (activeChatId === chatId) { const otherMessages = messages ? messages.filter((message) => message.created !== newMessage.created) : []; const newMessages = otherMessages.concat(newMessage); const sortedMessages = sortMessages(newMessages); setMessages(sortedMessages); if (isChatFeedAtBottom) { scrollToBottom(333, `ce-message-list-${activeChatId}`); } } } async function onEditMessage(chatId: number, newMessage: MessageObject) { if (chatId === activeChatId) { const otherMessages = messages ? messages.filter((message) => message.id !== newMessage.id) : []; const newMessages = [newMessage].concat(otherMessages); const sortedMessages = sortMessages(newMessages); setMessages(sortedMessages); } } async function onDeleteMessage(chatId: number, oldMessage: MessageObject) { if (chatId === activeChatId) { const newMessages = messages ? messages.filter((message) => message.id !== oldMessage.id) : []; setMessages(newMessages); } } async function onConnect() { fetchSingleChatData(); } async function onAuthFail() {} async function onChatCardClick(activeChatId: number) { setActiveChatId(activeChatId); getMessages( host, headers, activeChatId, messageCountIterator, (chatId, messages) => { onGetMessages(chatId, messages); scrollToBottom(0, `ce-message-list-${activeChatId}`); } ); } async function onMessageFormSubmit(message: MessageObject) { const newMessages = messages?.concat(message); setMessages(newMessages); newMessage(host, headers, activeChatId, message, () => {}); setTimeout(() => { scrollToBottom(333, `ce-message-list-${activeChatId}`); }, 100); } async function onBottomMessageShow() { setIsChatFeedAtBottom(true); } async function onBottomMessageHide() { setIsChatFeedAtBottom(false); } async function onMessageLoaderShow() { const scrollContainerId = `ce-message-list-${activeChatId}`; const messageListId = `ce-message-list-content-${activeChatId}`; const currentElement = document.getElementById(messageListId); let currentHeight = currentElement ? currentElement.clientHeight : 0; activeChatId && getMessages( host, headers, activeChatId, messageCountRef.current + messageCountIterator, (chatId, messages) => { onGetMessages(chatId, messages); setTimeout(() => { const element = document.getElementById(messageListId); if (element) { animateScroll.scrollTo(element.clientHeight - currentHeight, { duration: 333, containerId: scrollContainerId, }); } }, 1000); } ); } async function onMessageLoaderHide() {} async function onIsTyping(id: number, person: PersonObject) { void id, person; } return { // Socket Hooks onConnect, onAuthFail, onEditChat, onDeleteChat, onGetMessages, onNewMessage, onEditMessage, onDeleteMessage, onIsTyping, // Auth Data projectId, chatId, chatAccessKey, httpUrl, wsUrl: httpUrl && httpUrl.replace('http', 'ws'), // Chat Data activeChatId, setActiveChatId, chat, messages, setMessages, peopleToInvite, setPeopleToInvite, // Chat State hasMoreChats, setHasMoreChats, hasMoreMessages, setHasMoreMessages, isChatFeedAtBottom, setIsChatFeedAtBottom, isChatFeedLoading, setIsChatFeedLoading, // Component Hooks onChatCardClick, onMessageLoaderShow, onMessageLoaderHide, onBottomMessageShow, onBottomMessageHide, onMessageFormSubmit, }; };