Skip to content

Commit

Permalink
💄 style: support switch model with tag (lobehub#1435)
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx authored Mar 1, 2024
1 parent 438b4c2 commit 233150e
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 174 deletions.
102 changes: 0 additions & 102 deletions src/app/chat/(desktop)/features/ChatHeader.tsx

This file was deleted.

34 changes: 34 additions & 0 deletions src/app/chat/(desktop)/features/ChatHeader/HeaderAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ActionIcon } from '@lobehub/ui';
import { PanelRightClose, PanelRightOpen } from 'lucide-react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

import { DESKTOP_HEADER_ICON_SIZE } from '@/const/layoutTokens';
import { useGlobalStore } from '@/store/global';

import SettingButton from '../../../features/ChatHeader/SettingButton';
import ShareButton from '../../../features/ChatHeader/ShareButton';

const HeaderAction = memo(() => {
const { t } = useTranslation('chat');

const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
s.preference.showChatSideBar,
s.toggleChatSideBar,
]);

return (
<>
<ShareButton />
<ActionIcon
icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
onClick={() => toggleConfig()}
size={DESKTOP_HEADER_ICON_SIZE}
title={t('roleAndArchive')}
/>
<SettingButton />
</>
);
});

export default HeaderAction;
58 changes: 58 additions & 0 deletions src/app/chat/(desktop)/features/ChatHeader/Main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Avatar, ChatHeaderTitle } from '@lobehub/ui';
import { Skeleton } from 'antd';
import { useRouter } from 'next/navigation';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';

import { useSessionStore } from '@/store/session';
import { agentSelectors, sessionSelectors } from '@/store/session/selectors';
import { pathString } from '@/utils/url';

import Tags from './Tags';

const Main = memo(() => {
const { t } = useTranslation('chat');

const router = useRouter();

const [init, isInbox, title, description, avatar, backgroundColor] = useSessionStore((s) => [
sessionSelectors.isSomeSessionActive(s),
sessionSelectors.isInboxSession(s),
agentSelectors.currentAgentTitle(s),
agentSelectors.currentAgentDescription(s),
agentSelectors.currentAgentAvatar(s),
agentSelectors.currentAgentBackgroundColor(s),
]);

const displayTitle = isInbox ? t('inbox.title') : title;
const displayDesc = isInbox ? t('inbox.desc') : description;

return !init ? (
<Flexbox horizontal>
<Skeleton
active
avatar={{ shape: 'circle', size: 'default' }}
paragraph={false}
title={{ style: { margin: 0, marginTop: 8 }, width: 200 }}
/>
</Flexbox>
) : (
<Flexbox align={'flex-start'} gap={12} horizontal>
<Avatar
avatar={avatar}
background={backgroundColor}
onClick={() =>
isInbox
? router.push('/settings/agent')
: router.push(pathString('/chat/settings', { search: location.search }))
}
size={40}
title={title}
/>
<ChatHeaderTitle desc={displayDesc} tag={<Tags />} title={displayTitle} />
</Flexbox>
);
});

export default Main;
30 changes: 30 additions & 0 deletions src/app/chat/(desktop)/features/ChatHeader/Tags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { memo } from 'react';

import ModelTag from '@/components/ModelTag';
import ModelSwitchPanel from '@/features/ModelSwitchPanel';
import { useGlobalStore } from '@/store/global';
import { modelProviderSelectors } from '@/store/global/selectors';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';

import PluginTag from '../../../features/PluginTag';

const TitleTags = memo(() => {
const [model, plugins] = useSessionStore((s) => [
agentSelectors.currentAgentModel(s),
agentSelectors.currentAgentPlugins(s),
]);

const showPlugin = useGlobalStore(modelProviderSelectors.modelEnabledFunctionCall(model));

return (
<>
<ModelSwitchPanel>
<ModelTag model={model} />
</ModelSwitchPanel>
{showPlugin && plugins?.length > 0 && <PluginTag plugins={plugins} />}
</>
);
});

export default TitleTags;
9 changes: 9 additions & 0 deletions src/app/chat/(desktop)/features/ChatHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ChatHeader } from '@lobehub/ui';
import { memo } from 'react';

import HeaderAction from './HeaderAction';
import Main from './Main';

const Header = memo(() => <ChatHeader left={<Main />} right={<HeaderAction />} />);

export default Header;
2 changes: 1 addition & 1 deletion src/app/chat/features/ChatHeader/ShareButton/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ChatList from '@/features/Conversation/components/ChatList';
import { useSessionStore } from '@/store/session';
import { agentSelectors, sessionSelectors } from '@/store/session/selectors';

import PluginTag from '../../ChatHeader/PluginTag';
import PluginTag from '../../PluginTag';
import { useStyles } from './style';
import { FieldType } from './type';

Expand Down
File renamed without changes.
75 changes: 4 additions & 71 deletions src/features/ChatInput/ActionBar/ModelSwitch.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,17 @@
import { ActionIcon } from '@lobehub/ui';
import { Dropdown } from 'antd';
import { createStyles } from 'antd-style';
import isEqual from 'fast-deep-equal';
import { BrainCog } from 'lucide-react';
import { memo, useMemo } from 'react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

import { ModelItemRender, ProviderItemRender } from '@/components/ModelSelect';
import { useGlobalStore } from '@/store/global';
import { modelProviderSelectors } from '@/store/global/selectors';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';
import { ModelProviderCard } from '@/types/llm';

const useStyles = createStyles(({ css, prefixCls }) => ({
menu: css`
.${prefixCls}-dropdown-menu-item {
display: flex;
gap: 8px;
}
.${prefixCls}-dropdown-menu {
&-item-group-title {
padding-inline: 8px;
}
&-item-group-list {
margin: 0 !important;
}
}
`,
}));
import ModelSwitchPanel from '@/features/ModelSwitchPanel';

const ModelSwitch = memo(() => {
const { t } = useTranslation('chat');
const { styles } = useStyles();
const model = useSessionStore(agentSelectors.currentAgentModel);
const updateAgentConfig = useSessionStore((s) => s.updateAgentConfig);

const select = useGlobalStore(modelProviderSelectors.modelSelectList, isEqual);
const enabledList = select.filter((s) => s.enabled);

const items = useMemo(() => {
const getModelItems = (provider: ModelProviderCard) =>
provider.chatModels
.filter((c) => !c.hidden)
.map((model) => ({
key: model.id,
label: <ModelItemRender {...model} />,
onClick: () => {
updateAgentConfig({ model: model.id, provider: provider.id });
},
}));

if (enabledList.length === 1) {
const provider = enabledList[0];
return getModelItems(provider);
}

return enabledList.map((provider) => ({
children: getModelItems(provider),
key: provider.id,
label: <ProviderItemRender provider={provider.id} />,
type: 'group',
}));
}, [enabledList]);
return (
<Dropdown
menu={{
activeKey: model,
className: styles.menu,
items,
style: {
maxHeight: 500,
overflowY: 'scroll',
},
}}
trigger={['click']}
>
<ModelSwitchPanel>
<ActionIcon icon={BrainCog} placement={'bottom'} title={t('ModelSwitch.title')} />
</Dropdown>
</ModelSwitchPanel>
);
});

Expand Down
Loading

0 comments on commit 233150e

Please sign in to comment.