@lobehub/chat 0.81.0 → 0.82.2

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 (83) hide show
  1. package/CHANGELOG.md +75 -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/docs/Environment-Variable.zh-CN.md +3 -6
  6. package/locales/en_US/common.json +13 -1
  7. package/locales/ru_RU/common.json +13 -1
  8. package/locales/zh_CN/common.json +13 -1
  9. package/locales/zh_TW/common.json +13 -1
  10. package/package.json +6 -3
  11. package/public/images/screenshot_background.webp +0 -0
  12. package/public/manifest.json +2 -16
  13. package/src/app/chat/features/Conversation/ChatList/Error/InvalidAccess.tsx +16 -6
  14. package/src/app/chat/features/Header/Mobile.tsx +12 -7
  15. package/src/app/chat/features/Header/ShareButton/Inner.tsx +114 -14
  16. package/src/app/chat/features/Header/ShareButton/Preview.tsx +140 -0
  17. package/src/app/chat/features/Header/ShareButton/index.tsx +12 -2
  18. package/src/app/chat/features/Header/ShareButton/style.ts +71 -0
  19. package/src/app/chat/features/SessionList/Header/Desktop.tsx +2 -4
  20. package/src/app/chat/features/SessionList/Header/Mobile.tsx +15 -14
  21. package/src/app/chat/features/Sidebar/Mobile.tsx +3 -17
  22. package/src/app/chat/layout.desktop.tsx +2 -1
  23. package/src/app/chat/layout.mobile.tsx +2 -1
  24. package/src/app/chat/settings/features/Header/index.tsx +3 -3
  25. package/src/app/chat/settings/layout.mobile.tsx +1 -8
  26. package/src/app/market/features/AgentCard/AgentCardBanner.tsx +2 -1
  27. package/src/app/market/features/Header/Mobile.tsx +2 -21
  28. package/src/app/market/features/SideBar/AgentInfo/Header.tsx +2 -1
  29. package/src/app/market/features/SideBar/AgentInfo/index.tsx +10 -2
  30. package/src/app/market/features/SideBar/Mobile.tsx +3 -17
  31. package/src/app/market/layout.desktop.tsx +2 -1
  32. package/src/app/market/layout.mobile.tsx +2 -1
  33. package/src/app/settings/agent/index.tsx +20 -0
  34. package/src/app/settings/agent/page.tsx +7 -0
  35. package/src/app/settings/{features/Settings → common}/Common.tsx +1 -1
  36. package/src/app/settings/common/index.tsx +20 -0
  37. package/src/app/settings/common/page.tsx +7 -0
  38. package/src/app/settings/features/Header/Desktop.tsx +9 -2
  39. package/src/app/settings/features/Header/Mobile.tsx +5 -2
  40. package/src/app/settings/features/SideBar/Item.tsx +39 -0
  41. package/src/app/settings/features/SideBar/List.tsx +30 -0
  42. package/src/app/settings/features/SideBar/index.tsx +38 -0
  43. package/src/app/settings/index.tsx +5 -7
  44. package/src/app/settings/layout.desktop.tsx +6 -2
  45. package/src/app/settings/layout.mobile.tsx +1 -3
  46. package/src/app/settings/{features/Settings → llm}/LLM/index.tsx +4 -2
  47. package/src/app/settings/llm/index.tsx +20 -0
  48. package/src/app/settings/llm/page.tsx +7 -0
  49. package/src/app/settings/mobile/ExtraList.tsx +61 -0
  50. package/src/app/settings/mobile/index.tsx +43 -0
  51. package/src/app/settings/mobile/page.tsx +7 -0
  52. package/src/app/settings/page.tsx +1 -7
  53. package/src/components/MobilePadding/index.tsx +32 -0
  54. package/src/const/layoutTokens.ts +1 -0
  55. package/src/features/AgentSetting/AgentMeta/index.tsx +0 -1
  56. package/src/features/AgentSetting/AgentPlugin/MarketSettingModal.tsx +29 -16
  57. package/src/features/AvatarWithUpload/index.tsx +23 -45
  58. package/src/features/MobileTabBar/index.tsx +15 -3
  59. package/src/features/PluginDevModal/PluginPreview.tsx +11 -4
  60. package/src/features/PluginDevModal/index.tsx +14 -10
  61. package/src/features/SideBar/BottomActions.tsx +3 -3
  62. package/src/features/SideBar/TopActions.tsx +5 -4
  63. package/src/features/SideBar/index.tsx +1 -1
  64. package/src/locales/create.ts +5 -3
  65. package/src/locales/default/common.ts +13 -1
  66. package/src/locales/default/plugin.ts +2 -1
  67. package/src/services/shareGPT.ts +11 -1
  68. package/src/store/global/hooks/useSwitchSettingsOnInit.ts +9 -0
  69. package/src/store/global/initialState.ts +13 -4
  70. package/src/store/global/store.ts +0 -4
  71. package/src/store/session/slices/chat/actions/share.ts +73 -39
  72. package/src/styles/antdOverride.ts +2 -26
  73. package/src/styles/global.ts +9 -0
  74. package/src/utils/imageToBase64.ts +37 -0
  75. package/src/utils/parseMarkdown.ts +9 -0
  76. package/public/icons/icon-maskable-192x192.png +0 -0
  77. package/public/icons/icon-maskable-512x512.png +0 -0
  78. package/src/app/settings/features/Banner/index.tsx +0 -94
  79. package/src/app/settings/features/Settings/index.tsx +0 -53
  80. /package/src/app/settings/{features/Settings → agent}/Agent.tsx +0 -0
  81. /package/src/app/settings/{features/Settings → llm}/LLM/Checker.tsx +0 -0
  82. /package/src/app/settings/{features/Settings → llm}/LLM/ModelList.tsx +0 -0
  83. /package/src/app/settings/{features/Settings → llm}/LLM/getModelList.ts +0 -0
@@ -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
  );
@@ -4,6 +4,7 @@ import { createStyles } from 'antd-style';
4
4
  import { CSSProperties, memo } from 'react';
5
5
 
6
6
  import { useGlobalStore } from '@/store/global';
7
+ import { imageToBase64 } from '@/utils/imageToBase64';
7
8
  import { createUploadImageHandler } from '@/utils/uploadFIle';
8
9
 
9
10
  const useStyle = createStyles(
@@ -26,56 +27,33 @@ const useStyle = createStyles(
26
27
 
27
28
  interface AvatarWithUploadProps {
28
29
  compressSize?: number;
30
+ id?: string;
29
31
  size?: number;
30
32
  style?: CSSProperties;
31
33
  }
32
34
 
33
- const AvatarWithUpload = memo<AvatarWithUploadProps>(({ size = 40, compressSize = 128, style }) => {
34
- const [avatar, setSettings] = useGlobalStore((st) => [st.settings.avatar, st.setSettings]);
35
- const { styles } = useStyle();
36
-
37
- const handleUploadAvatar = createUploadImageHandler((avatar) => {
38
- const img = new Image();
39
- img.src = avatar;
40
- img.addEventListener('load', () => {
41
- const canvas = document.createElement('canvas');
42
- const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
43
- let startX = 0;
44
- let startY = 0;
45
-
46
- if (img.width > img.height) {
47
- startX = (img.width - img.height) / 2;
48
- } else {
49
- startY = (img.height - img.width) / 2;
50
- }
51
-
52
- canvas.width = compressSize;
53
- canvas.height = compressSize;
54
-
55
- ctx.drawImage(
56
- img,
57
- startX,
58
- startY,
59
- Math.min(img.width, img.height),
60
- Math.min(img.width, img.height),
61
- 0,
62
- 0,
63
- compressSize,
64
- compressSize,
65
- );
66
-
67
- const webpBase64 = canvas.toDataURL('image/webp');
68
- setSettings({ avatar: webpBase64 });
35
+ const AvatarWithUpload = memo<AvatarWithUploadProps>(
36
+ ({ size = 40, compressSize = 128, style, id }) => {
37
+ const [avatar, setSettings] = useGlobalStore((st) => [st.settings.avatar, st.setSettings]);
38
+ const { styles } = useStyle();
39
+
40
+ const handleUploadAvatar = createUploadImageHandler((avatar) => {
41
+ const img = new Image();
42
+ img.src = avatar;
43
+ img.addEventListener('load', () => {
44
+ const webpBase64 = imageToBase64({ img, size: compressSize });
45
+ setSettings({ avatar: webpBase64 });
46
+ });
69
47
  });
70
- });
71
48
 
72
- return (
73
- <div className={styles} style={{ maxHeight: size, maxWidth: size, ...style }}>
74
- <Upload beforeUpload={handleUploadAvatar} itemRender={() => void 0} maxCount={1}>
75
- {avatar ? <Avatar avatar={avatar} size={size} /> : <Logo size={size} />}
76
- </Upload>
77
- </div>
78
- );
79
- });
49
+ return (
50
+ <div className={styles} id={id} style={{ maxHeight: size, maxWidth: size, ...style }}>
51
+ <Upload beforeUpload={handleUploadAvatar} itemRender={() => void 0} maxCount={1}>
52
+ {avatar ? <Avatar avatar={avatar} size={size} /> : <Logo size={size} />}
53
+ </Upload>
54
+ </div>
55
+ );
56
+ },
57
+ );
80
58
 
81
59
  export default AvatarWithUpload;
@@ -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"
@@ -12,7 +12,7 @@ export default memo(() => {
12
12
 
13
13
  return (
14
14
  <SideNav
15
- avatar={<AvatarWithUpload />}
15
+ avatar={<AvatarWithUpload id={'avatar'} />}
16
16
  bottomActions={<BottomActions setTab={setTab} tab={tab} />}
17
17
  style={{ height: '100vh' }}
18
18
  topActions={<TopActions setTab={setTab} tab={tab} />}
@@ -7,6 +7,8 @@ import type { Namespaces } from '@/types/locale';
7
7
 
8
8
  import resources from './resources';
9
9
 
10
+ const isDev = process.env.NODE_ENV === 'development';
11
+
10
12
  export const createI18nNext = (params: { namespace?: Namespaces[] | Namespaces } = {}) => {
11
13
  const { namespace } = params;
12
14
 
@@ -18,16 +20,16 @@ export const createI18nNext = (params: { namespace?: Namespaces[] | Namespaces }
18
20
  .use(LanguageDetector)
19
21
  .use(initReactI18next)
20
22
  .init({
21
- debug: process.env.NODE_ENV === 'development',
23
+ debug: isDev,
22
24
  defaultNS: ns,
23
25
  detection: {
24
26
  caches: [],
25
27
  },
26
- fallbackLng: 'en-US',
28
+ fallbackLng: isDev ? 'zh-CN' : 'en-US',
27
29
  interpolation: {
28
30
  escapeValue: false,
29
31
  },
30
- lng: 'en-US',
32
+ lng: isDev ? 'zh-CN' : 'en-US',
31
33
  ns,
32
34
  resources,
33
35
  });
@@ -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
  },
@@ -49,6 +49,7 @@ export default {
49
49
  newAgent: '新建助手',
50
50
  noDescription: '暂无描述',
51
51
  ok: '确定',
52
+ password: '密码',
52
53
  pin: '置顶',
53
54
  pinOff: '取消置顶',
54
55
  regenerate: '重新生成',
@@ -62,6 +63,17 @@ export default {
62
63
  sessionList: '助手列表',
63
64
  setting: '设置',
64
65
  share: '分享',
66
+ shareModal: {
67
+ download: '下载截图',
68
+ imageType: '图片格式',
69
+ screenshot: '截图',
70
+ settings: '导出设置',
71
+ shareToShareGPT: '生成 ShareGPT 分享链接',
72
+ withBackground: '包含背景图片',
73
+ withFooter: '包含页脚',
74
+ withPluginInfo: '包含插件信息',
75
+ withSystemRole: '包含助手角色设定',
76
+ },
65
77
  stop: '停止',
66
78
  tab: {
67
79
  chat: '会话',
@@ -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: '设置插件市场',
@@ -1,10 +1,20 @@
1
1
  import { ShareGPTConversation } from '@/types/share';
2
+ import { parseMarkdown } from '@/utils/parseMarkdown';
2
3
 
3
4
  const SHAREGPT_URL = 'https://sharegpt.com/api/conversations';
4
5
 
5
6
  export const genShareGPTUrl = async (conversation: ShareGPTConversation) => {
7
+ const items = [];
8
+
9
+ for (const item of conversation.items) {
10
+ items.push({
11
+ from: item.from,
12
+ value: item.from === 'gpt' ? await parseMarkdown(item.value) : item.value,
13
+ });
14
+ }
15
+
6
16
  const res = await fetch(SHAREGPT_URL, {
7
- body: JSON.stringify(conversation),
17
+ body: JSON.stringify({ ...conversation, items }),
8
18
  headers: {
9
19
  'Content-Type': 'application/json',
10
20
  },
@@ -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
+ };
@@ -1,9 +1,17 @@
1
1
  import { DEFAULT_SETTINGS } from '@/const/settings';
2
2
  import type { GlobalSettings } from '@/types/settings';
3
3
 
4
- export type SidebarTabKey = 'chat' | 'market' | 'settings';
4
+ export enum SidebarTabKey {
5
+ Chat = 'chat',
6
+ Market = 'market',
7
+ Setting = 'settings',
8
+ }
5
9
 
6
- export type SettingsTabs = 'agent' | 'common' | 'llm';
10
+ export enum SettingsTabs {
11
+ Agent = 'agent',
12
+ Common = 'common',
13
+ LLM = 'llm',
14
+ }
7
15
 
8
16
  export interface Guide {
9
17
  // Topic 引导
@@ -21,7 +29,7 @@ export interface GlobalState {
21
29
  * 用户设置
22
30
  */
23
31
  settings: GlobalSettings;
24
- settingsTab?: SettingsTabs;
32
+ settingsTab: SettingsTabs;
25
33
  sidebarKey: SidebarTabKey;
26
34
  }
27
35
 
@@ -44,5 +52,6 @@ export const initialState: GlobalState = {
44
52
  showSessionPanel: true,
45
53
  },
46
54
  settings: DEFAULT_SETTINGS,
47
- sidebarKey: 'chat',
55
+ settingsTab: SettingsTabs.Common,
56
+ sidebarKey: SidebarTabKey.Chat,
48
57
  };
@@ -69,10 +69,6 @@ const persistOptions: PersistOptions<GlobalStore, GlobalPersist> = {
69
69
  dbName: 'LobeHub',
70
70
  selectors: ['preference', 'settings'],
71
71
  },
72
- url: {
73
- mode: 'hash',
74
- selectors: [{ settingsTab: 'tab' }],
75
- },
76
72
  }),
77
73
  };
78
74