Add loading history in group chats (#139)

This commit is contained in:
Szymon Szlachtowicz 2021-11-29 10:30:10 +01:00 committed by GitHub
parent 0742fa3635
commit 9592f7eab3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 24 deletions

View File

@ -76,7 +76,7 @@ function DragDiv() {
<ReactChat
theme={theme ? lightTheme : darkTheme}
communityKey={
"0x0229d71fb62c14ec0370d2507ef7e13f1d53ddf1170db3babb5710fd113d0d94f9"
"0x0235564b1b402e8f6ad540f4da0f6384fb828b8f7bb5a34942aa03719041b8b793"
}
fetchMetadata={fetchMetadata}
/>

View File

@ -94,7 +94,7 @@ function ChatUiMessage({
export function ChatMessages() {
const { messages, activeChannel, contacts } = useMessengerContext();
const ref = useRef<HTMLHeadingElement>(null);
const loadingMessages = useChatScrollHandle(messages, ref, activeChannel.id);
const loadingMessages = useChatScrollHandle(messages, ref, activeChannel);
const shownMessages = useMemo(
() =>

View File

@ -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(
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);
}
}
}

View File

@ -30,7 +30,7 @@ export type MessengerType = {
clearNotifications: (id: string) => void;
mentions: { [chatId: string]: number };
clearMentions: (id: string) => void;
loadPrevDay: (id: string) => Promise<void>;
loadPrevDay: (id: string, groupChat?: boolean) => Promise<void>;
loadingMessages: boolean;
communityData: CommunityData | undefined;
contacts: Contacts;
@ -109,7 +109,6 @@ export function useMessenger(
clearMentions,
} = useMessages(chatId, identity, contactsClass);
const [community, setCommunity] = useState<Community | undefined>(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<ChannelsData>({});
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") {

View File

@ -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<HTMLHeadingElement>,
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 ==

View File

@ -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<number> {
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);
}
}