Add loading history in group chats (#139)
This commit is contained in:
parent
0742fa3635
commit
9592f7eab3
|
@ -76,7 +76,7 @@ function DragDiv() {
|
||||||
<ReactChat
|
<ReactChat
|
||||||
theme={theme ? lightTheme : darkTheme}
|
theme={theme ? lightTheme : darkTheme}
|
||||||
communityKey={
|
communityKey={
|
||||||
"0x0229d71fb62c14ec0370d2507ef7e13f1d53ddf1170db3babb5710fd113d0d94f9"
|
"0x0235564b1b402e8f6ad540f4da0f6384fb828b8f7bb5a34942aa03719041b8b793"
|
||||||
}
|
}
|
||||||
fetchMetadata={fetchMetadata}
|
fetchMetadata={fetchMetadata}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -94,7 +94,7 @@ function ChatUiMessage({
|
||||||
export function ChatMessages() {
|
export function ChatMessages() {
|
||||||
const { messages, activeChannel, contacts } = useMessengerContext();
|
const { messages, activeChannel, contacts } = useMessengerContext();
|
||||||
const ref = useRef<HTMLHeadingElement>(null);
|
const ref = useRef<HTMLHeadingElement>(null);
|
||||||
const loadingMessages = useChatScrollHandle(messages, ref, activeChannel.id);
|
const loadingMessages = useChatScrollHandle(messages, ref, activeChannel);
|
||||||
|
|
||||||
const shownMessages = useMemo(
|
const shownMessages = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
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;
|
const _MS_PER_DAY = 1000 * 60 * 60 * 24;
|
||||||
|
|
||||||
export function useLoadPrevDay(
|
export function useLoadPrevDay(
|
||||||
chatId: string,
|
chatId: string,
|
||||||
messenger: Messenger | undefined
|
messenger: Messenger | undefined,
|
||||||
|
groupChats?: GroupChats
|
||||||
) {
|
) {
|
||||||
const loadingPreviousMessages = useRef<{
|
const loadingPreviousMessages = useRef<{
|
||||||
[chatId: string]: boolean;
|
[chatId: string]: boolean;
|
||||||
|
@ -20,7 +21,7 @@ export function useLoadPrevDay(
|
||||||
}, [chatId]);
|
}, [chatId]);
|
||||||
|
|
||||||
const loadPrevDay = useCallback(
|
const loadPrevDay = useCallback(
|
||||||
async (id: string) => {
|
async (id: string, groupChat?: boolean) => {
|
||||||
if (messenger) {
|
if (messenger) {
|
||||||
const endTime = lastLoadTime.current[id] ?? new Date();
|
const endTime = lastLoadTime.current[id] ?? new Date();
|
||||||
const startTime = new Date(endTime.getTime() - _MS_PER_DAY);
|
const startTime = new Date(endTime.getTime() - _MS_PER_DAY);
|
||||||
|
@ -31,16 +32,25 @@ export function useLoadPrevDay(
|
||||||
if (!loadingPreviousMessages.current[id]) {
|
if (!loadingPreviousMessages.current[id]) {
|
||||||
loadingPreviousMessages.current[id] = true;
|
loadingPreviousMessages.current[id] = true;
|
||||||
setLoadingMessages(true);
|
setLoadingMessages(true);
|
||||||
const amountOfMessages = await messenger.retrievePreviousMessages(
|
let amountOfMessages = 0;
|
||||||
id,
|
if (groupChat && groupChats) {
|
||||||
startTime,
|
amountOfMessages = await groupChats.retrievePreviousMessages(
|
||||||
endTime
|
id,
|
||||||
);
|
startTime,
|
||||||
|
endTime
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
amountOfMessages = await messenger.retrievePreviousMessages(
|
||||||
|
id,
|
||||||
|
startTime,
|
||||||
|
endTime
|
||||||
|
);
|
||||||
|
}
|
||||||
lastLoadTime.current[id] = startTime;
|
lastLoadTime.current[id] = startTime;
|
||||||
loadingPreviousMessages.current[id] = false;
|
loadingPreviousMessages.current[id] = false;
|
||||||
setLoadingMessages(false);
|
setLoadingMessages(false);
|
||||||
if (amountOfMessages === 0) {
|
if (amountOfMessages === 0) {
|
||||||
loadPrevDay(id);
|
loadPrevDay(id, groupChat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ export type MessengerType = {
|
||||||
clearNotifications: (id: string) => void;
|
clearNotifications: (id: string) => void;
|
||||||
mentions: { [chatId: string]: number };
|
mentions: { [chatId: string]: number };
|
||||||
clearMentions: (id: string) => void;
|
clearMentions: (id: string) => void;
|
||||||
loadPrevDay: (id: string) => Promise<void>;
|
loadPrevDay: (id: string, groupChat?: boolean) => Promise<void>;
|
||||||
loadingMessages: boolean;
|
loadingMessages: boolean;
|
||||||
communityData: CommunityData | undefined;
|
communityData: CommunityData | undefined;
|
||||||
contacts: Contacts;
|
contacts: Contacts;
|
||||||
|
@ -109,7 +109,6 @@ export function useMessenger(
|
||||||
clearMentions,
|
clearMentions,
|
||||||
} = useMessages(chatId, identity, contactsClass);
|
} = useMessages(chatId, identity, contactsClass);
|
||||||
const [community, setCommunity] = useState<Community | undefined>(undefined);
|
const [community, setCommunity] = useState<Community | undefined>(undefined);
|
||||||
const { loadPrevDay, loadingMessages } = useLoadPrevDay(chatId, messenger);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (identity) {
|
if (identity) {
|
||||||
|
@ -127,14 +126,6 @@ export function useMessenger(
|
||||||
}
|
}
|
||||||
}, [messenger, communityKey, addMessage, contactsClass]);
|
}, [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 [channels, setChannels] = useState<ChannelsData>({});
|
||||||
|
|
||||||
const setChannel = useCallback((channel: ChannelData) => {
|
const setChannel = useCallback((channel: ChannelData) => {
|
||||||
|
@ -201,6 +192,19 @@ export function useMessenger(
|
||||||
channels
|
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(
|
const sendMessage = useCallback(
|
||||||
async (messageText?: string, image?: Uint8Array) => {
|
async (messageText?: string, image?: Uint8Array) => {
|
||||||
if (activeChannel.type === "group") {
|
if (activeChannel.type === "group") {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useMessengerContext } from "../contexts/messengerProvider";
|
import { useMessengerContext } from "../contexts/messengerProvider";
|
||||||
|
import { ChannelData } from "../models/ChannelData";
|
||||||
import { ChatMessage } from "../models/ChatMessage";
|
import { ChatMessage } from "../models/ChatMessage";
|
||||||
|
|
||||||
export function useChatScrollHandle(
|
export function useChatScrollHandle(
|
||||||
messages: ChatMessage[],
|
messages: ChatMessage[],
|
||||||
ref: React.RefObject<HTMLHeadingElement>,
|
ref: React.RefObject<HTMLHeadingElement>,
|
||||||
activeChannelId: string
|
activeChannel: ChannelData
|
||||||
) {
|
) {
|
||||||
const { loadPrevDay, loadingMessages } = useMessengerContext();
|
const { loadPrevDay, loadingMessages } = useMessengerContext();
|
||||||
const [scrollOnBot, setScrollOnBot] = useState(true);
|
const [scrollOnBot, setScrollOnBot] = useState(true);
|
||||||
|
@ -23,7 +24,7 @@ export function useChatScrollHandle(
|
||||||
(ref?.current?.clientHeight ?? 0) >= (ref?.current?.scrollHeight ?? 0)
|
(ref?.current?.clientHeight ?? 0) >= (ref?.current?.scrollHeight ?? 0)
|
||||||
) {
|
) {
|
||||||
setScrollOnBot(true);
|
setScrollOnBot(true);
|
||||||
loadPrevDay(activeChannelId);
|
loadPrevDay(activeChannel.id, activeChannel.type === "group");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [messages.length, loadingMessages]);
|
}, [messages.length, loadingMessages]);
|
||||||
|
@ -32,7 +33,7 @@ export function useChatScrollHandle(
|
||||||
const setScroll = () => {
|
const setScroll = () => {
|
||||||
if (ref?.current) {
|
if (ref?.current) {
|
||||||
if (ref.current.scrollTop <= 0) {
|
if (ref.current.scrollTop <= 0) {
|
||||||
loadPrevDay(activeChannelId);
|
loadPrevDay(activeChannel.id, activeChannel.type === "group");
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
ref.current.scrollTop + ref.current.clientHeight ==
|
ref.current.scrollTop + ref.current.clientHeight ==
|
||||||
|
|
|
@ -246,4 +246,41 @@ export class GroupChats {
|
||||||
);
|
);
|
||||||
wakuMessages.forEach((msg) => this.waku.relay.send(msg));
|
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