Skip to content

Commit

Permalink
♻️ refactor: Refactor ChatList (lobehub#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Oct 16, 2023
1 parent a977383 commit aa4216c
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 200 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Icon } from '@lobehub/ui';
import { Icon, RenderErrorMessage } from '@lobehub/ui';
import { Button, Segmented } from 'antd';
import { KeySquare, SquareAsterisk } from 'lucide-react';
import { memo, useState } from 'react';
Expand All @@ -17,7 +17,7 @@ enum Tab {
Password = 'password',
}

const InvalidAccess = memo<{ id: string }>(({ id }) => {
const InvalidAccess: RenderErrorMessage = memo(({ id }) => {
const { t } = useTranslation('error');
const [mode, setMode] = useState<Tab>(Tab.Password);
const [password, setSettings] = useGlobalStore((s) => [s.settings.password, s.setSettings]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { RenderErrorMessage } from '@lobehub/ui';
import { memo } from 'react';

import APIKeyForm from './ApiKeyForm';
import { ErrorActionContainer } from './style';

const OpenAPIKey = memo<{ id: string }>(({ id }) => (
const OpenAPIKey: RenderErrorMessage = memo(({ id }) => (
<ErrorActionContainer>
<APIKeyForm id={id} />
</ErrorActionContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Highlighter } from '@lobehub/ui';
import { Highlighter, RenderErrorMessage } from '@lobehub/ui';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';

Expand All @@ -16,16 +16,18 @@ interface OpenAIErrorResponse {
error: OpenAIError;
}

const OpenAiBizError = memo<{ content: OpenAIErrorResponse; id: string }>(({ content, id }) => {
const OpenAiBizError: RenderErrorMessage = memo(({ error, id, ...props }) => {
const { styles } = useStyles();

const errorCode = content.error?.code;
const errorBody: OpenAIErrorResponse = (error as any)?.body;

if (errorCode === 'invalid_api_key') return <OpenAPIKey id={id} />;
const errorCode = errorBody.error?.code;

if (errorCode === 'invalid_api_key') return <OpenAPIKey error={error} id={id} {...props} />;

return (
<Flexbox className={styles.container} style={{ maxWidth: 600 }}>
<Highlighter language={'json'}>{JSON.stringify(content, null, 2)}</Highlighter>
<Highlighter language={'json'}>{JSON.stringify(errorBody, null, 2)}</Highlighter>
</Flexbox>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Highlighter } from '@lobehub/ui';
import { Highlighter, RenderErrorMessage } from '@lobehub/ui';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';

Expand All @@ -15,12 +15,13 @@ interface OpenAIErrorResponse {
error: OpenAIError;
}

const PluginError = memo<{ content: OpenAIErrorResponse; id: string }>(({ content }) => {
const PluginError: RenderErrorMessage = memo(({ error, id }) => {
const { styles } = useStyles();
const errorBody: OpenAIErrorResponse = (error as any)?.body;

return (
<Flexbox className={styles.container} style={{ maxWidth: 600 }}>
<Highlighter language={'json'}>{JSON.stringify(content, null, 2)}</Highlighter>
<Flexbox className={styles.container} id={id} style={{ maxWidth: 600 }}>
<Highlighter language={'json'}>{JSON.stringify(errorBody, null, 2)}</Highlighter>
</Flexbox>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Avatar } from '@lobehub/ui';
import { Avatar, RenderErrorMessage } from '@lobehub/ui';
import { Button, Divider } from 'antd';
import { useTheme } from 'antd-style';
import isEqual from 'fast-deep-equal';
Expand All @@ -12,32 +12,26 @@ import { useSessionStore } from '@/store/session';

import { ErrorActionContainer, useStyles } from '../style';

interface PluginSettingsProps {
id: string;
pluginIdentifier: string;
}

const PluginSettings = memo<PluginSettingsProps>(({ id, pluginIdentifier }) => {
const PluginSettings: RenderErrorMessage = memo(({ id, plugin }) => {
const { styles } = useStyles();

const { t } = useTranslation('error');
const theme = useTheme();
const [resend, deleteMessage] = useSessionStore((s) => [s.resendMessage, s.deleteMessage]);

const plugin = usePluginStore(pluginSelectors.getPluginMetaById(pluginIdentifier), isEqual);
const pluginIdentifier = plugin?.identifier as string;
const pluginMeta = usePluginStore(pluginSelectors.getPluginMetaById(pluginIdentifier), isEqual);
const manifest = usePluginStore(pluginSelectors.getPluginManifestById(pluginIdentifier), isEqual);

return (
<ErrorActionContainer>
<Center gap={16} style={{ maxWidth: 400 }}>
<Avatar
avatar={pluginHelpers.getPluginAvatar(plugin?.meta) || '⚙️'}
avatar={pluginHelpers.getPluginAvatar(pluginMeta?.meta) || '⚙️'}
background={theme.colorFillContent}
gap={12}
size={80}
/>
<Flexbox style={{ fontSize: 20 }}>
{t('pluginSettings.title', { name: pluginHelpers.getPluginTitle(plugin?.meta) })}
{t('pluginSettings.title', { name: pluginHelpers.getPluginTitle(pluginMeta?.meta) })}
</Flexbox>
<Flexbox className={styles.desc}>{t('pluginSettings.desc')}</Flexbox>
<Divider style={{ margin: '0 16px' }} />
Expand Down
56 changes: 17 additions & 39 deletions src/app/chat/features/Conversation/ChatList/Error/index.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,26 @@
import { IPluginErrorType, PluginErrorType } from '@lobehub/chat-plugin-sdk';
import { RenderErrorMessage } from '@lobehub/ui';
import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
import { ChatListProps } from '@lobehub/ui';

import { ChatMessage } from '@/types/chatMessage';
import { ChatErrorType, ErrorType } from '@/types/fetch';
import { ChatErrorType } from '@/types/fetch';

import InvalidAccess from './InvalidAccess';
import OpenAPIKey from './OpenAPIKey';
import OpenAiBizError from './OpenAiBizError';
import PluginError from './Plugin/PluginError';
import PluginSettings from './Plugin/PluginSettings';

export const renderErrorMessage: RenderErrorMessage = (error, message: ChatMessage) => {
switch (error.type as IPluginErrorType) {
case PluginErrorType.PluginMarketIndexNotFound:
case PluginErrorType.PluginMarketIndexInvalid:
case PluginErrorType.PluginMetaInvalid:
case PluginErrorType.PluginMetaNotFound:
case PluginErrorType.PluginManifestInvalid:
case PluginErrorType.PluginManifestNotFound:
case PluginErrorType.PluginApiNotFound:
case PluginErrorType.PluginApiParamsError:
case PluginErrorType.PluginServerError: {
return <PluginError content={(error as any).body} id={message.id} />;
}
case PluginErrorType.PluginSettingsInvalid: {
return (
message.plugin?.identifier && (
<PluginSettings id={message.id} pluginIdentifier={message.plugin?.identifier} />
)
);
}
}

switch (error.type as ErrorType) {
case ChatErrorType.InvalidAccessCode: {
return <InvalidAccess id={message.id} />;
}

case ChatErrorType.NoAPIKey: {
return <OpenAPIKey id={message.id} />;
}

case ChatErrorType.OpenAIBizError: {
return <OpenAiBizError content={(error as any).body} id={message.id} />;
}
}
export const renderErrorMessages: ChatListProps['renderErrorMessages'] = {
[PluginErrorType.PluginMarketIndexNotFound]: PluginError,
[PluginErrorType.PluginMarketIndexInvalid]: PluginError,
[PluginErrorType.PluginMetaInvalid]: PluginError,
[PluginErrorType.PluginMetaNotFound]: PluginError,
[PluginErrorType.PluginManifestInvalid]: PluginError,
[PluginErrorType.PluginManifestNotFound]: PluginError,
[PluginErrorType.PluginApiNotFound]: PluginError,
[PluginErrorType.PluginApiParamsError]: PluginError,
[PluginErrorType.PluginServerError]: PluginError,
[PluginErrorType.PluginSettingsInvalid]: PluginSettings,
[ChatErrorType.InvalidAccessCode]: InvalidAccess,
[ChatErrorType.NoAPIKey]: OpenAPIKey,
[ChatErrorType.OpenAIBizError]: OpenAiBizError,
};
85 changes: 0 additions & 85 deletions src/app/chat/features/Conversation/ChatList/MessageExtra.tsx

This file was deleted.

82 changes: 82 additions & 0 deletions src/app/chat/features/Conversation/ChatList/Messages/Assistant.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { SiOpenai } from '@icons-pack/react-simple-icons';
import { ActionIconGroup, RenderAction, Tag, useChatListActionsBar } from '@lobehub/ui';
import { RenderMessage, RenderMessageExtra } from '@lobehub/ui/src';
import { createStyles } from 'antd-style';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/slices/agentConfig';
import { isFunctionMessage } from '@/utils/message';

import FunctionCall from '../Plugins/FunctionCall';
import { DefautMessage } from './Default';
import { SystemActionsBar } from './System';

const useStyles = createStyles(({ css }) => ({
container: css`
margin-top: 8px;
`,
plugin: css`
display: flex;
gap: 4px;
align-items: center;
width: fit-content;
`,
}));

export const AssistantMessage: RenderMessage = memo(
({ id, plugin, function_call, content, ...props }) => {
const chatLoadingId = useSessionStore((s) => s.chatLoadingId);

if (!isFunctionMessage(content)) return <DefautMessage content={content} id={id} {...props} />;

const itemId = plugin?.identifier || function_call?.name;
const command = plugin ?? function_call;
const args = command?.arguments;
const fcProps = {
arguments: args,
command,
content: content,
id: itemId,
loading: id === chatLoadingId,
};

return (
<div id={itemId}>
<FunctionCall {...fcProps} />
</div>
);
},
);

export const AssistantMessageExtra: RenderMessageExtra = memo(({ extra, function_call }) => {
const { styles } = useStyles();
const model = useSessionStore(agentSelectors.currentAgentModel);

const hasModelTag = extra?.fromModel && model !== extra?.fromModel;
const hasFuncTag = !!function_call;
if (!(hasModelTag || hasFuncTag)) return;

return (
<Flexbox className={styles.container} horizontal>
<div>
<Tag icon={<SiOpenai size={'1em'} />}>{extra?.fromModel as string}</Tag>
</div>
</Flexbox>
);
});

export const AssistantActionsBar: RenderAction = memo(({ text, error, id, ...props }) => {
const { regenerate, edit, copy, divider, del } = useChatListActionsBar(text);
if (id === 'default') return;
if (error) return <SystemActionsBar id={id} text={text} {...props} />;
return (
<ActionIconGroup
dropdownMenu={[edit, copy, regenerate, divider, del]}
items={[regenerate, copy]}
type="ghost"
{...props}
/>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { RenderMessage } from '@lobehub/ui/src';
import { memo } from 'react';

export const DefautMessage: RenderMessage = memo(({ id, content }) => {
return <div id={id}>{content}</div>;
});
Loading

0 comments on commit aa4216c

Please sign in to comment.