diff --git a/client/shared/contexts/ConverseMessageContext.tsx b/client/shared/contexts/ConverseMessageContext.tsx new file mode 100644 index 00000000..2c9129b2 --- /dev/null +++ b/client/shared/contexts/ConverseMessageContext.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import type { ChatMessage, SendMessagePayload } from '../model/message'; +import { useConverseMessage } from '../redux/hooks/useConverseMessage'; +import { createContextFactory } from './factory'; + +interface ConverseMessageContextProps { + messages: ChatMessage[]; + loading: boolean; + error?: Error; + isLoadingMore: boolean; + hasMoreMessage: boolean; + fetchMoreMessage: () => Promise; + sendMessage: (payload: SendMessagePayload) => Promise; +} + +const { + Context: ConverseMessageContext, + useContext: useConverseMessageContext, +} = createContextFactory({ + defaultValue: {} as ConverseMessageContextProps, + displayName: 'ConverseMessageContext', +}); + +/** + * 会话消息列表相关上下文 + */ +export const ConverseMessageProvider: React.FC< + React.PropsWithChildren<{ + converseId: string; + isGroup: boolean; + }> +> = React.memo((props) => { + const { converseId, isGroup } = props; + const { + messages, + loading, + error, + isLoadingMore, + hasMoreMessage, + handleFetchMoreMessage: fetchMoreMessage, + handleSendMessage: sendMessage, + } = useConverseMessage({ + converseId, + isGroup, + }); + + return ( + + {props.children} + + ); +}); +ConverseMessageProvider.displayName = 'ConverseMessageProvider'; + +export { useConverseMessageContext }; diff --git a/client/shared/contexts/factory.tsx b/client/shared/contexts/factory.tsx new file mode 100644 index 00000000..81b1cbd3 --- /dev/null +++ b/client/shared/contexts/factory.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +interface CreateContextFactoryOptions { + defaultValue: Props; + displayName: string; +} + +export function createContextFactory( + options: CreateContextFactoryOptions +) { + const Context = React.createContext(options.defaultValue); + Context.displayName = options.displayName; + + function useContext(): Props { + return React.useContext(Context); + } + + return { + Context, + useContext, + }; +} diff --git a/client/shared/index.tsx b/client/shared/index.tsx index e331eb15..e343dec2 100644 --- a/client/shared/index.tsx +++ b/client/shared/index.tsx @@ -28,6 +28,10 @@ export { useChatBoxContext, } from './contexts/ChatBoxContext'; export { useColorScheme } from './contexts/ColorSchemeContext'; +export { + ConverseMessageProvider, + useConverseMessageContext, +} from './contexts/ConverseMessageContext'; export { GroupInfoContextProvider, useGroupInfoContext, diff --git a/client/web/src/components/ChatBox/index.tsx b/client/web/src/components/ChatBox/index.tsx index 426e7a51..dfc6cc0e 100644 --- a/client/web/src/components/ChatBox/index.tsx +++ b/client/web/src/components/ChatBox/index.tsx @@ -1,6 +1,10 @@ import { getMessageTextDecorators } from '@/plugin/common'; import React from 'react'; -import { ChatBoxContextProvider, useConverseMessage } from 'tailchat-shared'; +import { + ChatBoxContextProvider, + ConverseMessageProvider, + useConverseMessageContext, +} from 'tailchat-shared'; import { ErrorView } from '../ErrorView'; import { ChatBoxPlaceholder } from './ChatBoxPlaceholder'; import { ChatInputBox } from './ChatInputBox'; @@ -22,19 +26,16 @@ type ChatBoxProps = groupId: string; }; const ChatBoxInner: React.FC = React.memo((props) => { - const { converseId, converseTitle, isGroup } = props; + const { converseId, converseTitle } = props; const { messages, loading, error, isLoadingMore, hasMoreMessage, - handleFetchMoreMessage, - handleSendMessage, - } = useConverseMessage({ - converseId, - isGroup, - }); + fetchMoreMessage, + sendMessage, + } = useConverseMessageContext(); if (loading) { return ; @@ -52,7 +53,7 @@ const ChatBoxInner: React.FC = React.memo((props) => { messages={messages} isLoadingMore={isLoadingMore} hasMoreMessage={hasMoreMessage} - onLoadMore={handleFetchMoreMessage} + onLoadMore={fetchMoreMessage} /> @@ -60,7 +61,7 @@ const ChatBoxInner: React.FC = React.memo((props) => { { const content = preprocessMessage(msg); - handleSendMessage({ + sendMessage({ converseId: props.converseId, groupId: props.groupId, content, @@ -77,7 +78,12 @@ ChatBoxInner.displayName = 'ChatBoxInner'; export const ChatBox: React.FC = React.memo((props) => { return ( - + + + ); });