Skip to content

Commit

Permalink
♻️ refactor: refactor the main chat (lobehub#4773)
Browse files Browse the repository at this point in the history
* ♻️ refactor: refactor the main chat

* ♻️ refactor: refactor welcome
  • Loading branch information
arvinxx authored Nov 24, 2024
1 parent d41f955 commit 6973f4e
Show file tree
Hide file tree
Showing 36 changed files with 541 additions and 524 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { memo, useMemo } from 'react';

import { ChatItem } from '@/features/Conversation';
import ActionsBar from '@/features/Conversation/components/ChatItem/ActionsBar';
import { useAgentStore } from '@/store/agent';
import { agentSelectors } from '@/store/agent/selectors';
import { useChatStore } from '@/store/chat';
import { chatSelectors } from '@/store/chat/selectors';

export interface ThreadChatItemProps {
id: string;
index: number;
}

const MainChatItem = memo<ThreadChatItemProps>(({ id, index }) => {
const [historyLength] = useChatStore((s) => [chatSelectors.mainDisplayChatIDs(s).length]);

const enableHistoryDivider = useAgentStore((s) => {
const config = agentSelectors.currentAgentChatConfig(s);
return (
config.enableHistoryCount &&
historyLength > (config.historyCount ?? 0) &&
config.historyCount === historyLength - index
);
});

const actionBar = useMemo(() => <ActionsBar id={id} />, [id]);

return (
<ChatItem
actionBar={actionBar}
enableHistoryDivider={enableHistoryDivider}
id={id}
index={index}
/>
);
});

export default MainChatItem;
Original file line number Diff line number Diff line change
@@ -1,35 +1,41 @@
'use client';

import isEqual from 'fast-deep-equal';
import React, { memo } from 'react';
import React, { memo, useCallback } from 'react';

import { InboxWelcome, VirtualizedList } from '@/features/Conversation';
import { SkeletonList, VirtualizedList } from '@/features/Conversation';
import { useChatStore } from '@/store/chat';
import { chatSelectors } from '@/store/chat/selectors';
import { useSessionStore } from '@/store/session';

import MainChatItem from './ChatItem';
import Welcome from './WelcomeChatItem';

interface ListProps {
mobile?: boolean;
}

const Content = memo<ListProps>(({ mobile }) => {
const [activeTopicId, useFetchMessages, showInboxWelcome, isCurrentChatLoaded] = useChatStore(
(s) => [
s.activeTopicId,
s.useFetchMessages,
chatSelectors.showInboxWelcome(s),
chatSelectors.isCurrentChatLoaded(s),
],
);
const [activeTopicId, useFetchMessages, isCurrentChatLoaded] = useChatStore((s) => [
s.activeTopicId,
s.useFetchMessages,
chatSelectors.isCurrentChatLoaded(s),
]);

const [sessionId] = useSessionStore((s) => [s.activeId]);
useFetchMessages(sessionId, activeTopicId);

const data = useChatStore(chatSelectors.currentChatIDsWithGuideMessage, isEqual);
const data = useChatStore(chatSelectors.mainDisplayChatIDs);

const itemContent = useCallback(
(index: number, id: string) => <MainChatItem id={id} index={index} />,
[mobile],
);

if (!isCurrentChatLoaded) return <SkeletonList mobile={mobile} />;

if (showInboxWelcome && isCurrentChatLoaded) return <InboxWelcome />;
if (data.length === 0) return <Welcome />;

return <VirtualizedList dataSource={data} mobile={mobile} />;
return <VirtualizedList dataSource={data} itemContent={itemContent} mobile={mobile} />;
});

Content.displayName = 'ChatListRender';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ChatItem } from '@lobehub/ui';
import isEqual from 'fast-deep-equal';
import React from 'react';
import { useTranslation } from 'react-i18next';

import { useAgentStore } from '@/store/agent';
import { agentSelectors } from '@/store/agent/selectors';
import { useChatStore } from '@/store/chat';
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
import { useSessionStore } from '@/store/session';
import { sessionMetaSelectors } from '@/store/session/selectors';

const WelcomeMessage = () => {
const { t } = useTranslation('chat');
const [type = 'chat'] = useAgentStore((s) => {
const config = agentSelectors.currentAgentChatConfig(s);
return [config.displayMode];
});

const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
const { isAgentEditable } = useServerConfigStore(featureFlagsSelectors);
const activeId = useChatStore((s) => s.activeId);

const agentSystemRoleMsg = t('agentDefaultMessageWithSystemRole', {
name: meta.title || t('defaultAgent'),
systemRole: meta.description,
});

const agentMsg = t(isAgentEditable ? 'agentDefaultMessage' : 'agentDefaultMessageWithoutEdit', {
name: meta.title || t('defaultAgent'),
url: `/chat/settings?session=${activeId}`,
});

return (
<ChatItem
avatar={meta}
editing={false}
message={!!meta.description ? agentSystemRoleMsg : agentMsg}
placement={'left'}
type={type === 'chat' ? 'block' : 'pure'}
/>
);
};
export default WelcomeMessage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { memo } from 'react';

import { useChatStore } from '@/store/chat';
import { chatSelectors } from '@/store/chat/selectors';

import InboxWelcome from './InboxWelcome';
import WelcomeMessage from './WelcomeMessage';

const WelcomeChatItem = memo(() => {
const showInboxWelcome = useChatStore(chatSelectors.showInboxWelcome);

if (showInboxWelcome) return <InboxWelcome />;

return <WelcomeMessage />;
});

export default WelcomeChatItem;
14 changes: 1 addition & 13 deletions src/app/(main)/chat/(workspace)/@portal/features/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
'use client';

import { ActionIcon } from '@lobehub/ui';
import { XIcon } from 'lucide-react';
import { memo } from 'react';

import SidebarHeader from '@/components/SidebarHeader';
import { PortalHeader } from '@/features/Portal/router';
import { useChatStore } from '@/store/chat';

const Header = memo(() => {
const [toggleInspector] = useChatStore((s) => [s.togglePortal]);

return (
<SidebarHeader
actions={<ActionIcon icon={XIcon} onClick={() => toggleInspector(false)} />}
style={{ paddingBlock: 8, paddingInline: 8 }}
title={<PortalHeader />}
/>
);
return <PortalHeader />;
});

export default Header;
1 change: 1 addition & 0 deletions src/components/BrandWatermark/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const BrandWatermark = memo<Omit<FlexboxProps, 'children'>>(({ style, ...rest })
return (
<Flexbox
align={'center'}
dir={'ltr'}
flex={'none'}
gap={4}
horizontal
Expand Down
2 changes: 1 addition & 1 deletion src/const/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ export const LOADING_FLAT = '...';

export const MESSAGE_CANCEL_FLAT = 'canceled';

export const MESSAGE_THREAD_DIVIDER_ID = 'thread-divider';
export const MESSAGE_THREAD_DIVIDER_ID = '__THREAD_DIVIDER__';

export const MESSAGE_WELCOME_GUIDE_ID = 'welcome';
22 changes: 9 additions & 13 deletions src/features/Conversation/components/ChatItem/ActionsBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { memo, useCallback } from 'react';

import { useChatStore } from '@/store/chat';
import { chatSelectors } from '@/store/chat/selectors';
import { useSessionStore } from '@/store/session';
import { sessionMetaSelectors } from '@/store/session/selectors';
import { MessageRoleType } from '@/types/message';

import { renderActions, useActionsClick } from '../../Actions';
import { useChatListActionsBar } from '../../hooks/useChatListActionsBar';
Expand All @@ -25,34 +24,31 @@ const ActionsBar = memo<ActionsBarProps>((props) => {
});

interface ActionsProps {
index: number;
setEditing: (edit: boolean) => void;
id: string;
}
const Actions = memo<ActionsProps>(({ index, setEditing }) => {
const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);

const item = useChatStore(
(s) => chatSelectors.currentChatsWithGuideMessage(meta)(s)[index],
isEqual,
);
const Actions = memo<ActionsProps>(({ id }) => {
const item = useChatStore(chatSelectors.getMessageById(id), isEqual);
const [toggleMessageEditing] = useChatStore((s) => [s.toggleMessageEditing]);
const onActionsClick = useActionsClick();

const handleActionClick = useCallback(
async (action: ActionEvent) => {
switch (action.key) {
case 'edit': {
setEditing(true);
toggleMessageEditing(id, true);
}
}
if (!item) return;

onActionsClick(action, item);
},
[item],
);

const RenderFunction = renderActions[item?.role] ?? ActionsBar;
const RenderFunction = renderActions[(item?.role || '') as MessageRoleType] ?? ActionsBar;

return <RenderFunction {...item} onActionClick={handleActionClick} />;
return <RenderFunction {...item!} onActionClick={handleActionClick} />;
});

export default Actions;
Loading

0 comments on commit 6973f4e

Please sign in to comment.