@lobehub/chat 0.152.6 → 0.152.8

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 (206) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/docs/self-hosting/advanced/settings-url-share.mdx +100 -0
  3. package/docs/self-hosting/advanced/settings-url-share.zh-CN.mdx +100 -0
  4. package/locales/ar/common.json +1 -0
  5. package/locales/ar/setting.json +4 -1
  6. package/locales/bg-BG/common.json +1 -0
  7. package/locales/bg-BG/setting.json +4 -1
  8. package/locales/de-DE/common.json +1 -0
  9. package/locales/de-DE/setting.json +4 -1
  10. package/locales/en-US/common.json +1 -0
  11. package/locales/en-US/setting.json +4 -1
  12. package/locales/es-ES/common.json +1 -0
  13. package/locales/es-ES/setting.json +4 -1
  14. package/locales/fr-FR/common.json +1 -0
  15. package/locales/fr-FR/setting.json +4 -1
  16. package/locales/it-IT/common.json +1 -0
  17. package/locales/it-IT/setting.json +4 -1
  18. package/locales/ja-JP/common.json +1 -0
  19. package/locales/ja-JP/setting.json +4 -1
  20. package/locales/ko-KR/common.json +1 -0
  21. package/locales/ko-KR/setting.json +4 -1
  22. package/locales/nl-NL/common.json +1 -0
  23. package/locales/nl-NL/setting.json +4 -1
  24. package/locales/pl-PL/common.json +1 -0
  25. package/locales/pl-PL/setting.json +4 -1
  26. package/locales/pt-BR/common.json +1 -0
  27. package/locales/pt-BR/setting.json +4 -1
  28. package/locales/ru-RU/common.json +1 -0
  29. package/locales/ru-RU/setting.json +4 -1
  30. package/locales/tr-TR/common.json +1 -0
  31. package/locales/tr-TR/setting.json +4 -1
  32. package/locales/vi-VN/common.json +1 -0
  33. package/locales/vi-VN/setting.json +4 -1
  34. package/locales/zh-CN/common.json +1 -0
  35. package/locales/zh-CN/setting.json +4 -1
  36. package/locales/zh-TW/common.json +1 -0
  37. package/locales/zh-TW/setting.json +4 -1
  38. package/package.json +1 -1
  39. package/src/app/(main)/(mobile)/me/features/AvatarBanner.tsx +52 -0
  40. package/src/app/(main)/(mobile)/me/features/Cate.tsx +35 -0
  41. package/src/app/(main)/(mobile)/me/features/ExtraCate.tsx +26 -0
  42. package/src/app/(main)/(mobile)/me/features/useExtraCate.tsx +62 -0
  43. package/src/app/(main)/(mobile)/me/layout.tsx +11 -0
  44. package/src/app/(main)/(mobile)/me/loading.tsx +17 -0
  45. package/src/app/(main)/(mobile)/me/page.tsx +31 -0
  46. package/src/app/(main)/@nav/_layout/Desktop/index.tsx +1 -1
  47. package/src/app/(main)/@nav/_layout/Mobile.tsx +3 -3
  48. package/src/app/(main)/chat/(mobile)/features/SessionHeader.tsx +3 -3
  49. package/src/app/(main)/chat/_layout/Desktop/index.tsx +6 -8
  50. package/src/app/(main)/chat/_layout/Mobile/index.tsx +5 -3
  51. package/src/app/(main)/chat/_layout/type.ts +5 -0
  52. package/src/app/(main)/chat/features/SettingButton.tsx +3 -4
  53. package/src/app/(main)/chat/features/ShareButton/ShareModal.tsx +2 -2
  54. package/src/app/(main)/chat/layout.ts +5 -2
  55. package/src/app/(main)/chat/settings/{(desktop) → _layout/Desktop}/Header.tsx +2 -0
  56. package/src/app/(main)/chat/settings/_layout/Desktop/index.tsx +28 -0
  57. package/src/app/(main)/chat/settings/{(mobile) → _layout/Mobile}/Header.tsx +3 -2
  58. package/src/app/(main)/chat/settings/_layout/Mobile/index.tsx +15 -0
  59. package/src/app/(main)/chat/settings/error.tsx +5 -0
  60. package/src/app/(main)/chat/settings/features/HeaderContent.tsx +15 -9
  61. package/src/app/(main)/chat/settings/features/SubmitAgentButton/SubmitAgentModal.tsx +2 -0
  62. package/src/app/(main)/chat/settings/features/SubmitAgentButton/index.tsx +16 -8
  63. package/src/app/(main)/chat/settings/layout.tsx +9 -2
  64. package/src/app/(main)/chat/settings/loading.tsx +3 -0
  65. package/src/app/(main)/chat/settings/not-found.tsx +3 -0
  66. package/src/app/(main)/chat/settings/page.tsx +2 -9
  67. package/src/app/(main)/market/@detail/default.tsx +1 -10
  68. package/src/app/(main)/market/{@detail/_layout/Desktop.tsx → _layout/Desktop/DetailSidebar.tsx} +2 -2
  69. package/src/app/(main)/market/_layout/Desktop/index.tsx +2 -1
  70. package/src/app/(main)/market/{@detail/_layout/Mobile.tsx → _layout/Mobile/DetailModal.tsx} +2 -2
  71. package/src/app/(main)/market/_layout/Mobile/index.tsx +3 -1
  72. package/src/app/(main)/settings/@category/default.tsx +16 -0
  73. package/src/app/(main)/settings/@category/features/CategoryContent.tsx +33 -0
  74. package/src/app/(main)/settings/@category/features/UpgradeAlert.tsx +38 -0
  75. package/src/app/(main)/settings/_layout/Desktop/Header.tsx +78 -23
  76. package/src/app/(main)/settings/_layout/Desktop/SideBar.tsx +39 -27
  77. package/src/app/(main)/settings/_layout/Desktop/index.tsx +41 -17
  78. package/src/app/(main)/settings/_layout/Mobile/{SubSettingHeader.tsx → Header.tsx} +3 -1
  79. package/src/app/(main)/settings/_layout/Mobile/index.tsx +7 -18
  80. package/src/app/(main)/settings/_layout/type.ts +6 -0
  81. package/src/app/(main)/settings/about/features/AboutList.tsx +134 -0
  82. package/src/app/(main)/settings/about/features/Analytics.tsx +42 -0
  83. package/src/app/(main)/settings/about/index.tsx +46 -0
  84. package/src/app/(main)/settings/about/page.tsx +13 -33
  85. package/src/app/(main)/settings/agent/{Agent.tsx → index.tsx} +8 -4
  86. package/src/app/(main)/settings/agent/page.tsx +8 -16
  87. package/src/app/(main)/settings/common/{Common.tsx → features/Common.tsx} +6 -4
  88. package/src/app/(main)/settings/common/{Theme.tsx → features/Theme/index.tsx} +8 -6
  89. package/src/app/(main)/settings/common/index.tsx +11 -16
  90. package/src/app/(main)/settings/common/page.tsx +8 -7
  91. package/src/app/(main)/settings/error.tsx +5 -0
  92. package/src/app/(main)/settings/features/Footer.tsx +2 -0
  93. package/src/app/(main)/settings/features/UpgradeAlert.tsx +21 -13
  94. package/src/app/(main)/settings/hooks/useCategory.tsx +54 -0
  95. package/src/app/(main)/settings/hooks/useSyncSettings.ts +2 -2
  96. package/src/app/(main)/settings/layout.ts +4 -1
  97. package/src/app/(main)/settings/llm/Anthropic/index.tsx +4 -8
  98. package/src/app/(main)/settings/llm/Azure/index.tsx +3 -1
  99. package/src/app/(main)/settings/llm/Bedrock/index.tsx +3 -1
  100. package/src/app/(main)/settings/llm/Google/index.tsx +4 -2
  101. package/src/app/(main)/settings/llm/Groq/index.tsx +3 -1
  102. package/src/app/(main)/settings/llm/Minimax/index.tsx +3 -9
  103. package/src/app/(main)/settings/llm/Mistral/index.tsx +3 -9
  104. package/src/app/(main)/settings/llm/Moonshot/index.tsx +3 -1
  105. package/src/app/(main)/settings/llm/Ollama/index.tsx +3 -1
  106. package/src/app/(main)/settings/llm/OpenAI/index.tsx +2 -0
  107. package/src/app/(main)/settings/llm/OpenRouter/index.tsx +3 -9
  108. package/src/app/(main)/settings/llm/Perplexity/index.tsx +3 -9
  109. package/src/app/(main)/settings/llm/TogetherAI/index.tsx +3 -9
  110. package/src/app/(main)/settings/llm/ZeroOne/index.tsx +3 -9
  111. package/src/app/(main)/settings/llm/Zhipu/index.tsx +3 -10
  112. package/src/app/(main)/settings/llm/components/Checker.tsx +2 -0
  113. package/src/app/(main)/settings/llm/components/Footer.tsx +26 -0
  114. package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +29 -3
  115. package/src/app/(main)/settings/llm/index.tsx +11 -23
  116. package/src/app/(main)/settings/llm/page.tsx +15 -0
  117. package/src/app/(main)/settings/loading.tsx +9 -0
  118. package/src/app/(main)/settings/not-found.tsx +3 -0
  119. package/src/app/(main)/settings/page.tsx +2 -14
  120. package/src/app/(main)/settings/sync/{DeviceInfo → features/DeviceInfo}/Card.tsx +6 -5
  121. package/src/app/(main)/settings/sync/features/DeviceInfo/DeviceName.tsx +63 -0
  122. package/src/app/(main)/settings/sync/{components → features/DeviceInfo}/SystemIcon.tsx +6 -14
  123. package/src/app/(main)/settings/sync/{DeviceInfo → features/DeviceInfo}/index.tsx +22 -36
  124. package/src/app/(main)/settings/sync/{WebRTC → features/WebRTC}/ChannelNameInput.tsx +3 -3
  125. package/src/app/(main)/settings/sync/{WebRTC → features/WebRTC}/index.tsx +10 -9
  126. package/src/app/(main)/settings/sync/index.tsx +17 -0
  127. package/src/app/(main)/settings/sync/page.tsx +11 -15
  128. package/src/app/(main)/settings/tts/features/OpenAI.tsx +54 -0
  129. package/src/app/(main)/settings/tts/{TTS/index.tsx → features/STT.tsx} +11 -27
  130. package/src/app/(main)/settings/tts/index.tsx +15 -0
  131. package/src/app/(main)/settings/tts/page.tsx +8 -16
  132. package/src/app/layout.tsx +6 -2
  133. package/src/components/BrandWatermark/index.tsx +39 -0
  134. package/src/components/Cell/Divider.tsx +19 -0
  135. package/src/components/Cell/index.tsx +38 -0
  136. package/src/components/Menu/index.tsx +97 -0
  137. package/src/components/SkeletonLoading/index.tsx +21 -0
  138. package/src/const/url.ts +2 -0
  139. package/src/features/AgentSetting/AgentChat/index.tsx +135 -0
  140. package/src/features/AgentSetting/AgentMeta/index.tsx +4 -3
  141. package/src/features/AgentSetting/AgentModal/index.tsx +95 -0
  142. package/src/features/AgentSetting/AgentPlugin/index.tsx +65 -66
  143. package/src/features/AgentSetting/AgentPrompt/index.tsx +101 -47
  144. package/src/features/AgentSetting/AgentTTS/index.tsx +4 -0
  145. package/src/features/AgentSetting/StoreUpdater.tsx +2 -0
  146. package/src/features/AgentSetting/index.tsx +6 -6
  147. package/src/features/AgentSetting/store/index.ts +2 -0
  148. package/src/features/AvatarWithUpload/index.tsx +4 -2
  149. package/src/hooks/useQuery.test.ts +20 -0
  150. package/src/hooks/useQuery.ts +7 -0
  151. package/src/hooks/useQueryRoute.test.ts +86 -0
  152. package/src/hooks/useQueryRoute.ts +46 -0
  153. package/src/layout/GlobalProvider/index.tsx +7 -1
  154. package/src/locales/default/common.ts +1 -0
  155. package/src/locales/default/setting.ts +3 -0
  156. package/src/services/chat.ts +2 -2
  157. package/src/store/chat/slices/message/selectors.ts +2 -2
  158. package/src/store/global/initialState.ts +1 -0
  159. package/src/store/serverConfig/Provider.tsx +3 -2
  160. package/src/store/serverConfig/selectors.ts +1 -0
  161. package/src/store/serverConfig/store.ts +1 -0
  162. package/src/store/user/initialState.ts +5 -3
  163. package/src/store/user/selectors.ts +1 -1
  164. package/src/store/user/slices/auth/action.test.ts +118 -0
  165. package/src/store/user/slices/auth/action.ts +81 -0
  166. package/src/store/user/slices/auth/initialState.ts +20 -0
  167. package/src/store/user/slices/auth/selectors.ts +6 -0
  168. package/src/store/user/slices/common/action.test.ts +1 -224
  169. package/src/store/user/slices/common/action.ts +3 -112
  170. package/src/store/user/slices/settings/initialState.ts +0 -2
  171. package/src/store/user/slices/sync/action.test.ts +150 -0
  172. package/src/store/user/slices/sync/action.ts +94 -0
  173. package/src/store/user/slices/{common → sync}/initialState.ts +2 -7
  174. package/src/store/user/store.ts +11 -2
  175. package/src/app/(main)/chat/settings/(desktop)/index.tsx +0 -23
  176. package/src/app/(main)/chat/settings/(mobile)/index.tsx +0 -16
  177. package/src/app/(main)/settings/(desktop)/index.tsx +0 -23
  178. package/src/app/(main)/settings/(mobile)/features/AvatarBanner.tsx +0 -68
  179. package/src/app/(main)/settings/(mobile)/features/ExtraList.tsx +0 -65
  180. package/src/app/(main)/settings/(mobile)/index.tsx +0 -53
  181. package/src/app/(main)/settings/about/AboutList.tsx +0 -53
  182. package/src/app/(main)/settings/about/Analytics.tsx +0 -40
  183. package/src/app/(main)/settings/about/style.ts +0 -22
  184. package/src/app/(main)/settings/agent/loading.tsx +0 -3
  185. package/src/app/(main)/settings/common/loading.tsx +0 -3
  186. package/src/app/(main)/settings/features/SettingList/index.tsx +0 -47
  187. package/src/app/(main)/settings/llm/layout.tsx +0 -11
  188. package/src/app/(main)/settings/llm/loading.tsx +0 -3
  189. package/src/app/(main)/settings/sync/DeviceInfo/DeviceName.tsx +0 -66
  190. package/src/app/(main)/settings/sync/PageTitle.tsx +0 -11
  191. package/src/app/(main)/settings/sync/layout.tsx +0 -12
  192. package/src/app/(main)/settings/sync/loading.tsx +0 -3
  193. package/src/app/(main)/settings/tts/loading.tsx +0 -3
  194. package/src/features/AgentSetting/AgentConfig/index.tsx +0 -202
  195. package/src/features/AgentSetting/AgentConfig/useSyncConfig.ts +0 -23
  196. package/src/store/user/slices/common/selectors.ts +0 -6
  197. /package/src/app/(main)/settings/{features/SettingList → about/features}/Item.tsx +0 -0
  198. /package/src/app/(main)/settings/{features → common/features/Theme}/ThemeSwatches/ThemeSwatchesNeutral.tsx +0 -0
  199. /package/src/app/(main)/settings/{features → common/features/Theme}/ThemeSwatches/ThemeSwatchesPrimary.tsx +0 -0
  200. /package/src/app/(main)/settings/{features → common/features/Theme}/ThemeSwatches/index.ts +0 -0
  201. /package/src/app/(main)/settings/sync/{Alert.tsx → features/Alert.tsx} +0 -0
  202. /package/src/app/(main)/settings/sync/{components → features/WebRTC}/SyncSwitch/index.css +0 -0
  203. /package/src/app/(main)/settings/sync/{components → features/WebRTC}/SyncSwitch/index.tsx +0 -0
  204. /package/src/app/(main)/settings/sync/{util.ts → features/WebRTC/generateRandomRoomName.ts} +0 -0
  205. /package/src/app/(main)/settings/tts/{TTS/options.ts → features/const.ts} +0 -0
  206. /package/src/features/AgentSetting/{AgentConfig → AgentModal}/ModelSelect.tsx +0 -0
@@ -27,9 +27,12 @@
27
27
  }
28
28
  },
29
29
  "header": {
30
+ "desc": "偏好與模型設定",
30
31
  "global": "全域設定",
31
32
  "session": "對話設定",
32
- "sessionWithName": "對話設定 · {{name}}"
33
+ "sessionDesc": "角色設定與會話偏好",
34
+ "sessionWithName": "對話設定 · {{name}}",
35
+ "title": "設定"
33
36
  },
34
37
  "llm": {
35
38
  "checker": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.152.6",
3
+ "version": "0.152.8",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+
3
+ import { createStyles } from 'antd-style';
4
+ import { PropsWithChildren, memo } from 'react';
5
+ import { Center, Flexbox } from 'react-layout-kit';
6
+
7
+ export const useStyles = createStyles(({ css, token }) => ({
8
+ avatar: css`
9
+ position: absolute;
10
+ z-index: 10;
11
+
12
+ flex: none;
13
+
14
+ background: ${token.colorBgContainer};
15
+ border: 6px solid ${token.colorBgContainer};
16
+ border-radius: 50%;
17
+ `,
18
+ banner: css`
19
+ position: relative;
20
+ flex: none;
21
+ `,
22
+ bannerBox: css`
23
+ position: relative;
24
+
25
+ overflow: hidden;
26
+
27
+ width: 100%;
28
+ height: 180px;
29
+
30
+ background: ${token.colorBgLayout};
31
+ `,
32
+ bannerImg: css`
33
+ position: absolute;
34
+ scale: 5;
35
+ filter: blur(24px) saturate(2);
36
+ `,
37
+ }));
38
+
39
+ const AvatarBanner = memo<PropsWithChildren>(({ children }) => {
40
+ const { styles } = useStyles();
41
+
42
+ return (
43
+ <Flexbox align={'center'} className={styles.banner} justify={'center'} width={'100%'}>
44
+ <Flexbox align={'center'} className={styles.bannerBox} justify={'center'}>
45
+ <div className={styles.bannerImg}>{children}</div>
46
+ </Flexbox>
47
+ <Center className={styles.avatar}>{children}</Center>
48
+ </Flexbox>
49
+ );
50
+ });
51
+
52
+ export default AvatarBanner;
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ import { useTheme } from 'antd-style';
4
+ import { useRouter } from 'next/navigation';
5
+ import { memo } from 'react';
6
+ import { Flexbox } from 'react-layout-kit';
7
+ import urlJoin from 'url-join';
8
+
9
+ import { useCategory } from '@/app/(main)/settings/hooks/useCategory';
10
+ import Cell from '@/components/Cell';
11
+ import Divider from '@/components/Cell/Divider';
12
+
13
+ const SettingCate = memo(() => {
14
+ const theme = useTheme();
15
+ const settingItems = useCategory({ mobile: true });
16
+ const router = useRouter();
17
+
18
+ return (
19
+ <Flexbox style={{ background: theme.colorBgContainer }} width={'100%'}>
20
+ {settingItems?.map(({ key, icon, label, type }: any, index) => {
21
+ if (type === 'divider') return <Divider key={index} />;
22
+ return (
23
+ <Cell
24
+ icon={icon}
25
+ key={key}
26
+ label={label}
27
+ onClick={() => router.push(urlJoin('/settings', key))}
28
+ />
29
+ );
30
+ })}
31
+ </Flexbox>
32
+ );
33
+ });
34
+
35
+ export default SettingCate;
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+
3
+ import { useTheme } from 'antd-style';
4
+ import { memo } from 'react';
5
+ import { Flexbox } from 'react-layout-kit';
6
+
7
+ import Cell from '@/components/Cell';
8
+ import Divider from '@/components/Cell/Divider';
9
+
10
+ import { useExtraCate } from './useExtraCate';
11
+
12
+ const ExtraCate = memo(() => {
13
+ const theme = useTheme();
14
+ const mainItems = useExtraCate();
15
+
16
+ return (
17
+ <Flexbox style={{ background: theme.colorBgContainer }} width={'100%'}>
18
+ {mainItems?.map(({ key, icon, label, type, onClick }: any, index) => {
19
+ if (type === 'divider') return <Divider key={index} />;
20
+ return <Cell icon={icon} key={key} label={label} onClick={onClick} />;
21
+ })}
22
+ </Flexbox>
23
+ );
24
+ });
25
+
26
+ export default ExtraCate;
@@ -0,0 +1,62 @@
1
+ import { DiscordIcon, Icon } from '@lobehub/ui';
2
+ import { Book, Feather, HardDriveDownload, HardDriveUpload } from 'lucide-react';
3
+ import { useTranslation } from 'react-i18next';
4
+
5
+ import { type MenuProps } from '@/components/Menu';
6
+ import { DISCORD, DOCUMENTS, FEEDBACK } from '@/const/url';
7
+ import DataImporter from '@/features/DataImporter';
8
+ import { configService } from '@/services/config';
9
+
10
+ export const useExtraCate = () => {
11
+ const { t } = useTranslation(['common', 'setting']);
12
+
13
+ const iconSize = { fontSize: 20 };
14
+
15
+ const exports: MenuProps['items'] = [
16
+ {
17
+ icon: <Icon icon={HardDriveUpload} size={iconSize} />,
18
+ key: 'import',
19
+ label: <DataImporter>{t('import')}</DataImporter>,
20
+ },
21
+ {
22
+ icon: <Icon icon={HardDriveDownload} size={iconSize} />,
23
+ key: 'export',
24
+ label: t('export'),
25
+ onClick: configService.exportAll,
26
+ },
27
+ {
28
+ type: 'divider',
29
+ },
30
+ ];
31
+
32
+ const helps: MenuProps['items'] = [
33
+ {
34
+ icon: <Icon icon={Book} size={iconSize} />,
35
+ key: 'docs',
36
+ label: t('document'),
37
+ onClick: () => window.open(DOCUMENTS, '__blank'),
38
+ },
39
+ {
40
+ icon: <Icon icon={Feather} size={iconSize} />,
41
+ key: 'feedback',
42
+ label: t('feedback'),
43
+ onClick: () => window.open(FEEDBACK, '__blank'),
44
+ },
45
+ {
46
+ icon: <Icon icon={DiscordIcon} size={iconSize} />,
47
+ key: 'discord',
48
+ label: 'Discord',
49
+ onClick: () => window.open(DISCORD, '__blank'),
50
+ },
51
+ ];
52
+
53
+ const mainItems = [
54
+ {
55
+ type: 'divider',
56
+ },
57
+ ...exports,
58
+ ...helps,
59
+ ].filter(Boolean) as MenuProps['items'];
60
+
61
+ return mainItems;
62
+ };
@@ -0,0 +1,11 @@
1
+ import { PropsWithChildren } from 'react';
2
+
3
+ import MobileContentLayout from '@/components/server/MobileNavLayout';
4
+
5
+ const Layout = ({ children }: PropsWithChildren) => {
6
+ return <MobileContentLayout withNav>{children}</MobileContentLayout>;
7
+ };
8
+
9
+ Layout.displayName = 'MeLayout';
10
+
11
+ export default Layout;
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+
3
+ import { Skeleton } from 'antd';
4
+ import { Center } from 'react-layout-kit';
5
+
6
+ import SkeletonLoading from '@/components/SkeletonLoading';
7
+
8
+ export default () => {
9
+ return (
10
+ <>
11
+ <Center height={180}>
12
+ <Skeleton.Avatar shape={'circle'} size={88} />
13
+ </Center>
14
+ <SkeletonLoading paragraph={{ rows: 8 }} title={false} />
15
+ </>
16
+ );
17
+ };
@@ -0,0 +1,31 @@
1
+ import { redirect } from 'next/navigation';
2
+ import { Center } from 'react-layout-kit';
3
+
4
+ import BrandWatermark from '@/components/BrandWatermark';
5
+ import Avatar from '@/features/AvatarWithUpload';
6
+ import { isMobileDevice } from '@/utils/responsive';
7
+
8
+ import AvatarBanner from './features/AvatarBanner';
9
+ import Cate from './features/Cate';
10
+ import ExtraCate from './features/ExtraCate';
11
+
12
+ const Page = () => {
13
+ const mobile = isMobileDevice();
14
+
15
+ if (!mobile) return redirect('/chat');
16
+
17
+ return (
18
+ <>
19
+ <AvatarBanner>
20
+ <Avatar size={88} />
21
+ </AvatarBanner>
22
+ <Cate />
23
+ <ExtraCate />
24
+ <Center padding={16}>
25
+ <BrandWatermark />
26
+ </Center>
27
+ </>
28
+ );
29
+ };
30
+
31
+ export default Page;
@@ -15,7 +15,7 @@ const Nav = memo(() => {
15
15
  <SideNav
16
16
  avatar={<Avatar />}
17
17
  bottomActions={<BottomActions tab={sidebarKey} />}
18
- style={{ height: '100%' }}
18
+ style={{ height: '100%', zIndex: 100 }}
19
19
  topActions={<TopActions tab={sidebarKey} />}
20
20
  />
21
21
  );
@@ -53,11 +53,11 @@ const Nav = memo(() => {
53
53
  },
54
54
  {
55
55
  icon: (active) => <Icon className={active ? styles.active : undefined} icon={User} />,
56
- key: SidebarTabKey.Setting,
56
+ key: SidebarTabKey.Me,
57
57
  onClick: () => {
58
- router.push('/settings');
58
+ router.push('/me');
59
59
  },
60
- title: t('tab.setting'),
60
+ title: t('tab.me'),
61
61
  },
62
62
  ],
63
63
  [t],
@@ -10,7 +10,7 @@ import SyncStatusInspector from '@/features/SyncStatusInspector';
10
10
  import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
11
11
  import { useSessionStore } from '@/store/session';
12
12
  import { useUserStore } from '@/store/user';
13
- import { commonSelectors } from '@/store/user/selectors';
13
+ import { userProfileSelectors } from '@/store/user/selectors';
14
14
  import { mobileHeaderSticky } from '@/styles/mobileHeader';
15
15
 
16
16
  export const useStyles = createStyles(({ css, token }) => ({
@@ -26,14 +26,14 @@ export const useStyles = createStyles(({ css, token }) => ({
26
26
  const Header = memo(() => {
27
27
  const [createSession] = useSessionStore((s) => [s.createSession]);
28
28
  const router = useRouter();
29
- const avatar = useUserStore(commonSelectors.userAvatar);
29
+ const avatar = useUserStore(userProfileSelectors.userAvatar);
30
30
  const { showCreateSession } = useServerConfigStore(featureFlagsSelectors);
31
31
 
32
32
  return (
33
33
  <MobileNavBar
34
34
  left={
35
35
  <Flexbox align={'center'} gap={8} horizontal style={{ marginLeft: 8 }}>
36
- <div onClick={() => router.push('/settings')}>
36
+ <div onClick={() => router.push('/me')}>
37
37
  {avatar ? <Avatar avatar={avatar} size={28} /> : <Logo size={28} />}
38
38
  </div>
39
39
  <Logo type={'text'} />
@@ -1,13 +1,9 @@
1
- 'use client';
2
-
3
- import { PropsWithChildren, memo } from 'react';
4
1
  import { Flexbox } from 'react-layout-kit';
5
2
 
6
- import ClientResponsiveLayout from '@/components/client/ClientResponsiveLayout';
7
-
3
+ import { LayoutProps } from '../type';
8
4
  import ResponsiveSessionList from './SessionList';
9
5
 
10
- const Desktop = memo(({ children }: PropsWithChildren) => {
6
+ const Layout = ({ children }: LayoutProps) => {
11
7
  return (
12
8
  <>
13
9
  <ResponsiveSessionList />
@@ -21,6 +17,8 @@ const Desktop = memo(({ children }: PropsWithChildren) => {
21
17
  </Flexbox>
22
18
  </>
23
19
  );
24
- });
20
+ };
21
+
22
+ Layout.displayName = 'DesktopChatLayout';
25
23
 
26
- export default ClientResponsiveLayout({ Desktop, Mobile: () => import('../Mobile') });
24
+ export default Layout;
@@ -1,7 +1,9 @@
1
- import { PropsWithChildren } from 'react';
1
+ import { LayoutProps } from '../type';
2
2
 
3
- const MobileLayout = ({ children }: PropsWithChildren) => {
3
+ const Layout = ({ children }: LayoutProps) => {
4
4
  return children;
5
5
  };
6
6
 
7
- export default MobileLayout;
7
+ Layout.displayName = 'MobileChatLayout';
8
+
9
+ export default Layout;
@@ -0,0 +1,5 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export interface LayoutProps {
4
+ children: ReactNode;
5
+ }
@@ -1,20 +1,19 @@
1
1
  import { ActionIcon } from '@lobehub/ui';
2
2
  import { AlignJustify } from 'lucide-react';
3
- import { useRouter } from 'next/navigation';
4
3
  import { memo } from 'react';
5
4
  import { useTranslation } from 'react-i18next';
6
5
 
7
6
  import { DESKTOP_HEADER_ICON_SIZE, MOBILE_HEADER_ICON_SIZE } from '@/const/layoutTokens';
7
+ import { useQueryRoute } from '@/hooks/useQueryRoute';
8
8
  import { useGlobalStore } from '@/store/global';
9
9
  import { SidebarTabKey } from '@/store/global/initialState';
10
10
  import { useSessionStore } from '@/store/session';
11
11
  import { sessionSelectors } from '@/store/session/selectors';
12
- import { pathString } from '@/utils/url';
13
12
 
14
13
  const SettingButton = memo<{ mobile?: boolean }>(({ mobile }) => {
15
14
  const isInbox = useSessionStore(sessionSelectors.isInboxSession);
16
15
  const { t } = useTranslation('common');
17
- const router = useRouter();
16
+ const router = useQueryRoute();
18
17
 
19
18
  return (
20
19
  <ActionIcon
@@ -26,7 +25,7 @@ const SettingButton = memo<{ mobile?: boolean }>(({ mobile }) => {
26
25
  });
27
26
  router.push('/settings/agent');
28
27
  } else {
29
- router.push(pathString('/chat/settings', { search: location.search }));
28
+ router.push('/chat/settings');
30
29
  }
31
30
  }}
32
31
  size={mobile ? MOBILE_HEADER_ICON_SIZE : DESKTOP_HEADER_ICON_SIZE}
@@ -7,7 +7,7 @@ import { Flexbox } from 'react-layout-kit';
7
7
  import { FORM_STYLE } from '@/const/layoutTokens';
8
8
  import { useChatStore } from '@/store/chat';
9
9
  import { useUserStore } from '@/store/user';
10
- import { commonSelectors } from '@/store/user/selectors';
10
+ import { userProfileSelectors } from '@/store/user/selectors';
11
11
 
12
12
  import Preview from './Preview';
13
13
  import { FieldType, ImageType } from './type';
@@ -49,7 +49,7 @@ const ShareModal = memo<ModalProps>(({ onCancel, open }) => {
49
49
  const [fieldValue, setFieldValue] = useState<FieldType>(DEFAULT_FIELD_VALUE);
50
50
  const [tab, setTab] = useState<Tab>(Tab.Screenshot);
51
51
  const { t } = useTranslation('chat');
52
- const avatar = useUserStore(commonSelectors.userAvatar);
52
+ const avatar = useUserStore(userProfileSelectors.userAvatar);
53
53
  const [shareLoading, shareToShareGPT] = useChatStore((s) => [s.shareLoading, s.shareToShareGPT]);
54
54
  const { loading, onDownload, title } = useScreenshot(fieldValue.imageType);
55
55
 
@@ -2,7 +2,10 @@ import ServerLayout from '@/components/server/ServerLayout';
2
2
 
3
3
  import Desktop from './_layout/Desktop';
4
4
  import Mobile from './_layout/Mobile';
5
+ import { LayoutProps } from './_layout/type';
5
6
 
6
- const ChatLayout = ServerLayout({ Desktop, Mobile });
7
+ const Layout = ServerLayout<LayoutProps>({ Desktop, Mobile });
7
8
 
8
- export default ChatLayout;
9
+ Layout.displayName = 'ChatLayout';
10
+
11
+ export default Layout;
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import { ChatHeader, ChatHeaderTitle } from '@lobehub/ui';
2
4
  import { useRouter } from 'next/navigation';
3
5
  import { memo } from 'react';
@@ -0,0 +1,28 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { Flexbox } from 'react-layout-kit';
3
+
4
+ import SafeSpacing from '@/components/SafeSpacing';
5
+ import { HEADER_HEIGHT } from '@/const/layoutTokens';
6
+
7
+ import Header from './Header';
8
+
9
+ const Layout = ({ children }: PropsWithChildren) => (
10
+ <>
11
+ <Header />
12
+ <Flexbox
13
+ align={'center'}
14
+ height={'100%'}
15
+ style={{ overflowX: 'hidden', overflowY: 'auto' }}
16
+ width={'100%'}
17
+ >
18
+ <SafeSpacing height={HEADER_HEIGHT - 16} />
19
+ <Flexbox gap={64} style={{ maxWidth: 1024, padding: '32px 24px' }} width={'100%'}>
20
+ {children}
21
+ </Flexbox>
22
+ </Flexbox>
23
+ </>
24
+ );
25
+
26
+ Layout.displayName = 'DesktopSessionSettingsLayout';
27
+
28
+ export default Layout;
@@ -1,13 +1,14 @@
1
+ 'use client';
2
+
1
3
  import { MobileNavBar, MobileNavBarTitle } from '@lobehub/ui';
2
4
  import { useRouter } from 'next/navigation';
3
5
  import { memo } from 'react';
4
6
  import { useTranslation } from 'react-i18next';
5
7
 
8
+ import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
6
9
  import { mobileHeaderSticky } from '@/styles/mobileHeader';
7
10
  import { pathString } from '@/utils/url';
8
11
 
9
- import HeaderContent from '../features/HeaderContent';
10
-
11
12
  const Header = memo(() => {
12
13
  const { t } = useTranslation('setting');
13
14
  const router = useRouter();
@@ -0,0 +1,15 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren } from 'react';
4
+
5
+ import MobileContentLayout from '@/components/server/MobileNavLayout';
6
+
7
+ import Header from './Header';
8
+
9
+ const Layout = ({ children }: PropsWithChildren) => (
10
+ <MobileContentLayout header={<Header />}>{children}</MobileContentLayout>
11
+ );
12
+
13
+ Layout.displayName = 'MobileSessionSettingsLayout';
14
+
15
+ export default Layout;
@@ -0,0 +1,5 @@
1
+ 'use client';
2
+
3
+ import dynamic from 'next/dynamic';
4
+
5
+ export default dynamic(() => import('@/components/Error'));
@@ -1,5 +1,5 @@
1
- import { ActionIcon } from '@lobehub/ui';
2
- import { Dropdown, MenuProps } from 'antd';
1
+ import { ActionIcon, Icon } from '@lobehub/ui';
2
+ import { Button, Dropdown, MenuProps } from 'antd';
3
3
  import { useResponsive } from 'antd-style';
4
4
  import { HardDriveDownload } from 'lucide-react';
5
5
  import { memo, useMemo } from 'react';
@@ -11,7 +11,7 @@ import { useSessionStore } from '@/store/session';
11
11
 
12
12
  import SubmitAgentButton from './SubmitAgentButton';
13
13
 
14
- export const HeaderContent = memo<{ mobile?: boolean }>(() => {
14
+ export const HeaderContent = memo<{ mobile?: boolean; modal?: boolean }>(({ modal }) => {
15
15
  const { t } = useTranslation('setting');
16
16
  const id = useSessionStore((s) => s.activeId);
17
17
 
@@ -43,13 +43,19 @@ export const HeaderContent = memo<{ mobile?: boolean }>(() => {
43
43
 
44
44
  return (
45
45
  <>
46
- <SubmitAgentButton />
46
+ <SubmitAgentButton modal={modal} />
47
47
  <Dropdown arrow={false} menu={{ items }} trigger={['click']}>
48
- <ActionIcon
49
- icon={HardDriveDownload}
50
- size={HEADER_ICON_SIZE(mobile)}
51
- title={t('export', { ns: 'common' })}
52
- />
48
+ {modal ? (
49
+ <Button block icon={<Icon icon={HardDriveDownload} />}>
50
+ {t('export', { ns: 'common' })}
51
+ </Button>
52
+ ) : (
53
+ <ActionIcon
54
+ icon={HardDriveDownload}
55
+ size={HEADER_ICON_SIZE(mobile)}
56
+ title={t('export', { ns: 'common' })}
57
+ />
58
+ )}
53
59
  </Dropdown>
54
60
  </>
55
61
  );
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import { Alert, Modal, type ModalProps } from '@lobehub/ui';
2
4
  import { Button, Divider, Input } from 'antd';
3
5
  import { useTheme } from 'antd-style';
@@ -1,4 +1,5 @@
1
- import { ActionIcon } from '@lobehub/ui';
1
+ import { ActionIcon, Icon } from '@lobehub/ui';
2
+ import { Button } from 'antd';
2
3
  import { useResponsive } from 'antd-style';
3
4
  import { Share2 } from 'lucide-react';
4
5
  import { memo, useState } from 'react';
@@ -8,18 +9,25 @@ import { HEADER_ICON_SIZE } from '@/const/layoutTokens';
8
9
 
9
10
  import SubmitAgentModal from './SubmitAgentModal';
10
11
 
11
- const SubmitAgentButton = memo(() => {
12
+ const SubmitAgentButton = memo<{ modal?: boolean }>(({ modal }) => {
12
13
  const { t } = useTranslation('setting');
13
14
  const { mobile } = useResponsive();
14
15
  const [isModalOpen, setIsModalOpen] = useState(false);
16
+
15
17
  return (
16
18
  <>
17
- <ActionIcon
18
- icon={Share2}
19
- onClick={() => setIsModalOpen(true)}
20
- size={HEADER_ICON_SIZE(mobile)}
21
- title={t('submitAgentModal.tooltips')}
22
- />
19
+ {modal ? (
20
+ <Button block icon={<Icon icon={Share2} />} onClick={() => setIsModalOpen(true)}>
21
+ {t('submitAgentModal.tooltips')}
22
+ </Button>
23
+ ) : (
24
+ <ActionIcon
25
+ icon={Share2}
26
+ onClick={() => setIsModalOpen(true)}
27
+ size={HEADER_ICON_SIZE(mobile)}
28
+ title={t('submitAgentModal.tooltips')}
29
+ />
30
+ )}
23
31
  <SubmitAgentModal onCancel={() => setIsModalOpen(false)} open={isModalOpen} />
24
32
  </>
25
33
  );
@@ -1,14 +1,21 @@
1
1
  import { notFound } from 'next/navigation';
2
2
  import { PropsWithChildren } from 'react';
3
3
 
4
+ import ServerLayout from '@/components/server/ServerLayout';
4
5
  import { serverFeatureFlags } from '@/config/server/featureFlags';
5
6
 
7
+ import Desktop from './_layout/Desktop';
8
+ import Mobile from './_layout/Mobile';
9
+
10
+ const SessionSettingsLayout = ServerLayout({ Desktop, Mobile });
11
+
6
12
  const Layout = ({ children }: PropsWithChildren) => {
7
13
  const isAgentEditable = serverFeatureFlags().isAgentEditable;
8
-
9
14
  if (!isAgentEditable) return notFound();
10
15
 
11
- return children;
16
+ return <SessionSettingsLayout>{children}</SessionSettingsLayout>;
12
17
  };
13
18
 
19
+ Layout.displayName = 'SessionSettingsLayout';
20
+
14
21
  export default Layout;
@@ -0,0 +1,3 @@
1
+ import SkeletonLoading from '@/components/SkeletonLoading';
2
+
3
+ export default () => <SkeletonLoading paragraph={{ rows: 8 }} />;
@@ -0,0 +1,3 @@
1
+ import dynamic from 'next/dynamic';
2
+
3
+ export default dynamic(() => import('@/components/404'));
@@ -1,14 +1,7 @@
1
- import { isMobileDevice } from '@/utils/responsive';
2
-
3
- import DesktopPage from './(desktop)';
4
- import MobilePage from './(mobile)';
1
+ import EditPage from './features/EditPage';
5
2
 
6
3
  const Page = () => {
7
- const mobile = isMobileDevice();
8
-
9
- const Page = mobile ? MobilePage : DesktopPage;
10
-
11
- return <Page />;
4
+ return <EditPage />;
12
5
  };
13
6
 
14
7
  export default Page;