Add loading history in group chats (#139)
This commit is contained in:
parent
0742fa3635
commit
9592f7eab3
|
@ -76,7 +76,7 @@ function DragDiv() {
|
|||
<ReactChat
|
||||
theme={theme ? lightTheme : darkTheme}
|
||||
communityKey={
|
||||
"0x0229d71fb62c14ec0370d2507ef7e13f1d53ddf1170db3babb5710fd113d0d94f9"
|
||||
"0x0235564b1b402e8f6ad540f4da0f6384fb828b8f7bb5a34942aa03719041b8b793"
|
||||
}
|
||||
fetchMetadata={fetchMetadata}
|
||||
/>
|
||||
|
|
|
@ -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(
|
||||
() =>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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 ==
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue