@lobehub/chat 0.82.1 → 0.82.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +22 -6
  3. package/README.zh-CN.md +21 -5
  4. package/docs/Environment-Variable.md +45 -9
  5. package/locales/en_US/common.json +1 -1
  6. package/locales/ru_RU/common.json +1 -1
  7. package/locales/zh_CN/common.json +1 -1
  8. package/locales/zh_TW/common.json +1 -1
  9. package/package.json +1 -1
  10. package/public/images/screenshot_background.webp +0 -0
  11. package/src/app/chat/features/Conversation/ChatList/Error/ApiKeyForm.tsx +44 -20
  12. package/src/app/chat/features/Conversation/ChatList/Error/InvalidAccess.tsx +20 -18
  13. package/src/app/chat/features/Conversation/ChatList/Error/OpenAiBizError.tsx +1 -11
  14. package/src/app/chat/features/Conversation/ChatList/OTPInput.tsx +0 -6
  15. package/src/app/chat/features/Header/Mobile.tsx +12 -7
  16. package/src/app/chat/features/Header/ShareButton/Inner.tsx +31 -26
  17. package/src/app/chat/features/Header/ShareButton/index.tsx +6 -1
  18. package/src/app/chat/features/SessionList/Header/Desktop.tsx +2 -4
  19. package/src/app/chat/features/SessionList/Header/Mobile.tsx +15 -14
  20. package/src/app/chat/features/Sidebar/Mobile.tsx +3 -17
  21. package/src/app/chat/layout.desktop.tsx +2 -1
  22. package/src/app/chat/layout.mobile.tsx +2 -1
  23. package/src/app/chat/settings/features/Header/index.tsx +3 -3
  24. package/src/app/chat/settings/layout.mobile.tsx +1 -8
  25. package/src/app/market/features/AgentCard/AgentCardBanner.tsx +2 -1
  26. package/src/app/market/features/Header/Mobile.tsx +2 -21
  27. package/src/app/market/features/SideBar/AgentInfo/Header.tsx +2 -1
  28. package/src/app/market/features/SideBar/AgentInfo/index.tsx +10 -2
  29. package/src/app/market/features/SideBar/Mobile.tsx +3 -17
  30. package/src/app/market/layout.desktop.tsx +2 -1
  31. package/src/app/market/layout.mobile.tsx +2 -1
  32. package/src/app/settings/agent/index.tsx +20 -0
  33. package/src/app/settings/agent/page.tsx +7 -0
  34. package/src/app/settings/{features/Settings → common}/Common.tsx +1 -1
  35. package/src/app/settings/common/index.tsx +20 -0
  36. package/src/app/settings/common/page.tsx +7 -0
  37. package/src/app/settings/features/Header/Desktop.tsx +9 -2
  38. package/src/app/settings/features/Header/Mobile.tsx +5 -2
  39. package/src/app/settings/features/SideBar/Item.tsx +39 -0
  40. package/src/app/settings/features/SideBar/List.tsx +30 -0
  41. package/src/app/settings/features/SideBar/index.tsx +38 -0
  42. package/src/app/settings/index.tsx +5 -7
  43. package/src/app/settings/layout.desktop.tsx +6 -2
  44. package/src/app/settings/layout.mobile.tsx +1 -3
  45. package/src/app/settings/{features/Settings → llm}/LLM/index.tsx +4 -2
  46. package/src/app/settings/llm/index.tsx +20 -0
  47. package/src/app/settings/llm/page.tsx +7 -0
  48. package/src/app/settings/mobile/ExtraList.tsx +61 -0
  49. package/src/app/settings/mobile/index.tsx +43 -0
  50. package/src/app/settings/mobile/page.tsx +7 -0
  51. package/src/app/settings/page.tsx +1 -7
  52. package/src/components/MobilePadding/index.tsx +32 -0
  53. package/src/const/layoutTokens.ts +1 -0
  54. package/src/features/AgentSetting/AgentMeta/index.tsx +0 -1
  55. package/src/features/AgentSetting/AgentPlugin/MarketSettingModal.tsx +29 -16
  56. package/src/features/MobileTabBar/index.tsx +15 -3
  57. package/src/features/PluginDevModal/PluginPreview.tsx +11 -4
  58. package/src/features/PluginDevModal/index.tsx +14 -10
  59. package/src/features/SideBar/BottomActions.tsx +3 -3
  60. package/src/features/SideBar/TopActions.tsx +5 -4
  61. package/src/locales/default/common.ts +1 -1
  62. package/src/locales/default/error.ts +1 -0
  63. package/src/locales/default/plugin.ts +2 -1
  64. package/src/store/global/hooks/useSwitchSettingsOnInit.ts +9 -0
  65. package/src/store/global/initialState.ts +13 -4
  66. package/src/store/global/selectors.ts +7 -0
  67. package/src/store/global/slices/settings.ts +5 -1
  68. package/src/store/global/store.ts +0 -4
  69. package/src/store/session/slices/chat/actions/share.ts +1 -1
  70. package/src/styles/antdOverride.ts +2 -26
  71. package/src/styles/global.ts +9 -0
  72. package/src/app/settings/features/Banner/index.tsx +0 -94
  73. package/src/app/settings/features/Settings/index.tsx +0 -53
  74. /package/src/app/settings/{features/Settings → agent}/Agent.tsx +0 -0
  75. /package/src/app/settings/{features/Settings → llm}/LLM/Checker.tsx +0 -0
  76. /package/src/app/settings/{features/Settings → llm}/LLM/ModelList.tsx +0 -0
  77. /package/src/app/settings/{features/Settings → llm}/LLM/getModelList.ts +0 -0
@@ -0,0 +1,38 @@
1
+ import { DraggablePanelBody, Logo } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import FolderPanel from '@/features/FolderPanel';
7
+
8
+ import List from './List';
9
+
10
+ const useStyles = createStyles(({ stylish, token, css }) => ({
11
+ body: stylish.noScrollbar,
12
+ logo: css`
13
+ fill: ${token.colorText};
14
+ `,
15
+ top: css`
16
+ position: sticky;
17
+ top: 0;
18
+ `,
19
+ }));
20
+
21
+ const SideBar = memo(() => {
22
+ const { styles } = useStyles();
23
+
24
+ return (
25
+ <FolderPanel>
26
+ <DraggablePanelBody className={styles.body} style={{ padding: 0 }}>
27
+ <Flexbox className={styles.top} padding={16}>
28
+ <div>
29
+ <Logo className={styles.logo} size={36} type={'text'} />
30
+ </div>
31
+ </Flexbox>
32
+ <List />
33
+ </DraggablePanelBody>
34
+ </FolderPanel>
35
+ );
36
+ });
37
+
38
+ export default SideBar;
@@ -2,33 +2,31 @@
2
2
 
3
3
  import { useResponsive } from 'antd-style';
4
4
  import Head from 'next/head';
5
- import { memo } from 'react';
5
+ import { ReactNode, memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
8
  import { useSwitchSideBarOnInit } from '@/store/global';
9
+ import { SidebarTabKey } from '@/store/global/initialState';
9
10
  import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
10
11
 
11
- import Settings from './features/Settings';
12
12
  import DesktopLayout from './layout.desktop';
13
13
  import MobileLayout from './layout.mobile';
14
14
 
15
- const Setting = memo(() => {
15
+ const Setting = memo<{ children: ReactNode }>(({ children }) => {
16
16
  const { mobile } = useResponsive();
17
17
  const { t } = useTranslation('setting');
18
18
  const pageTitle = genSiteHeadTitle(t('header.global'));
19
19
 
20
20
  const RenderLayout = mobile ? MobileLayout : DesktopLayout;
21
21
 
22
- useSwitchSideBarOnInit('settings');
22
+ useSwitchSideBarOnInit(SidebarTabKey.Setting);
23
23
 
24
24
  return (
25
25
  <>
26
26
  <Head>
27
27
  <title>{pageTitle}</title>
28
28
  </Head>
29
- <RenderLayout>
30
- <Settings />
31
- </RenderLayout>
29
+ <RenderLayout>{children}</RenderLayout>
32
30
  </>
33
31
  );
34
32
  });
@@ -1,19 +1,23 @@
1
1
  import { ReactNode, memo } from 'react';
2
- import { Flexbox } from 'react-layout-kit';
2
+ import { Center, Flexbox } from 'react-layout-kit';
3
3
 
4
4
  import SafeSpacing from '@/components/SafeSpacing';
5
5
  import AppLayout from '@/layout/AppLayout';
6
6
 
7
7
  import Header from './features/Header';
8
+ import SideBar from './features/SideBar';
8
9
 
9
10
  const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
10
11
  return (
11
12
  <AppLayout>
13
+ <SideBar />
12
14
  <Flexbox flex={1} height={'100vh'} style={{ position: 'relative' }}>
13
15
  <Header />
14
16
  <Flexbox align={'center'} flex={1} padding={24} style={{ overflow: 'auto' }}>
15
17
  <SafeSpacing />
16
- {children}
18
+ <Center gap={16} width={'100%'}>
19
+ {children}
20
+ </Center>
17
21
  </Flexbox>
18
22
  </Flexbox>
19
23
  </AppLayout>
@@ -8,9 +8,7 @@ import Header from './features/Header';
8
8
  const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
9
9
  return (
10
10
  <AppMobileLayout navBar={<Header />}>
11
- <Flexbox align={'center'} padding={16} style={{ overflow: 'auto' }}>
12
- {children}
13
- </Flexbox>
11
+ <Flexbox style={{ overflow: 'auto' }}>{children}</Flexbox>
14
12
  </AppMobileLayout>
15
13
  );
16
14
  });
@@ -1,4 +1,4 @@
1
- import { Form, Markdown } from '@lobehub/ui';
1
+ import { Form, type ItemGroup, Markdown } from '@lobehub/ui';
2
2
  import { Form as AntForm, AutoComplete, Input, Switch } from 'antd';
3
3
  import { createStyles } from 'antd-style';
4
4
  import { debounce } from 'lodash-es';
@@ -49,7 +49,7 @@ const LLM = memo(() => {
49
49
 
50
50
  const useAzure = useGlobalStore((s) => s.settings.languageModel.openAI.useAzure);
51
51
 
52
- const openAI = {
52
+ const openAI: ItemGroup = {
53
53
  children: [
54
54
  {
55
55
  children: (
@@ -94,6 +94,7 @@ const LLM = memo(() => {
94
94
  ),
95
95
  desc: t('llm.OpenAI.useAzure.desc'),
96
96
  label: t('llm.OpenAI.useAzure.title'),
97
+ minWidth: undefined,
97
98
  name: [configKey, 'openAI', 'useAzure'],
98
99
  valuePropName: 'checked',
99
100
  },
@@ -124,6 +125,7 @@ const LLM = memo(() => {
124
125
  children: <Checker checkModel={!useAzure} />,
125
126
  desc: t('llm.OpenAI.check.desc'),
126
127
  label: t('llm.OpenAI.check.title'),
128
+ minWidth: undefined,
127
129
  },
128
130
  // {
129
131
  // children: useAzure ? <Flexbox>{t('llm.OpenAI.models.notSupport')}</Flexbox> : <ModelList />,
@@ -0,0 +1,20 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+
5
+ import { useSwitchSideBarOnInit } from '@/store/global/hooks/useSwitchSettingsOnInit';
6
+ import { SettingsTabs } from '@/store/global/initialState';
7
+
8
+ import Layout from '../index';
9
+ import LLM from './LLM';
10
+
11
+ const LLMSetting = memo(() => {
12
+ useSwitchSideBarOnInit(SettingsTabs.LLM);
13
+ return (
14
+ <Layout>
15
+ <LLM />
16
+ </Layout>
17
+ );
18
+ });
19
+
20
+ export default LLMSetting;
@@ -0,0 +1,7 @@
1
+ import Page from './index';
2
+
3
+ const Index = () => {
4
+ return <Page />;
5
+ };
6
+
7
+ export default Index;
@@ -0,0 +1,61 @@
1
+ import { Upload } from 'antd';
2
+ import { useResponsive } from 'antd-style';
3
+ import { Feather, FileClock, HardDriveDownload, HardDriveUpload, Heart } from 'lucide-react';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { ABOUT, CHANGELOG, FEEDBACK } from '@/const/url';
8
+ import { useExportConfig } from '@/hooks/useExportConfig';
9
+ import { useImportConfig } from '@/hooks/useImportConfig';
10
+ import { useGlobalStore } from '@/store/global';
11
+
12
+ import Item from '../features/SideBar/Item';
13
+
14
+ const ExtraList = memo(() => {
15
+ const { t } = useTranslation('common');
16
+ const { exportAll } = useExportConfig();
17
+ const { importConfig } = useImportConfig();
18
+ const tab = useGlobalStore((s) => s.settingsTab);
19
+ const { mobile } = useResponsive();
20
+ const items = [
21
+ {
22
+ icon: HardDriveDownload,
23
+ label: t('export'),
24
+ onClick: exportAll,
25
+ value: 'export',
26
+ },
27
+ {
28
+ icon: Feather,
29
+ label: t('feedback'),
30
+ onClick: () => window.open(FEEDBACK, '__blank'),
31
+ value: 'feedback',
32
+ },
33
+ {
34
+ icon: FileClock,
35
+ label: t('changelog'),
36
+ onClick: () => window.open(CHANGELOG, '__blank'),
37
+ value: 'changelog',
38
+ },
39
+ {
40
+ icon: Heart,
41
+ label: t('about'),
42
+ onClick: () => window.open(ABOUT, '__blank'),
43
+ value: 'about',
44
+ },
45
+ ];
46
+
47
+ return (
48
+ <>
49
+ <Upload maxCount={1} onChange={importConfig} showUploadList={false}>
50
+ <Item icon={HardDriveUpload} label={t('import')} style={{ width: '100vw' }} />
51
+ </Upload>
52
+ {items.map(({ value, icon, label, onClick }) => (
53
+ <div key={value} onClick={onClick}>
54
+ <Item active={mobile ? false : tab === value} icon={icon} label={label} />
55
+ </div>
56
+ ))}
57
+ </>
58
+ );
59
+ });
60
+
61
+ export default ExtraList;
@@ -0,0 +1,43 @@
1
+ 'use client';
2
+
3
+ import { Divider } from 'antd';
4
+ import { memo } from 'react';
5
+ import { Center } from 'react-layout-kit';
6
+
7
+ import AgentCardBanner from '@/app/market/features/AgentCard/AgentCardBanner';
8
+ import Header from '@/app/market/features/Header';
9
+ import AvatarWithUpload from '@/features/AvatarWithUpload';
10
+ import AppMobileLayout from '@/layout/AppMobileLayout';
11
+ import { useGlobalStore, useSwitchSideBarOnInit } from '@/store/global';
12
+ import { SidebarTabKey } from '@/store/global/initialState';
13
+ import { AVATAR } from '@/store/session/slices/chat/actions/share';
14
+
15
+ import List from '../features/SideBar/List';
16
+ import ExtraList from './ExtraList';
17
+
18
+ const Setting = memo(() => {
19
+ const avatar = useGlobalStore((s) => s.settings.avatar);
20
+ useSwitchSideBarOnInit(SidebarTabKey.Setting);
21
+ return (
22
+ <AppMobileLayout navBar={<Header />} showTabBar>
23
+ <AgentCardBanner
24
+ mask
25
+ meta={{ avatar: avatar || AVATAR }}
26
+ size={10}
27
+ style={{ height: 180, marginBottom: 0 }}
28
+ >
29
+ <Center style={{ position: 'absolute', zIndex: 2 }}>
30
+ <AvatarWithUpload size={100} />
31
+ </Center>
32
+ </AgentCardBanner>
33
+ <div style={{ width: '100%' }}>
34
+ <Divider style={{ margin: '0 0 8px' }} />
35
+ <List />
36
+ <Divider style={{ margin: '8px 0' }} />
37
+ <ExtraList />
38
+ </div>
39
+ </AppMobileLayout>
40
+ );
41
+ });
42
+
43
+ export default Setting;
@@ -0,0 +1,7 @@
1
+ import Page from './index';
2
+
3
+ const Index = () => {
4
+ return <Page />;
5
+ };
6
+
7
+ export default Index;
@@ -1,7 +1 @@
1
- import Page from './index';
2
-
3
- const Index = () => {
4
- return <Page />;
5
- };
6
-
7
- export default Index;
1
+ export { default } from './common/page';
@@ -0,0 +1,32 @@
1
+ import { useResponsive } from 'antd-style';
2
+ import { ReactNode, memo } from 'react';
3
+ import { Flexbox } from 'react-layout-kit';
4
+
5
+ interface MobilePaddingProps {
6
+ bottom?: number;
7
+ children: ReactNode;
8
+ gap?: number;
9
+ left?: number;
10
+ right?: number;
11
+ top?: number;
12
+ }
13
+
14
+ const MobilePadding = memo<MobilePaddingProps>(
15
+ ({ children, top = 16, right = 16, left = 16, bottom = 16, gap }) => {
16
+ const { mobile } = useResponsive();
17
+
18
+ if (mobile)
19
+ return (
20
+ <Flexbox
21
+ gap={gap}
22
+ style={{ paddingBottom: bottom, paddingLeft: left, paddingRight: right, paddingTop: top }}
23
+ >
24
+ {children}
25
+ </Flexbox>
26
+ );
27
+
28
+ return children;
29
+ },
30
+ );
31
+
32
+ export default MobilePadding;
@@ -13,3 +13,4 @@ export const FORM_STYLE: FormProps = {
13
13
  itemMinWidth: 'max(30%,240px)',
14
14
  style: { maxWidth: MAX_WIDTH, width: '100%' },
15
15
  };
16
+ export const MOBILE_HEADER_ICON_SIZE = { blockSize: 36, fontSize: 22 };
@@ -78,7 +78,6 @@ const AgentMeta = memo(() => {
78
78
  onChange={(backgroundColor) => updateMeta({ backgroundColor })}
79
79
  />
80
80
  ),
81
- divider: false,
82
81
  label: t('settingAgent.backgroundColor.title'),
83
82
  minWidth: undefined,
84
83
  },
@@ -1,9 +1,10 @@
1
- import { Input, Modal, Tooltip } from '@lobehub/ui';
2
- import { Form } from 'antd';
1
+ import { Form, Input, Modal } from '@lobehub/ui';
2
+ import { Alert } from 'antd';
3
3
  import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { Flexbox } from 'react-layout-kit';
6
6
 
7
+ import MobilePadding from '@/components/MobilePadding';
7
8
  import { PLUGINS_INDEX_URL } from '@/const/url';
8
9
 
9
10
  interface MarketSettingModalProps {
@@ -15,20 +16,32 @@ const MarketSettingModal = memo<MarketSettingModalProps>(({ open, onOpenChange }
15
16
  const { t } = useTranslation('plugin');
16
17
 
17
18
  return (
18
- <Modal
19
- footer={null}
20
- onCancel={() => onOpenChange(false)}
21
- open={open}
22
- title={t('settings.title')}
23
- >
24
- <Flexbox gap={12}>
25
- <Form layout={'vertical'}>
26
- <Form.Item extra={t('settings.modalDesc')} label={t('settings.indexUrl.title')}>
27
- <Tooltip title={t('settings.indexUrl.tooltip')}>
28
- <Input defaultValue={PLUGINS_INDEX_URL} disabled placeholder={'https://xxxxx.com'} />
29
- </Tooltip>
30
- </Form.Item>
31
- </Form>
19
+ <Modal footer={null} onCancel={() => onOpenChange(false)} open={open} title={t('setting')}>
20
+ <Flexbox gap={16}>
21
+ <MobilePadding bottom={0} gap={16}>
22
+ <Alert message={t('settings.indexUrl.tooltip')} showIcon type={'warning'} />
23
+ </MobilePadding>
24
+ <Form
25
+ items={[
26
+ {
27
+ children: [
28
+ {
29
+ children: (
30
+ <Input
31
+ defaultValue={PLUGINS_INDEX_URL}
32
+ disabled
33
+ placeholder={PLUGINS_INDEX_URL}
34
+ style={{ width: '100%' }}
35
+ />
36
+ ),
37
+ desc: t('settings.modalDesc'),
38
+ label: t('settings.indexUrl.title'),
39
+ },
40
+ ],
41
+ title: t('settings.title'),
42
+ },
43
+ ]}
44
+ />
32
45
  </Flexbox>
33
46
  </Modal>
34
47
  );
@@ -1,12 +1,13 @@
1
1
  import { Icon, MobileTabBar, type MobileTabBarProps } from '@lobehub/ui';
2
2
  import { createStyles } from 'antd-style';
3
- import { Bot, MessageSquare } from 'lucide-react';
3
+ import { Bot, MessageSquare, User } from 'lucide-react';
4
4
  import { useRouter } from 'next/navigation';
5
5
  import { rgba } from 'polished';
6
6
  import { memo, useMemo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
9
  import { useGlobalStore } from '@/store/global';
10
+ import { SidebarTabKey } from '@/store/global/initialState';
10
11
 
11
12
  const useStyles = createStyles(({ css, token }) => ({
12
13
  active: css`
@@ -27,20 +28,31 @@ export default memo<{ className?: string }>(({ className }) => {
27
28
  icon: (active) => (
28
29
  <Icon className={active ? styles.active : undefined} icon={MessageSquare} />
29
30
  ),
30
- key: 'chat',
31
+ key: SidebarTabKey.Chat,
31
32
  onClick: () => {
33
+ setTab(SidebarTabKey.Chat);
32
34
  router.push('/chat');
33
35
  },
34
36
  title: t('tab.chat'),
35
37
  },
36
38
  {
37
39
  icon: (active) => <Icon className={active ? styles.active : undefined} icon={Bot} />,
38
- key: 'market',
40
+ key: SidebarTabKey.Market,
39
41
  onClick: () => {
42
+ setTab(SidebarTabKey.Market);
40
43
  router.push('/market');
41
44
  },
42
45
  title: t('tab.market'),
43
46
  },
47
+ {
48
+ icon: (active) => <Icon className={active ? styles.active : undefined} icon={User} />,
49
+ key: SidebarTabKey.Setting,
50
+ onClick: () => {
51
+ setTab(SidebarTabKey.Setting);
52
+ router.push('/settings/mobile');
53
+ },
54
+ title: t('tab.setting'),
55
+ },
44
56
  ],
45
57
  [t],
46
58
  );
@@ -1,5 +1,5 @@
1
1
  import { Avatar, Form } from '@lobehub/ui';
2
- import { Form as AForm, Card, FormInstance, Switch, Tag } from 'antd';
2
+ import { Form as AForm, FormInstance, Switch, Tag } from 'antd';
3
3
  import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { Flexbox } from 'react-layout-kit';
@@ -28,9 +28,16 @@ const PluginPreview = memo<{ form: FormInstance }>(({ form }) => {
28
28
  };
29
29
 
30
30
  return (
31
- <Card size={'small'} title={t('dev.preview.card')}>
32
- <Form.Item {...items} colon={false} style={{ marginBottom: 0 }} />
33
- </Card>
31
+ <Form
32
+ colon={false}
33
+ items={[
34
+ {
35
+ children: [items],
36
+ title: t('dev.preview.card'),
37
+ },
38
+ ]}
39
+ style={{ marginBottom: 0 }}
40
+ />
34
41
  );
35
42
  });
36
43
 
@@ -1,9 +1,11 @@
1
1
  import { Modal } from '@lobehub/ui';
2
- import { App, Button, Form, Popconfirm } from 'antd';
2
+ import { Alert, App, Button, Form, Popconfirm } from 'antd';
3
+ import { useResponsive } from 'antd-style';
3
4
  import { memo, useEffect, useState } from 'react';
4
5
  import { useTranslation } from 'react-i18next';
5
6
  import { Flexbox } from 'react-layout-kit';
6
7
 
8
+ import MobilePadding from '@/components/MobilePadding';
7
9
  import { CustomPlugin } from '@/types/plugin';
8
10
 
9
11
  import ManifestForm from './ManifestForm';
@@ -25,7 +27,7 @@ const DevModal = memo<DevModalProps>(
25
27
  const isEditMode = mode === 'edit';
26
28
  const { t } = useTranslation('plugin');
27
29
  const { message } = App.useApp();
28
-
30
+ const { mobile } = useResponsive();
29
31
  const [submitting, setSubmitting] = useState(false);
30
32
  const [form] = Form.useForm();
31
33
  useEffect(() => {
@@ -98,14 +100,16 @@ const DevModal = memo<DevModalProps>(
98
100
  open={open}
99
101
  title={t('dev.title')}
100
102
  >
101
- <Flexbox gap={12}>
102
- {t('dev.modalDesc')}
103
- {/*<Tabs*/}
104
- {/* items={[*/}
105
- {/* { children: <MetaForm />, key: 'meta', label: t('dev.tabs.meta') },*/}
106
- {/* { children: <ManifestForm />, key: 'manifest', label: t('dev.tabs.manifest') },*/}
107
- {/* ]}*/}
108
- {/*/>*/}
103
+ <Flexbox gap={mobile ? 0 : 16}>
104
+ <MobilePadding bottom={0} gap={16}>
105
+ <Alert message={t('dev.modalDesc')} showIcon type={'info'} />
106
+ {/*<Tabs*/}
107
+ {/* items={[*/}
108
+ {/* { children: <MetaForm />, key: 'meta', label: t('dev.tabs.meta') },*/}
109
+ {/* { children: <ManifestForm />, key: 'manifest', label: t('dev.tabs.manifest') },*/}
110
+ {/* ]}*/}
111
+ {/*/>*/}
112
+ </MobilePadding>
109
113
  <PluginPreview form={form} />
110
114
  <ManifestForm form={form} />
111
115
  <MetaForm form={form} mode={mode} />
@@ -18,6 +18,7 @@ import { ABOUT, CHANGELOG, DISCORD, FEEDBACK, GITHUB } from '@/const/url';
18
18
  import { useExportConfig } from '@/hooks/useExportConfig';
19
19
  import { useImportConfig } from '@/hooks/useImportConfig';
20
20
  import { GlobalStore } from '@/store/global';
21
+ import { SidebarTabKey } from '@/store/global/initialState';
21
22
 
22
23
  export interface BottomActionProps {
23
24
  setTab: GlobalStore['switchSideBar'];
@@ -27,7 +28,6 @@ export interface BottomActionProps {
27
28
  const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
28
29
  const router = useRouter();
29
30
  const { t } = useTranslation('common');
30
-
31
31
  const { exportSessions, exportSettings, exportAll, exportAgents } = useExportConfig();
32
32
  const { importConfig } = useImportConfig();
33
33
 
@@ -101,7 +101,7 @@ const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
101
101
  key: 'setting',
102
102
  label: t('setting'),
103
103
  onClick: () => {
104
- setTab('settings');
104
+ setTab(SidebarTabKey.Setting);
105
105
  router.push('/settings');
106
106
  },
107
107
  },
@@ -124,7 +124,7 @@ const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
124
124
  title={'Github'}
125
125
  />
126
126
  <Dropdown arrow={false} menu={{ items }} trigger={['click']}>
127
- <ActionIcon active={tab === 'settings'} icon={Settings2} />
127
+ <ActionIcon active={tab === SidebarTabKey.Setting} icon={Settings2} />
128
128
  </Dropdown>
129
129
  </>
130
130
  );
@@ -5,6 +5,7 @@ import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { GlobalStore } from '@/store/global';
8
+ import { SidebarTabKey } from '@/store/global/initialState';
8
9
  import { useSessionStore } from '@/store/session';
9
10
 
10
11
  export interface TopActionProps {
@@ -20,25 +21,25 @@ const TopActions = memo<TopActionProps>(({ tab, setTab }) => {
20
21
  return (
21
22
  <>
22
23
  <ActionIcon
23
- active={tab === 'chat'}
24
+ active={tab === SidebarTabKey.Chat}
24
25
  icon={MessageSquare}
25
26
  onClick={() => {
26
27
  // 如果已经在 chat 路径下了,那么就不用再跳转了
27
28
  if (pathname?.startsWith('/chat')) return;
28
29
  switchBackToChat();
29
- setTab('chat');
30
+ setTab(SidebarTabKey.Chat);
30
31
  }}
31
32
  placement={'right'}
32
33
  size="large"
33
34
  title={t('tab.chat')}
34
35
  />
35
36
  <ActionIcon
36
- active={tab === 'market'}
37
+ active={tab === SidebarTabKey.Market}
37
38
  icon={Bot}
38
39
  onClick={() => {
39
40
  if (pathname?.startsWith('/market')) return;
40
41
  router.push('/market');
41
- setTab('market');
42
+ setTab(SidebarTabKey.Market);
42
43
  }}
43
44
  placement={'right'}
44
45
  size="large"
@@ -38,7 +38,7 @@ export default {
38
38
  import: '导入配置',
39
39
  inbox: {
40
40
  defaultMessage:
41
- '你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击<kbd>+</kbd>创建自定义助手',
41
+ '你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击`+`创建自定义助手',
42
42
  desc: '开启大脑集群,激发思维火花。你的智能助理,在这里与你交流一切',
43
43
  title: '随便聊聊',
44
44
  },
@@ -39,6 +39,7 @@ export default {
39
39
  description: '输入你的 OpenAI API Key 即可绕过密码验证。应用不会记录你的 API Key',
40
40
  title: '使用自定义 API Key',
41
41
  },
42
+ closeMessage: '关闭提示',
42
43
  confirm: '确认并重试',
43
44
  password: {
44
45
  description: '管理员已开启应用加密,输入应用密码后即可解锁应用。密码只需填写一次',
@@ -96,10 +96,11 @@ export default {
96
96
  plugins: {
97
97
  unknown: '插件检测中...',
98
98
  },
99
+ setting: '插件设置',
99
100
  settings: {
100
101
  indexUrl: {
101
102
  title: '市场索引',
102
- tooltip: '暂不支持编辑',
103
+ tooltip: '暂不支持在线编辑,请通过部署时环境变量进行设置',
103
104
  },
104
105
  modalDesc: '配置插件市场的地址后,可以使用自定义的插件市场',
105
106
  title: '设置插件市场',
@@ -0,0 +1,9 @@
1
+ import { SettingsTabs } from '../initialState';
2
+ import { useGlobalStore } from '../store';
3
+
4
+ /**
5
+ * 切换设置侧边栏选项
6
+ */
7
+ export const useSwitchSideBarOnInit = (key: SettingsTabs) => {
8
+ useGlobalStore.getState().switchSettingTabs(key);
9
+ };