mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
✨ feat: 优化 SideBar 实现,激活态指示更加明确
This commit is contained in:
98
src/features/SideBar/BottomAction.tsx
Normal file
98
src/features/SideBar/BottomAction.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import { ActionIcon, Icon } from '@lobehub/ui';
|
||||
import { Dropdown, MenuProps } from 'antd';
|
||||
import {
|
||||
Feather,
|
||||
FileClock,
|
||||
FolderInput,
|
||||
FolderOutput,
|
||||
Github,
|
||||
Heart,
|
||||
Settings,
|
||||
} from 'lucide-react';
|
||||
import Router from 'next/router';
|
||||
import { ReactNode, memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import pkg from '../../../package.json';
|
||||
|
||||
const BottomAction = memo<{ children: ReactNode }>(({ children }) => {
|
||||
const { t } = useTranslation('common');
|
||||
|
||||
const items: MenuProps['items'] = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: <Icon icon={FolderInput} />,
|
||||
key: 'import',
|
||||
label: <div>{t('import')}</div>,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
key: 'allAgent',
|
||||
label: <div>{t('exportType.allAgent')}</div>,
|
||||
},
|
||||
{
|
||||
key: 'allAgentWithMessage',
|
||||
label: <div>{t('exportType.allAgentWithMessage')}</div>,
|
||||
},
|
||||
{
|
||||
key: 'globalSetting',
|
||||
label: <div>{t('exportType.globalSetting')}</div>,
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
key: 'all',
|
||||
label: <div>{t('exportType.all')}</div>,
|
||||
},
|
||||
],
|
||||
icon: <Icon icon={FolderOutput} />,
|
||||
key: 'export',
|
||||
label: t('export'),
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={Feather} />,
|
||||
key: 'feedback',
|
||||
label: t('feedback'),
|
||||
onClick: () => window.open(pkg.bugs.url, '__blank'),
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={FileClock} />,
|
||||
key: 'changelog',
|
||||
label: t('changelog'),
|
||||
onClick: () => window.open(`${pkg.homepage}/blob/master/CHANGELOG.md`, '__blank'),
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={Heart} />,
|
||||
key: 'about',
|
||||
label: t('about'),
|
||||
onClick: () => window.open(pkg.homepage, '__blank'),
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={Settings} />,
|
||||
key: 'setting',
|
||||
label: t('setting'),
|
||||
onClick: () => Router.push('/setting'),
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionIcon icon={Github} onClick={() => window.open(pkg.homepage, '__blank')} />
|
||||
<Dropdown arrow={false} menu={{ items }} trigger={['click']}>
|
||||
{children}
|
||||
</Dropdown>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default BottomAction;
|
||||
@@ -1,106 +1,24 @@
|
||||
import { ActionIcon, Icon, SideNav } from '@lobehub/ui';
|
||||
import { Dropdown, type MenuProps } from 'antd';
|
||||
import {
|
||||
Feather,
|
||||
FileClock,
|
||||
FolderInput,
|
||||
FolderOutput,
|
||||
Github,
|
||||
Heart,
|
||||
MessageSquare,
|
||||
Settings,
|
||||
Settings2,
|
||||
Sticker,
|
||||
} from 'lucide-react';
|
||||
import { ActionIcon, SideNav } from '@lobehub/ui';
|
||||
import { MessageSquare, Settings2, Sticker } from 'lucide-react';
|
||||
import Router from 'next/router';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { memo } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import pkg from '@/../package.json';
|
||||
import AvatarWithUpload from '@/features/AvatarWithUpload';
|
||||
import { useSettings } from '@/store/settings';
|
||||
|
||||
import BottomAction from './BottomAction';
|
||||
|
||||
export default memo(() => {
|
||||
const [tab, setTab] = useSettings((s) => [s.sidebarKey, s.switchSideBar], shallow);
|
||||
const { t } = useTranslation('common');
|
||||
const items: MenuProps['items'] = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: <Icon icon={FolderInput} />,
|
||||
key: 'import',
|
||||
label: <div>{t('import')}</div>,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
key: 'allAgent',
|
||||
label: <div>{t('exportType.allAgent')}</div>,
|
||||
},
|
||||
{
|
||||
key: 'allAgentWithMessage',
|
||||
label: <div>{t('exportType.allAgentWithMessage')}</div>,
|
||||
},
|
||||
{
|
||||
key: 'globalSetting',
|
||||
label: <div>{t('exportType.globalSetting')}</div>,
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
key: 'all',
|
||||
label: <div>{t('exportType.all')}</div>,
|
||||
},
|
||||
],
|
||||
icon: <Icon icon={FolderOutput} />,
|
||||
key: 'export',
|
||||
label: t('export'),
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={Feather} />,
|
||||
key: 'feedback',
|
||||
label: t('feedback'),
|
||||
onClick: () => window.open(pkg.bugs.url, '__blank'),
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={FileClock} />,
|
||||
key: 'changelog',
|
||||
label: t('changelog'),
|
||||
onClick: () => window.open(`${pkg.homepage}/blob/master/CHANGELOG.md`, '__blank'),
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={Heart} />,
|
||||
key: 'about',
|
||||
label: t('about'),
|
||||
onClick: () => window.open(pkg.homepage, '__blank'),
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
icon: <Icon icon={Settings} />,
|
||||
key: 'setting',
|
||||
label: t('setting'),
|
||||
onClick: () => Router.push('/setting'),
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<SideNav
|
||||
avatar={<AvatarWithUpload />}
|
||||
bottomActions={
|
||||
<>
|
||||
<ActionIcon icon={Github} onClick={() => window.open(pkg.homepage, '__blank')} />
|
||||
<Dropdown arrow={false} menu={{ items }} trigger={['click']}>
|
||||
<ActionIcon icon={Settings2} />
|
||||
</Dropdown>
|
||||
</>
|
||||
<BottomAction>
|
||||
<ActionIcon active={tab === 'setting'} icon={Settings2} />
|
||||
</BottomAction>
|
||||
}
|
||||
style={{ height: '100vh' }}
|
||||
topActions={
|
||||
@@ -108,7 +26,12 @@ export default memo(() => {
|
||||
<ActionIcon
|
||||
active={tab === 'chat'}
|
||||
icon={MessageSquare}
|
||||
onClick={() => setTab('chat')}
|
||||
onClick={() => {
|
||||
// 如果已经在 chat 路径下了,那么就不用再跳转了
|
||||
if (Router.asPath.startsWith('/chat')) return;
|
||||
|
||||
Router.push('/');
|
||||
}}
|
||||
size="large"
|
||||
/>
|
||||
<ActionIcon
|
||||
|
||||
@@ -13,8 +13,8 @@ import AvatarWithUpload from '@/features/AvatarWithUpload';
|
||||
import { options } from '@/locales/options';
|
||||
import { settingsSelectors, useSettings } from '@/store/settings';
|
||||
import { DEFAULT_SETTINGS } from '@/store/settings/initialState';
|
||||
import { ConfigKeys } from '@/types/exportConfig';
|
||||
import { LanguageModel } from '@/types/llm';
|
||||
import { ConfigKeys } from '@/types/settings';
|
||||
|
||||
import { ThemeSwatchesNeutral, ThemeSwatchesPrimary } from './ThemeSwatches';
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Flexbox } from 'react-layout-kit';
|
||||
|
||||
import SideBar from '@/features/SideBar';
|
||||
import { createI18nNext } from '@/locales/create';
|
||||
import { useSettings } from '@/store/settings';
|
||||
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
||||
|
||||
const initI18n = createI18nNext('setting');
|
||||
@@ -17,6 +18,13 @@ const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
|
||||
initI18n.finally();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const hasRehydrated = useSettings.persist.hasHydrated();
|
||||
if (hasRehydrated) {
|
||||
useSettings.setState({ sidebarKey: 'setting' });
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
|
||||
Reference in New Issue
Block a user