@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
@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
6
6
  import { Center } from 'react-layout-kit';
7
7
 
8
8
  import { useGlobalStore } from '@/store/global';
9
+ import { SidebarTabKey } from '@/store/global/initialState';
9
10
  import { agentMarketSelectors, useMarketStore } from '@/store/market';
10
11
  import { useSessionStore } from '@/store/session';
11
12
 
@@ -54,7 +55,7 @@ const Header = memo(() => {
54
55
  if (!agentItem) return;
55
56
 
56
57
  createSession({ config, meta });
57
- switchSideBar('chat');
58
+ switchSideBar(SidebarTabKey.Chat);
58
59
  }}
59
60
  type={'primary'}
60
61
  >
@@ -1,4 +1,5 @@
1
1
  import { Markdown, TabsNav } from '@lobehub/ui';
2
+ import { useResponsive } from 'antd-style';
2
3
  import { memo, useState } from 'react';
3
4
  import { useTranslation } from 'react-i18next';
4
5
  import { Flexbox } from 'react-layout-kit';
@@ -22,7 +23,8 @@ const AgentModalInner = memo(() => {
22
23
  s.useFetchAgent,
23
24
  s.currentIdentifier,
24
25
  ]);
25
- const { styles } = useStyles();
26
+ const { styles, theme } = useStyles();
27
+ const { mobile } = useResponsive();
26
28
  const { data, isLoading } = useFetchAgent(currentIdentifier);
27
29
  const { t } = useTranslation('market');
28
30
  const [tab, setTab] = useState<string>(InfoTabs.prompt);
@@ -34,7 +36,13 @@ const AgentModalInner = memo(() => {
34
36
 
35
37
  return (
36
38
  <>
37
- <AgentCardBanner mask meta={meta} size={10} style={{ height: 120, marginBottom: -60 }} />
39
+ <AgentCardBanner
40
+ mask
41
+ maskColor={mobile ? theme.colorBgContainer : undefined}
42
+ meta={meta}
43
+ size={10}
44
+ style={{ height: 120, marginBottom: -60 }}
45
+ />
38
46
  <Header />
39
47
  <Flexbox align={'center'}>
40
48
  <TabsNav
@@ -1,14 +1,10 @@
1
- import { ActionIcon } from '@lobehub/ui';
2
- import { Drawer } from 'antd';
3
- import { useTheme } from 'antd-style';
4
- import { X } from 'lucide-react';
1
+ import { Modal } from '@lobehub/ui';
5
2
  import { PropsWithChildren, memo } from 'react';
6
3
  import { useTranslation } from 'react-i18next';
7
4
 
8
5
  import { agentMarketSelectors, useMarketStore } from '@/store/market';
9
6
 
10
7
  const Mobile = memo<PropsWithChildren>(({ children }) => {
11
- const theme = useTheme();
12
8
  const [showAgentSidebar, deactivateAgent] = useMarketStore((s) => [
13
9
  agentMarketSelectors.showSideBar(s),
14
10
  s.deactivateAgent,
@@ -17,19 +13,9 @@ const Mobile = memo<PropsWithChildren>(({ children }) => {
17
13
  const { t } = useTranslation('market');
18
14
 
19
15
  return (
20
- <Drawer
21
- bodyStyle={{ padding: 0 }}
22
- closeIcon={<ActionIcon icon={X} size={{ blockSize: 32, fontSize: 20 }} />}
23
- drawerStyle={{ background: theme.colorBgLayout }}
24
- headerStyle={{ padding: '8px 4px' }}
25
- height={'75vh'}
26
- onClose={deactivateAgent}
27
- open={showAgentSidebar}
28
- placement={'bottom'}
29
- title={t('sidebar.title')}
30
- >
16
+ <Modal onCancel={deactivateAgent} open={showAgentSidebar} title={t('sidebar.title')}>
31
17
  {children}
32
- </Drawer>
18
+ </Modal>
33
19
  );
34
20
  });
35
21
 
@@ -6,6 +6,7 @@ import { Center, Flexbox } from 'react-layout-kit';
6
6
  import SafeSpacing from '@/components/SafeSpacing';
7
7
  import { MAX_WIDTH } from '@/const/layoutTokens';
8
8
  import { useSwitchSideBarOnInit } from '@/store/global';
9
+ import { SidebarTabKey } from '@/store/global/initialState';
9
10
 
10
11
  import AppLayout from '../../layout/AppLayout';
11
12
  import Header from './features/Header';
@@ -27,7 +28,7 @@ const useStyles = createStyles(({ css }) => ({
27
28
  const MarketLayout = memo<PropsWithChildren>(({ children }) => {
28
29
  const { theme, styles } = useStyles();
29
30
 
30
- useSwitchSideBarOnInit('market');
31
+ useSwitchSideBarOnInit(SidebarTabKey.Market);
31
32
 
32
33
  return (
33
34
  <AppLayout>
@@ -3,12 +3,13 @@ import { Flexbox } from 'react-layout-kit';
3
3
 
4
4
  import AppMobileLayout from '@/layout/AppMobileLayout';
5
5
  import { useSwitchSideBarOnInit } from '@/store/global';
6
+ import { SidebarTabKey } from '@/store/global/initialState';
6
7
 
7
8
  import Header from './features/Header';
8
9
  import SideBar from './features/SideBar';
9
10
 
10
11
  const MarketLayout = memo<{ children: ReactNode }>(({ children }) => {
11
- useSwitchSideBarOnInit('market');
12
+ useSwitchSideBarOnInit(SidebarTabKey.Market);
12
13
 
13
14
  return (
14
15
  <AppMobileLayout navBar={<Header />} showTabBar>
@@ -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 Agent from './Agent';
10
+
11
+ const AgentSetting = memo(() => {
12
+ useSwitchSideBarOnInit(SettingsTabs.Agent);
13
+ return (
14
+ <Layout>
15
+ <Agent />
16
+ </Layout>
17
+ );
18
+ });
19
+
20
+ export default AgentSetting;
@@ -0,0 +1,7 @@
1
+ import Page from './index';
2
+
3
+ const Index = () => {
4
+ return <Page />;
5
+ };
6
+
7
+ export default Index;
@@ -15,7 +15,7 @@ import { useSessionStore } from '@/store/session';
15
15
  import { ConfigKeys } from '@/types/settings';
16
16
  import { switchLang } from '@/utils/switchLang';
17
17
 
18
- import { ThemeSwatchesNeutral, ThemeSwatchesPrimary } from '../ThemeSwatches';
18
+ import { ThemeSwatchesNeutral, ThemeSwatchesPrimary } from '../features/ThemeSwatches';
19
19
 
20
20
  type SettingItemGroup = ItemGroup & {
21
21
  children: {
@@ -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 Common from './Common';
10
+
11
+ const CommonSetting = memo(() => {
12
+ useSwitchSideBarOnInit(SettingsTabs.Common);
13
+ return (
14
+ <Layout>
15
+ <Common />
16
+ </Layout>
17
+ );
18
+ });
19
+
20
+ export default CommonSetting;
@@ -0,0 +1,7 @@
1
+ import Page from './index';
2
+
3
+ const Index = () => {
4
+ return <Page />;
5
+ };
6
+
7
+ export default Index;
@@ -1,13 +1,20 @@
1
- import { ChatHeader, ChatHeaderTitle, Logo } from '@lobehub/ui';
1
+ import { ChatHeader, ChatHeaderTitle } from '@lobehub/ui';
2
2
  import { memo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
5
+ import { useGlobalStore } from '@/store/global';
6
+
5
7
  const Index = memo(() => {
6
8
  const { t } = useTranslation('setting');
9
+ const tab = useGlobalStore((s) => s.settingsTab);
7
10
 
8
11
  return (
9
12
  <ChatHeader
10
- left={<ChatHeaderTitle title={<Logo extra={t('header.global')} type={'text'} />} />}
13
+ left={
14
+ <div style={{ paddingLeft: 8 }}>
15
+ <ChatHeaderTitle title={t(`tab.${tab}`)} />
16
+ </div>
17
+ }
11
18
  />
12
19
  );
13
20
  });
@@ -3,14 +3,17 @@ import { useRouter } from 'next/navigation';
3
3
  import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
+ import { useGlobalStore } from '@/store/global';
7
+
6
8
  const Header = memo(() => {
7
9
  const { t } = useTranslation('setting');
10
+ const tab = useGlobalStore((s) => s.settingsTab);
8
11
  const router = useRouter();
9
12
 
10
13
  return (
11
14
  <MobileNavBar
12
- center={<MobileNavBarTitle title={t('header.global')} />}
13
- onBackClick={() => router.push('/chat')}
15
+ center={<MobileNavBarTitle title={t(`tab.${tab}`)} />}
16
+ onBackClick={() => router.back()}
14
17
  showBackButton
15
18
  />
16
19
  );
@@ -0,0 +1,39 @@
1
+ import { Icon, List } from '@lobehub/ui';
2
+ import { createStyles, useResponsive } from 'antd-style';
3
+ import { ChevronRight, type LucideIcon } from 'lucide-react';
4
+ import { CSSProperties, ReactNode, memo } from 'react';
5
+
6
+ const { Item } = List;
7
+
8
+ const useStyles = createStyles(({ css }) => ({
9
+ container: css`
10
+ padding-top: 20px;
11
+ padding-bottom: 20px;
12
+ `,
13
+ }));
14
+
15
+ export interface ItemProps {
16
+ active?: boolean;
17
+ className?: string;
18
+ icon: LucideIcon;
19
+ label: ReactNode;
20
+ style?: CSSProperties;
21
+ }
22
+
23
+ const SettingItem = memo<ItemProps>(({ label, icon, active = false, style, className }) => {
24
+ const { cx, styles } = useStyles();
25
+ const { mobile } = useResponsive();
26
+ return (
27
+ <Item
28
+ active={active}
29
+ avatar={<Icon icon={icon} size={{ fontSize: 16 }} />}
30
+ className={cx(styles.container, className)}
31
+ style={style}
32
+ title={label as string}
33
+ >
34
+ {mobile && <Icon icon={ChevronRight} size={{ fontSize: 16 }} />}
35
+ </Item>
36
+ );
37
+ });
38
+
39
+ export default SettingItem;
@@ -0,0 +1,30 @@
1
+ import { useResponsive } from 'antd-style';
2
+ import { Bot, Settings2, Webhook } from 'lucide-react';
3
+ import { useRouter } from 'next/navigation';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { useGlobalStore } from '@/store/global';
8
+ import { SettingsTabs } from '@/store/global/initialState';
9
+
10
+ import Item from './Item';
11
+
12
+ const List = memo(() => {
13
+ const { t } = useTranslation('setting');
14
+ const tab = useGlobalStore((s) => s.settingsTab);
15
+ const router = useRouter();
16
+ const { mobile } = useResponsive();
17
+ const items = [
18
+ { icon: Settings2, label: t('tab.common'), value: SettingsTabs.Common },
19
+ { icon: Webhook, label: t('tab.llm'), value: SettingsTabs.LLM },
20
+ { icon: Bot, label: t('tab.agent'), value: SettingsTabs.Agent },
21
+ ];
22
+
23
+ return items.map(({ value, icon, label }) => (
24
+ <div key={value} onClick={() => router.push(`/settings/${value}`)}>
25
+ <Item active={mobile ? false : tab === value} icon={icon} label={label} />
26
+ </div>
27
+ ));
28
+ });
29
+
30
+ export default List;
@@ -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
  },