Fix: chat loading only one page per time (#19511)

This commit is contained in:
Tainan Felipe 2024-01-29 14:04:04 -03:00 committed by GitHub
parent 16c15f64b3
commit b524f0b9fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 81 additions and 86 deletions

View File

@ -12,7 +12,8 @@ import {
import { Message } from '/imports/ui/Types/message';
import ChatMessage from './chat-message/component';
import { GraphqlDataHookSubscriptionResponse } from '/imports/ui/Types/hook';
import useLoadedChatMessages from '/imports/ui/core/hooks/useLoadedChatMessages';
import { useCreateUseSubscription } from '/imports/ui/core/hooks/createUseSubscription';
import { setLoadedMessageGathering } from '/imports/ui/core/hooks/useLoadedChatMessages';
// @ts-ignore - temporary, while meteor exists in the project
const CHAT_CONFIG = Meteor.settings.public.chat;
@ -93,8 +94,6 @@ const ChatListPageContainer: React.FC<ChatListPageContainerProps> = ({
markMessageAsSeen,
scrollRef,
}) => {
const { setChatMessagesGraphqlVariablesAndQuery } = useContext(PluginsContext);
const isPublicChat = chatId === PUBLIC_GROUP_CHAT_KEY;
const chatQuery = isPublicChat
? CHAT_MESSAGE_PUBLIC_SUBSCRIPTION
@ -103,32 +102,31 @@ const ChatListPageContainer: React.FC<ChatListPageContainerProps> = ({
const variables = isPublicChat
? defaultVariables : { ...defaultVariables, requestedChatId: chatId };
const resp = useLoadedChatMessages((msg) => msg) as GraphqlDataHookSubscriptionResponse<Message[]>;
const useChatMessageSubscription = useCreateUseSubscription<Message>(chatQuery, variables, true);
const {
data: chatMessageData,
} = useChatMessageSubscription((msg) => msg) as GraphqlDataHookSubscriptionResponse<Message[]>;
const chatMessageData = resp?.data;
useEffect(() => {
setChatMessagesGraphqlVariablesAndQuery(
{
query: chatQuery,
variables,
},
);
}, [chatId, page, pageSize]);
if (chatMessageData) {
if (chatMessageData.length > 0 && chatMessageData[chatMessageData.length - 1].user?.userId) {
setLastSender(page, chatMessageData[chatMessageData.length - 1].user?.userId);
}
return (
<ChatListPage
messages={chatMessageData}
lastSenderPreviousPage={lastSenderPreviousPage}
page={page}
markMessageAsSeen={markMessageAsSeen}
scrollRef={scrollRef}
/>
);
} return (<></>);
// component will unmount
return () => {
setLoadedMessageGathering(page, []);
};
}, []);
if (!chatMessageData) return null;
if (chatMessageData.length > 0 && chatMessageData[chatMessageData.length - 1].user?.userId) {
setLastSender(page, chatMessageData[chatMessageData.length - 1].user?.userId);
}
setLoadedMessageGathering(page, chatMessageData);
return (
<ChatListPage
messages={chatMessageData}
lastSenderPreviousPage={lastSenderPreviousPage}
page={page}
markMessageAsSeen={markMessageAsSeen}
scrollRef={scrollRef}
/>
);
};
export default ChatListPageContainer;

View File

@ -1,7 +1,6 @@
import React, { createContext, useState } from 'react';
import { ExtensibleArea } from '/imports/ui/components/plugins-engine/extensible-areas/types';
import { ChatMessagesGraphqlVariablesAndQuery, PluginsContextType, UserListGraphqlVariables } from './types';
import { CHAT_MESSAGE_PUBLIC_SUBSCRIPTION } from '../../chat/chat-graphql/chat-message-list/page/queries';
import { PluginsContextType, UserListGraphqlVariables } from './types';
export const PluginsContext = createContext<PluginsContextType>({} as PluginsContextType);
@ -14,12 +13,6 @@ export const PluginsContextProvider = ({ children, ...props }: any) => {
{} as UserListGraphqlVariables,
);
const [domElementManipulationMessageIds, setDomElementManipulationMessageIds] = useState<string[]>([]);
const [
chatMessagesGraphqlVariablesAndQuery,
setChatMessagesGraphqlVariablesAndQuery,
] = useState<ChatMessagesGraphqlVariablesAndQuery>(
{ query: CHAT_MESSAGE_PUBLIC_SUBSCRIPTION } as ChatMessagesGraphqlVariablesAndQuery,
);
return (
<PluginsContext.Provider
@ -29,8 +22,6 @@ export const PluginsContextProvider = ({ children, ...props }: any) => {
pluginsExtensibleAreasAggregatedState,
userListGraphqlVariables,
setUserListGraphqlVariables,
chatMessagesGraphqlVariablesAndQuery,
setChatMessagesGraphqlVariablesAndQuery,
domElementManipulationMessageIds,
setDomElementManipulationMessageIds,
}}

View File

@ -1,4 +1,3 @@
import { DocumentNode } from 'graphql';
import { ExtensibleArea } from '/imports/ui/components/plugins-engine/extensible-areas/types';
import React from 'react';
@ -16,20 +15,12 @@ export type ChatMessagesVariables = {
limit: number;
}
export interface ChatMessagesGraphqlVariablesAndQuery {
query: DocumentNode;
variables: ChatMessagesVariables;
}
export interface PluginsContextType {
pluginsExtensibleAreasAggregatedState: ExtensibleArea;
setPluginsExtensibleAreasAggregatedState: React.Dispatch<React.SetStateAction<ExtensibleArea>>;
userListGraphqlVariables: UserListGraphqlVariables;
setUserListGraphqlVariables: React.Dispatch<
React.SetStateAction<UserListGraphqlVariables>>;
chatMessagesGraphqlVariablesAndQuery: ChatMessagesGraphqlVariablesAndQuery;
setChatMessagesGraphqlVariablesAndQuery: React.Dispatch<
React.SetStateAction<ChatMessagesGraphqlVariablesAndQuery>>;
domElementManipulationMessageIds: string[];
setDomElementManipulationMessageIds: React.Dispatch<
React.SetStateAction<string[]>>;

View File

@ -8,25 +8,22 @@ import {
} from 'bigbluebutton-html-plugin-sdk/dist/cjs/core/enum';
import { DataConsumptionHooks } from 'bigbluebutton-html-plugin-sdk/dist/cjs/data-consumption/enums';
import { UpdatedEventDetails } from 'bigbluebutton-html-plugin-sdk/dist/cjs/core/types';
import useLoadedChatMessages from '/imports/ui/core/hooks/useLoadedChatMessages';
import { GraphqlDataHookSubscriptionResponse } from '/imports/ui/Types/hook';
import useLoadedPageGathering from '/imports/ui/core/hooks/useLoadedChatMessages';
import { Message } from '/imports/ui/Types/message';
import formatLoadedChatMessagesDataFromGraphql from './utils';
const LoadedChatMessagesHookContainer = () => {
const [sendSignal, setSendSignal] = useState(false);
const chatMessagesData: GraphqlDataHookSubscriptionResponse<Partial<Message>[]> = useLoadedChatMessages(
(message: Partial<Message>) => ({
createdAt: message.createdAt,
message: message.message,
messageId: message.messageId,
user: message.user,
}),
);
const [chatMessagesData] = useLoadedPageGathering((message: Partial<Message>) => ({
createdAt: message.createdAt,
message: message.message,
messageId: message.messageId,
user: message.user,
}));
const updateLoadedChatMessagesForPlugin = () => {
window.dispatchEvent(new CustomEvent<
UpdatedEventDetails<PluginSdk.GraphqlResponseWrapper<LoadedChatMessage>>
UpdatedEventDetails<PluginSdk.GraphqlResponseWrapper<LoadedChatMessage[]>>
>(HookEvents.UPDATED, {
detail: {
data: formatLoadedChatMessagesDataFromGraphql(chatMessagesData),

View File

@ -1,18 +1,17 @@
import { GraphqlDataHookSubscriptionResponse } from '/imports/ui/Types/hook';
import { Message } from '/imports/ui/Types/message';
import * as PluginSdk from 'bigbluebutton-html-plugin-sdk';
const formatLoadedChatMessagesDataFromGraphql = (
responseDataFromGraphql: GraphqlDataHookSubscriptionResponse<Partial<Message>[]>,
responseData: Partial<Message>[],
) => ({
data: !responseDataFromGraphql.loading ? responseDataFromGraphql.data?.map((chatMessagesData) => ({
data: responseData.map((chatMessagesData) => ({
createdAt: chatMessagesData.createdAt,
message: chatMessagesData.message,
messageId: chatMessagesData.messageId,
senderUserId: chatMessagesData.user?.userId,
}) as PluginSdk.LoadedChatMessage) : undefined,
loading: responseDataFromGraphql.loading,
error: responseDataFromGraphql.errors?.[0],
} as PluginSdk.GraphqlResponseWrapper<PluginSdk.LoadedChatMessage>);
}) as PluginSdk.LoadedChatMessage),
loading: !(responseData),
error: undefined,
} as PluginSdk.GraphqlResponseWrapper<PluginSdk.LoadedChatMessage[]>);
export default formatLoadedChatMessagesDataFromGraphql;

View File

@ -1,27 +1,46 @@
import { useContext } from 'react';
import { DocumentNode } from 'graphql';
import { isEqual } from 'radash';
import { makeVar, useReactiveVar } from '@apollo/client';
import { Message } from '/imports/ui/Types/message';
import createUseSubscription from './createUseSubscription';
import { PluginsContext } from '../../components/components-data/plugin-context/context';
import { ChatMessagesVariables } from '../../components/components-data/plugin-context/types';
const createUseLoadedChatMessagesSubscription = (
query: DocumentNode,
variables: ChatMessagesVariables,
) => createUseSubscription<Message>(
query,
{ ...variables },
);
interface LoadedChatMessages {
[pageNumber: number]: Partial<Message>[];
}
const useLoadedChatMessages = (fn: (c: Partial<Message>) => Partial<Message>) => {
const { chatMessagesGraphqlVariablesAndQuery } = useContext(PluginsContext);
const {
query,
variables,
} = chatMessagesGraphqlVariablesAndQuery;
const useLoadedChatMessagesSubscription = createUseLoadedChatMessagesSubscription(query, variables);
const loadedChatMessages = useLoadedChatMessagesSubscription(fn);
return loadedChatMessages;
const createLoadedPageGathering = (): [
(fn: (c: Partial<Message>) => Partial<Message>) => [
Partial<Message>[],
(pageNumber: number, result: Partial<Message>[]) => void,
],
(pageNumber: number, result: Partial<Message>[]) => void,
] => {
const loadedPages = makeVar<LoadedChatMessages>({});
const pagesGathering = (pageNumber: number, result: Partial<Message>[]): void => {
const pageMessages = loadedPages()[pageNumber];
const hasMessages = pageMessages && pageMessages.length > 0;
const shouldAdd = !hasMessages || !isEqual(pageMessages, result);
if (shouldAdd) {
const a = {
...loadedPages(),
[pageNumber]: result,
};
loadedPages(a);
}
};
const useResultPage = (fn: (c: Partial<Message>) => Partial<Message>): [
Partial<Message>[],
(pageNumber: number, result: Partial<Message>[]) => void,
] => {
const gatheredPages = useReactiveVar(loadedPages);
const messages = Object.values(gatheredPages).filter((i) => Array.isArray(i)).flat();
return [messages.map(fn), pagesGathering];
};
return [useResultPage, pagesGathering];
};
export default useLoadedChatMessages;
const [useLoadedPageGathering, setLoadedMessageGathering] = createLoadedPageGathering();
export default useLoadedPageGathering;
export { setLoadedMessageGathering, useLoadedPageGathering };