diff --git a/packages/react-chat-example/src/index.tsx b/packages/react-chat-example/src/index.tsx index 695fbcbc..9c49bd55 100644 --- a/packages/react-chat-example/src/index.tsx +++ b/packages/react-chat-example/src/index.tsx @@ -76,7 +76,7 @@ function DragDiv() { diff --git a/packages/react-chat/src/components/Chat/ChatMessages.tsx b/packages/react-chat/src/components/Chat/ChatMessages.tsx index dd958fe4..9bc40658 100644 --- a/packages/react-chat/src/components/Chat/ChatMessages.tsx +++ b/packages/react-chat/src/components/Chat/ChatMessages.tsx @@ -94,7 +94,7 @@ function ChatUiMessage({ export function ChatMessages() { const { messages, activeChannel, contacts } = useMessengerContext(); const ref = useRef(null); - const loadingMessages = useChatScrollHandle(messages, ref, activeChannel.id); + const loadingMessages = useChatScrollHandle(messages, ref, activeChannel); const shownMessages = useMemo( () => diff --git a/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts b/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts index a29c351a..ee84afcc 100644 --- a/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts +++ b/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts @@ -1,11 +1,12 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { Messenger } from "status-communities/dist/cjs"; +import { GroupChats, Messenger } from "status-communities/dist/cjs"; const _MS_PER_DAY = 1000 * 60 * 60 * 24; export function useLoadPrevDay( chatId: string, - messenger: Messenger | undefined + messenger: Messenger | undefined, + groupChats?: GroupChats ) { const loadingPreviousMessages = useRef<{ [chatId: string]: boolean; @@ -20,7 +21,7 @@ export function useLoadPrevDay( }, [chatId]); const loadPrevDay = useCallback( - async (id: string) => { + async (id: string, groupChat?: boolean) => { if (messenger) { const endTime = lastLoadTime.current[id] ?? new Date(); const startTime = new Date(endTime.getTime() - _MS_PER_DAY); @@ -31,16 +32,25 @@ export function useLoadPrevDay( if (!loadingPreviousMessages.current[id]) { loadingPreviousMessages.current[id] = true; setLoadingMessages(true); - const amountOfMessages = await messenger.retrievePreviousMessages( - id, - startTime, - endTime - ); + let amountOfMessages = 0; + if (groupChat && groupChats) { + amountOfMessages = await groupChats.retrievePreviousMessages( + id, + startTime, + endTime + ); + } else { + amountOfMessages = await messenger.retrievePreviousMessages( + id, + startTime, + endTime + ); + } lastLoadTime.current[id] = startTime; loadingPreviousMessages.current[id] = false; setLoadingMessages(false); if (amountOfMessages === 0) { - loadPrevDay(id); + loadPrevDay(id, groupChat); } } } diff --git a/packages/react-chat/src/hooks/messenger/useMessenger.ts b/packages/react-chat/src/hooks/messenger/useMessenger.ts index b3a112c0..72b1b910 100644 --- a/packages/react-chat/src/hooks/messenger/useMessenger.ts +++ b/packages/react-chat/src/hooks/messenger/useMessenger.ts @@ -30,7 +30,7 @@ export type MessengerType = { clearNotifications: (id: string) => void; mentions: { [chatId: string]: number }; clearMentions: (id: string) => void; - loadPrevDay: (id: string) => Promise; + loadPrevDay: (id: string, groupChat?: boolean) => Promise; loadingMessages: boolean; communityData: CommunityData | undefined; contacts: Contacts; @@ -109,7 +109,6 @@ export function useMessenger( clearMentions, } = useMessages(chatId, identity, contactsClass); const [community, setCommunity] = useState(undefined); - const { loadPrevDay, loadingMessages } = useLoadPrevDay(chatId, messenger); useEffect(() => { if (identity) { @@ -127,14 +126,6 @@ export function useMessenger( } }, [messenger, communityKey, addMessage, contactsClass]); - useEffect(() => { - if (messenger && community?.chats) { - Array.from(community?.chats.values()).forEach(({ id }) => - loadPrevDay(id) - ); - } - }, [messenger, community]); - const [channels, setChannels] = useState({}); const setChannel = useCallback((channel: ChannelData) => { @@ -201,6 +192,19 @@ export function useMessenger( channels ); + const { loadPrevDay, loadingMessages } = useLoadPrevDay( + chatId, + messenger, + groupChat + ); + useEffect(() => { + if (messenger && community?.chats) { + Array.from(community?.chats.values()).forEach(({ id }) => + loadPrevDay(id) + ); + } + }, [messenger, community]); + const sendMessage = useCallback( async (messageText?: string, image?: Uint8Array) => { if (activeChannel.type === "group") { diff --git a/packages/react-chat/src/hooks/useChatScrollHandle.ts b/packages/react-chat/src/hooks/useChatScrollHandle.ts index b3901d3c..6abafcee 100644 --- a/packages/react-chat/src/hooks/useChatScrollHandle.ts +++ b/packages/react-chat/src/hooks/useChatScrollHandle.ts @@ -1,12 +1,13 @@ import { useEffect, useState } from "react"; import { useMessengerContext } from "../contexts/messengerProvider"; +import { ChannelData } from "../models/ChannelData"; import { ChatMessage } from "../models/ChatMessage"; export function useChatScrollHandle( messages: ChatMessage[], ref: React.RefObject, - activeChannelId: string + activeChannel: ChannelData ) { const { loadPrevDay, loadingMessages } = useMessengerContext(); const [scrollOnBot, setScrollOnBot] = useState(true); @@ -23,7 +24,7 @@ export function useChatScrollHandle( (ref?.current?.clientHeight ?? 0) >= (ref?.current?.scrollHeight ?? 0) ) { setScrollOnBot(true); - loadPrevDay(activeChannelId); + loadPrevDay(activeChannel.id, activeChannel.type === "group"); } } }, [messages.length, loadingMessages]); @@ -32,7 +33,7 @@ export function useChatScrollHandle( const setScroll = () => { if (ref?.current) { if (ref.current.scrollTop <= 0) { - loadPrevDay(activeChannelId); + loadPrevDay(activeChannel.id, activeChannel.type === "group"); } if ( ref.current.scrollTop + ref.current.clientHeight == diff --git a/packages/status-communities/src/groupChats.ts b/packages/status-communities/src/groupChats.ts index d8ab36d3..266705d2 100644 --- a/packages/status-communities/src/groupChats.ts +++ b/packages/status-communities/src/groupChats.ts @@ -246,4 +246,41 @@ export class GroupChats { ); wakuMessages.forEach((msg) => this.waku.relay.send(msg)); } + + /** + * Retrieve previous messages from a Waku Store node for the given chat Id. + * + */ + public async retrievePreviousMessages( + chatId: string, + startTime: Date, + endTime: Date + ): Promise { + const chat = this.chats[chatId]; + + if (!chat) + throw `Failed to retrieve messages, chat is not joined: ${chatId}`; + + const _callback = (wakuMessages: WakuMessage[], member: string): void => { + wakuMessages.forEach((wakuMessage: WakuMessage) => + this.handleWakuChatMessage(wakuMessage, chat, member) + ); + }; + + const amountOfMessages: number[] = []; + + await Promise.all( + chat.members.map(async (member) => { + const topic = await getNegotiatedTopic(this.identity, member); + const msgLength = ( + await this.waku.store.queryHistory([topic], { + timeFilter: { startTime, endTime }, + callback: (msg) => _callback(msg, member), + }) + ).length; + amountOfMessages.push(msgLength); + }) + ); + return amountOfMessages.reduce((a, b) => a + b); + } }