Skip to content

Commit 7263a33

Browse files
authored
♻️ refactor: refactor the create message flow to fix some bugs (lobehub#2521)
* ♻️ refactor: refactor the create message flow * ✅ test: fix test * ✅ test: add test * ✅ test: add more test * 💄 style: improve loading state
1 parent ffbe641 commit 7263a33

File tree

18 files changed

+868
-156
lines changed

18 files changed

+868
-156
lines changed

src/app/(main)/chat/@session/features/SessionHydration.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { useSessionStore } from '@/store/session';
1313
const SessionHydration = memo(() => {
1414
const useStoreUpdater = createStoreUpdater(useSessionStore);
1515
const useAgentStoreUpdater = createStoreUpdater(useAgentStore);
16+
const useChatStoreUpdater = createStoreUpdater(useChatStore);
1617
const [switchTopic] = useChatStore((s) => [s.switchTopic]);
1718

1819
// two-way bindings the url and session store
@@ -22,6 +23,7 @@ const SessionHydration = memo(() => {
2223
);
2324
useStoreUpdater('activeId', session);
2425
useAgentStoreUpdater('activeId', session);
26+
useChatStoreUpdater('activeId', session);
2527

2628
useEffect(() => {
2729
const unsubscribe = useSessionStore.subscribe(

src/features/Conversation/Error/index.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { IPluginErrorType, PluginErrorType } from '@lobehub/chat-plugin-sdk';
22
import type { AlertProps } from '@lobehub/ui';
3-
import { memo } from 'react';
3+
import { Skeleton } from 'antd';
4+
import dynamic from 'next/dynamic';
5+
import { Suspense, memo } from 'react';
46

57
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '@/libs/agent-runtime';
68
import { ChatErrorType, ErrorType } from '@/types/fetch';
@@ -10,9 +12,12 @@ import ClerkLogin from './ClerkLogin';
1012
import ErrorJsonViewer from './ErrorJsonViewer';
1113
import InvalidAPIKey from './InvalidAPIKey';
1214
import InvalidAccessCode from './InvalidAccessCode';
13-
import OllamaBizError from './OllamaBizError';
1415
import OpenAiBizError from './OpenAiBizError';
15-
import PluginSettings from './PluginSettings';
16+
17+
const loading = () => <Skeleton active />;
18+
19+
const OllamaBizError = dynamic(() => import('./OllamaBizError'), { loading, ssr: false });
20+
const PluginSettings = dynamic(() => import('./PluginSettings'), { loading, ssr: false });
1621

1722
// Config for the errorMessage display
1823
export const getErrorAlertConfig = (
@@ -95,4 +100,8 @@ const ErrorMessageExtra = memo<{ data: ChatMessage }>(({ data }) => {
95100
}
96101
});
97102

98-
export default ErrorMessageExtra;
103+
export default memo<{ data: ChatMessage }>(({ data }) => (
104+
<Suspense fallback={<Skeleton active style={{ width: '100%' }} />}>
105+
<ErrorMessageExtra data={data} />
106+
</Suspense>
107+
));

src/features/Conversation/components/VirtualizedList/index.tsx

+27-21
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
2929

3030
const [id] = useChatStore((s) => [chatSelectors.currentChatKey(s)]);
3131

32-
const [activeTopicId, useFetchMessages, isFirstLoading] = useChatStore((s) => [
33-
s.activeTopicId,
34-
s.useFetchMessages,
35-
chatSelectors.currentChatLoadingState(s),
36-
]);
32+
const [activeTopicId, useFetchMessages, isFirstLoading, isCurrentChatLoaded] = useChatStore(
33+
(s) => [
34+
s.activeTopicId,
35+
s.useFetchMessages,
36+
chatSelectors.currentChatLoadingState(s),
37+
chatSelectors.isCurrentChatLoaded(s),
38+
],
39+
);
3740

3841
const [sessionId] = useSessionStore((s) => [s.activeId]);
39-
const { isLoading } = useFetchMessages(sessionId, activeTopicId);
42+
useFetchMessages(sessionId, activeTopicId);
4043

4144
const data = useChatStore((s) => {
4245
const showInboxWelcome = chatSelectors.showInboxWelcome(s);
@@ -77,23 +80,26 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
7780
[mobile],
7881
);
7982

80-
// first time loading
83+
// first time loading or not loaded
8184
if (isFirstLoading) return <SkeletonList mobile={mobile} />;
8285

83-
// in server mode and switch page
84-
if (isServerMode && isLoading) return <SkeletonList mobile={mobile} />;
85-
86-
// in client mode using the center loading for more
87-
return isLoading ? (
88-
<Center height={'100%'} width={'100%'}>
89-
<Icon
90-
icon={Loader2Icon}
91-
size={{ fontSize: 32 }}
92-
spin
93-
style={{ color: theme.colorTextTertiary }}
94-
/>
95-
</Center>
96-
) : (
86+
if (!isCurrentChatLoaded)
87+
// use skeleton list when not loaded in server mode due to the loading duration is much longer than client mode
88+
return isServerMode ? (
89+
<SkeletonList mobile={mobile} />
90+
) : (
91+
// in client mode and switch page, using the center loading for smooth transition
92+
<Center height={'100%'} width={'100%'}>
93+
<Icon
94+
icon={Loader2Icon}
95+
size={{ fontSize: 32 }}
96+
spin
97+
style={{ color: theme.colorTextTertiary }}
98+
/>
99+
</Center>
100+
);
101+
102+
return (
97103
<Flexbox height={'100%'}>
98104
<Virtuoso
99105
atBottomStateChange={setAtBottom}

src/services/message/type.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { DB_Message } from '@/database/client/schemas/message';
2-
import { ChatMessage, ChatMessageError, ChatPluginPayload } from '@/types/message';
2+
import { ChatMessage, ChatMessageError, ChatPluginPayload, MessageRoleType } from '@/types/message';
33

44
/* eslint-disable typescript-sort-keys/interface */
55

66
export interface CreateMessageParams
7-
extends Partial<Omit<ChatMessage, 'content' | 'role'>>,
8-
Pick<ChatMessage, 'content' | 'role'> {
7+
extends Partial<Omit<ChatMessage, 'content' | 'role' | 'topicId'>> {
98
fromModel?: string;
109
fromProvider?: string;
1110
sessionId: string;
1211
traceId?: string;
12+
topicId?: string;
13+
content: string;
14+
error?: ChatMessageError;
15+
role: MessageRoleType;
1316
}
1417

1518
export interface IMessageService {

src/store/chat/slices/enchance/action.test.ts

+16-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { chainLangDetect } from '@/chains/langDetect';
55
import { chainTranslate } from '@/chains/translate';
66
import { chatService } from '@/services/chat';
77
import { messageService } from '@/services/message';
8+
import { messageMapKey } from '@/store/chat/slices/message/utils';
89

910
import { useChatStore } from '../../store';
1011

@@ -73,18 +74,21 @@ describe('ChatEnhanceAction', () => {
7374

7475
act(() => {
7576
useChatStore.setState({
76-
messages: [
77-
{
78-
id: messageId,
79-
content: messageContent,
80-
createdAt: Date.now(),
81-
updatedAt: Date.now(),
82-
role: 'user',
83-
sessionId: 'test',
84-
topicId: 'test',
85-
meta: {},
86-
},
87-
],
77+
activeId: 'session',
78+
messagesMap: {
79+
[messageMapKey('session')]: [
80+
{
81+
id: messageId,
82+
content: messageContent,
83+
createdAt: Date.now(),
84+
updatedAt: Date.now(),
85+
role: 'user',
86+
sessionId: 'test',
87+
topicId: 'test',
88+
meta: {},
89+
},
90+
],
91+
},
8892
});
8993
});
9094

0 commit comments

Comments
 (0)