@lobehub/chat 0.152.1 → 0.152.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 (214) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +8 -8
  3. package/README.zh-CN.md +8 -8
  4. package/locales/ar/common.json +14 -0
  5. package/locales/ar/setting.json +4 -1
  6. package/locales/bg-BG/common.json +14 -0
  7. package/locales/bg-BG/setting.json +4 -1
  8. package/locales/de-DE/common.json +14 -0
  9. package/locales/de-DE/setting.json +4 -1
  10. package/locales/en-US/common.json +14 -0
  11. package/locales/en-US/setting.json +4 -1
  12. package/locales/es-ES/common.json +14 -0
  13. package/locales/es-ES/setting.json +4 -1
  14. package/locales/fr-FR/common.json +14 -0
  15. package/locales/fr-FR/setting.json +4 -1
  16. package/locales/it-IT/common.json +14 -0
  17. package/locales/it-IT/setting.json +4 -1
  18. package/locales/ja-JP/common.json +14 -0
  19. package/locales/ja-JP/setting.json +4 -1
  20. package/locales/ko-KR/common.json +14 -0
  21. package/locales/ko-KR/setting.json +4 -1
  22. package/locales/nl-NL/common.json +14 -0
  23. package/locales/nl-NL/setting.json +4 -1
  24. package/locales/pl-PL/common.json +14 -0
  25. package/locales/pl-PL/setting.json +4 -1
  26. package/locales/pt-BR/common.json +14 -0
  27. package/locales/pt-BR/setting.json +4 -1
  28. package/locales/ru-RU/common.json +14 -0
  29. package/locales/ru-RU/setting.json +4 -1
  30. package/locales/tr-TR/common.json +14 -0
  31. package/locales/tr-TR/setting.json +4 -1
  32. package/locales/vi-VN/common.json +14 -0
  33. package/locales/vi-VN/setting.json +4 -1
  34. package/locales/zh-CN/common.json +14 -0
  35. package/locales/zh-CN/setting.json +4 -1
  36. package/locales/zh-TW/common.json +14 -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 +34 -0
  41. package/src/app/(main)/(mobile)/me/features/ExtraCate.tsx +26 -0
  42. package/src/app/(main)/(mobile)/me/features/useExtraCate.tsx +68 -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/BottomActions.tsx +7 -120
  47. package/src/app/(main)/@nav/_layout/Desktop/index.tsx +7 -2
  48. package/src/app/(main)/@nav/_layout/Mobile.tsx +3 -3
  49. package/src/app/(main)/@nav/features/UserAvatar.tsx +24 -0
  50. package/src/app/(main)/@nav/features/UserPanel/LangButton.tsx +55 -0
  51. package/src/app/(main)/@nav/features/UserPanel/Popover.tsx +34 -0
  52. package/src/app/(main)/@nav/features/UserPanel/ThemeButton.tsx +70 -0
  53. package/src/app/(main)/@nav/features/UserPanel/UserInfo.tsx +35 -0
  54. package/src/app/(main)/@nav/features/UserPanel/index.tsx +69 -0
  55. package/src/app/(main)/@nav/features/UserPanel/useMenu.tsx +144 -0
  56. package/src/app/(main)/@nav/features/UserPanel/useNewVersion.tsx +12 -0
  57. package/src/app/(main)/chat/(mobile)/features/SessionHeader.tsx +1 -1
  58. package/src/app/(main)/chat/_layout/Desktop/index.tsx +6 -8
  59. package/src/app/(main)/chat/_layout/Mobile/index.tsx +5 -3
  60. package/src/app/(main)/chat/_layout/type.ts +5 -0
  61. package/src/app/(main)/chat/features/SettingButton.tsx +5 -2
  62. package/src/app/(main)/chat/layout.ts +5 -2
  63. package/src/app/(main)/chat/settings/{(desktop) → _layout/Desktop}/Header.tsx +2 -0
  64. package/src/app/(main)/chat/settings/_layout/Desktop/index.tsx +32 -0
  65. package/src/app/(main)/chat/settings/{(mobile) → _layout/Mobile}/Header.tsx +3 -2
  66. package/src/app/(main)/chat/settings/_layout/Mobile/index.tsx +15 -0
  67. package/src/app/(main)/chat/settings/error.tsx +5 -0
  68. package/src/app/(main)/chat/settings/features/HeaderContent.tsx +15 -9
  69. package/src/app/(main)/chat/settings/features/SubmitAgentButton/SubmitAgentModal.tsx +2 -0
  70. package/src/app/(main)/chat/settings/features/SubmitAgentButton/index.tsx +16 -8
  71. package/src/app/(main)/chat/settings/layout.tsx +9 -2
  72. package/src/app/(main)/chat/settings/loading.tsx +3 -0
  73. package/src/app/(main)/chat/settings/not-found.tsx +3 -0
  74. package/src/app/(main)/chat/settings/page.tsx +2 -9
  75. package/src/app/(main)/market/@detail/default.tsx +1 -10
  76. package/src/app/(main)/market/@detail/loading.tsx +1 -0
  77. package/src/app/(main)/market/{@detail/_layout/Desktop.tsx → _layout/Desktop/DetailSidebar.tsx} +2 -2
  78. package/src/app/(main)/market/_layout/Desktop/index.tsx +2 -1
  79. package/src/app/(main)/market/{@detail/_layout/Mobile.tsx → _layout/Mobile/DetailModal.tsx} +2 -2
  80. package/src/app/(main)/market/_layout/Mobile/index.tsx +3 -1
  81. package/src/app/(main)/settings/@category/default.tsx +16 -0
  82. package/src/app/(main)/settings/@category/features/CategoryContent.tsx +35 -0
  83. package/src/app/(main)/settings/@category/features/UpgradeAlert.tsx +38 -0
  84. package/src/app/(main)/settings/_layout/Desktop/Header.tsx +78 -23
  85. package/src/app/(main)/settings/_layout/Desktop/SideBar.tsx +39 -27
  86. package/src/app/(main)/settings/_layout/Desktop/index.tsx +41 -17
  87. package/src/app/(main)/settings/_layout/Mobile/{SubSettingHeader.tsx → Header.tsx} +3 -1
  88. package/src/app/(main)/settings/_layout/Mobile/index.tsx +7 -18
  89. package/src/app/(main)/settings/_layout/type.ts +6 -0
  90. package/src/app/(main)/settings/about/features/AboutList.tsx +122 -0
  91. package/src/app/(main)/settings/about/features/Analytics.tsx +42 -0
  92. package/src/app/(main)/settings/about/layout.tsx +26 -0
  93. package/src/app/(main)/settings/about/loading.tsx +5 -0
  94. package/src/app/(main)/settings/about/page.tsx +20 -25
  95. package/src/app/(main)/settings/agent/layout.tsx +35 -0
  96. package/src/app/(main)/settings/agent/loading.tsx +4 -2
  97. package/src/app/(main)/settings/agent/page.tsx +25 -12
  98. package/src/app/(main)/settings/common/{Common.tsx → features/Common.tsx} +7 -5
  99. package/src/app/(main)/settings/common/{Theme.tsx → features/Theme/index.tsx} +8 -6
  100. package/src/app/(main)/settings/common/page.tsx +21 -4
  101. package/src/app/(main)/settings/error.tsx +5 -0
  102. package/src/app/(main)/settings/features/Footer.tsx +2 -0
  103. package/src/app/(main)/settings/features/UpgradeAlert.tsx +21 -13
  104. package/src/app/(main)/settings/hooks/useCategory.tsx +54 -0
  105. package/src/app/(main)/settings/hooks/useSyncSettings.ts +2 -2
  106. package/src/app/(main)/settings/layout.ts +4 -1
  107. package/src/app/(main)/settings/llm/Anthropic/index.tsx +4 -10
  108. package/src/app/(main)/settings/llm/Azure/index.tsx +3 -1
  109. package/src/app/(main)/settings/llm/Bedrock/index.tsx +3 -1
  110. package/src/app/(main)/settings/llm/Google/index.tsx +4 -2
  111. package/src/app/(main)/settings/llm/Groq/index.tsx +3 -1
  112. package/src/app/(main)/settings/llm/Minimax/index.tsx +3 -9
  113. package/src/app/(main)/settings/llm/Mistral/index.tsx +3 -9
  114. package/src/app/(main)/settings/llm/Moonshot/index.tsx +3 -1
  115. package/src/app/(main)/settings/llm/Ollama/index.tsx +3 -1
  116. package/src/app/(main)/settings/llm/OpenAI/index.tsx +2 -0
  117. package/src/app/(main)/settings/llm/OpenRouter/index.tsx +3 -9
  118. package/src/app/(main)/settings/llm/Perplexity/index.tsx +3 -9
  119. package/src/app/(main)/settings/llm/TogetherAI/index.tsx +3 -9
  120. package/src/app/(main)/settings/llm/ZeroOne/index.tsx +3 -9
  121. package/src/app/(main)/settings/llm/Zhipu/index.tsx +3 -10
  122. package/src/app/(main)/settings/llm/components/Checker.tsx +2 -0
  123. package/src/app/(main)/settings/llm/components/Footer.tsx +26 -0
  124. package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +16 -1
  125. package/src/app/(main)/settings/llm/page.tsx +57 -3
  126. package/src/app/(main)/settings/loading.tsx +9 -0
  127. package/src/app/(main)/settings/not-found.tsx +3 -0
  128. package/src/app/(main)/settings/page.tsx +2 -14
  129. package/src/app/(main)/settings/sync/{DeviceInfo → features/DeviceInfo}/Card.tsx +6 -5
  130. package/src/app/(main)/settings/sync/features/DeviceInfo/DeviceName.tsx +63 -0
  131. package/src/app/(main)/settings/sync/{components → features/DeviceInfo}/SystemIcon.tsx +6 -14
  132. package/src/app/(main)/settings/sync/{DeviceInfo → features/DeviceInfo}/index.tsx +22 -36
  133. package/src/app/(main)/settings/sync/{WebRTC → features/WebRTC}/ChannelNameInput.tsx +3 -3
  134. package/src/app/(main)/settings/sync/{WebRTC → features/WebRTC}/index.tsx +10 -9
  135. package/src/app/(main)/settings/sync/page.tsx +19 -11
  136. package/src/app/(main)/settings/tts/features/OpenAI.tsx +54 -0
  137. package/src/app/(main)/settings/tts/{TTS/index.tsx → features/STT.tsx} +11 -27
  138. package/src/app/(main)/settings/tts/page.tsx +17 -11
  139. package/src/app/@modal/(.)settings/about/layout.tsx +1 -0
  140. package/src/app/@modal/(.)settings/about/page.tsx +1 -0
  141. package/src/app/@modal/(.)settings/agent/layout.tsx +1 -0
  142. package/src/app/@modal/(.)settings/agent/page.tsx +1 -0
  143. package/src/app/@modal/(.)settings/common/page.tsx +1 -0
  144. package/src/app/@modal/(.)settings/layout.tsx +28 -0
  145. package/src/app/@modal/(.)settings/llm/page.tsx +1 -0
  146. package/src/app/@modal/(.)settings/loading.tsx +5 -0
  147. package/src/app/@modal/(.)settings/sync/page.tsx +1 -0
  148. package/src/app/@modal/(.)settings/tts/page.tsx +1 -0
  149. package/src/app/@modal/_layout/SettingModalLayout.tsx +59 -0
  150. package/src/app/@modal/chat/(.)settings/features/CategoryContent.tsx +36 -0
  151. package/src/app/@modal/chat/(.)settings/features/useCategory.tsx +62 -0
  152. package/src/app/@modal/chat/(.)settings/layout.tsx +55 -0
  153. package/src/app/@modal/chat/(.)settings/loading.tsx +5 -0
  154. package/src/app/@modal/chat/(.)settings/page.tsx +40 -0
  155. package/src/app/@modal/default.tsx +1 -0
  156. package/src/app/@modal/layout.tsx +30 -0
  157. package/src/app/@modal/loading.tsx +5 -0
  158. package/src/app/layout.tsx +11 -3
  159. package/src/components/BrandWatermark/index.tsx +39 -0
  160. package/src/components/Cell/Divider.tsx +19 -0
  161. package/src/components/Cell/index.tsx +38 -0
  162. package/src/components/Menu/index.tsx +97 -0
  163. package/src/components/SkeletonLoading/index.tsx +21 -0
  164. package/src/const/url.ts +1 -0
  165. package/src/features/AgentSetting/AgentChat/index.tsx +135 -0
  166. package/src/features/AgentSetting/AgentMeta/index.tsx +4 -3
  167. package/src/features/AgentSetting/AgentModal/index.tsx +95 -0
  168. package/src/features/AgentSetting/AgentPlugin/index.tsx +65 -66
  169. package/src/features/AgentSetting/AgentPrompt/index.tsx +101 -47
  170. package/src/features/AgentSetting/AgentTTS/index.tsx +4 -0
  171. package/src/features/AgentSetting/StoreUpdater.tsx +2 -0
  172. package/src/features/AgentSetting/index.tsx +6 -6
  173. package/src/features/AgentSetting/store/index.ts +2 -0
  174. package/src/features/AvatarWithUpload/index.tsx +2 -0
  175. package/src/hooks/useQuery.ts +7 -0
  176. package/src/hooks/useQueryRoute.ts +16 -0
  177. package/src/locales/default/common.ts +14 -0
  178. package/src/locales/default/setting.ts +3 -0
  179. package/src/server/redirectHard.ts +9 -0
  180. package/src/store/global/initialState.ts +1 -0
  181. package/src/app/(main)/@nav/_layout/Desktop/Avatar.tsx +0 -11
  182. package/src/app/(main)/chat/settings/(desktop)/index.tsx +0 -23
  183. package/src/app/(main)/chat/settings/(mobile)/index.tsx +0 -16
  184. package/src/app/(main)/settings/(desktop)/index.tsx +0 -23
  185. package/src/app/(main)/settings/(mobile)/features/AvatarBanner.tsx +0 -68
  186. package/src/app/(main)/settings/(mobile)/features/ExtraList.tsx +0 -65
  187. package/src/app/(main)/settings/(mobile)/index.tsx +0 -53
  188. package/src/app/(main)/settings/about/AboutList.tsx +0 -53
  189. package/src/app/(main)/settings/about/Analytics.tsx +0 -40
  190. package/src/app/(main)/settings/about/style.ts +0 -22
  191. package/src/app/(main)/settings/agent/Agent.tsx +0 -29
  192. package/src/app/(main)/settings/common/index.tsx +0 -24
  193. package/src/app/(main)/settings/common/loading.tsx +0 -3
  194. package/src/app/(main)/settings/features/SettingList/index.tsx +0 -47
  195. package/src/app/(main)/settings/llm/index.tsx +0 -59
  196. package/src/app/(main)/settings/llm/layout.tsx +0 -11
  197. package/src/app/(main)/settings/llm/loading.tsx +0 -3
  198. package/src/app/(main)/settings/sync/DeviceInfo/DeviceName.tsx +0 -66
  199. package/src/app/(main)/settings/sync/PageTitle.tsx +0 -11
  200. package/src/app/(main)/settings/sync/layout.tsx +0 -12
  201. package/src/app/(main)/settings/sync/loading.tsx +0 -3
  202. package/src/app/(main)/settings/tts/loading.tsx +0 -3
  203. package/src/features/AgentSetting/AgentConfig/index.tsx +0 -202
  204. package/src/features/AgentSetting/AgentConfig/useSyncConfig.ts +0 -23
  205. /package/src/app/(main)/settings/{features/SettingList → about/features}/Item.tsx +0 -0
  206. /package/src/app/(main)/settings/{features → common/features/Theme}/ThemeSwatches/ThemeSwatchesNeutral.tsx +0 -0
  207. /package/src/app/(main)/settings/{features → common/features/Theme}/ThemeSwatches/ThemeSwatchesPrimary.tsx +0 -0
  208. /package/src/app/(main)/settings/{features → common/features/Theme}/ThemeSwatches/index.ts +0 -0
  209. /package/src/app/(main)/settings/sync/{Alert.tsx → features/Alert.tsx} +0 -0
  210. /package/src/app/(main)/settings/sync/{components → features/WebRTC}/SyncSwitch/index.css +0 -0
  211. /package/src/app/(main)/settings/sync/{components → features/WebRTC}/SyncSwitch/index.tsx +0 -0
  212. /package/src/app/(main)/settings/sync/{util.ts → features/WebRTC/generateRandomRoomName.ts} +0 -0
  213. /package/src/app/(main)/settings/tts/{TTS/options.ts → features/const.ts} +0 -0
  214. /package/src/features/AgentSetting/{AgentConfig → AgentModal}/ModelSelect.tsx +0 -0
@@ -10,47 +10,22 @@ import { Flexbox } from 'react-layout-kit';
10
10
  import { BrowserIcon } from '@/components/BrowserIcon';
11
11
  import { MAX_WIDTH } from '@/const/layoutTokens';
12
12
 
13
- import SystemIcon from '../components/SystemIcon';
14
13
  import Card from './Card';
15
14
  import DeviceName from './DeviceName';
15
+ import SystemIcon from './SystemIcon';
16
16
 
17
17
  const useStyles = createStyles(({ css, cx, responsive, isDarkMode, token, stylish }) => ({
18
- cards: css`
19
- flex-direction: row;
20
- ${responsive.mobile} {
21
- flex-direction: column;
22
- width: 100%;
23
- }
24
- `,
25
18
  container: css`
26
19
  position: relative;
27
20
  width: 100%;
28
21
  border-radius: ${token.borderRadiusLG}px;
29
22
  `,
30
- content: cx(
31
- stylish.blurStrong,
32
- css`
33
- z-index: 2;
34
-
35
- flex-direction: row;
36
- justify-content: space-between;
37
-
38
- height: 88px;
39
- padding: 12px;
40
-
41
- background: ${rgba(token.colorBgContainer, isDarkMode ? 0.7 : 1)};
42
- border-radius: ${token.borderRadiusLG - 1}px;
43
-
44
- ${responsive.mobile} {
45
- flex-direction: column;
46
- gap: 16px;
47
- align-items: flex-start;
48
-
49
- width: 100%;
50
- padding: 8px;
51
- }
52
- `,
53
- ),
23
+ content: css`
24
+ z-index: 2;
25
+ padding: 8px;
26
+ background: ${rgba(token.colorBgContainer, isDarkMode ? 0.7 : 1)};
27
+ border-radius: ${token.borderRadiusLG - 1}px;
28
+ `,
54
29
  glow: cx(
55
30
  stylish.gradientAnimation,
56
31
  css`
@@ -90,15 +65,26 @@ const DeviceCard = memo<DeviceCardProps>(({ browser, os }) => {
90
65
  <Flexbox className={styles.container} padding={4}>
91
66
  <Flexbox horizontal paddingBlock={8} paddingInline={12}>
92
67
  <div>
93
- <Typography style={{ fontWeight: 'bold' }}>{t('sync.device.title')}</Typography>
68
+ <Typography style={{ fontSize: 18, fontWeight: 'bold' }}>
69
+ {t('sync.device.title')}
70
+ </Typography>
94
71
  </div>
95
72
  </Flexbox>
96
- <Flexbox align={'center'} className={styles.content} flex={1} padding={12}>
73
+ <Flexbox
74
+ align={'center'}
75
+ className={styles.content}
76
+ flex={1}
77
+ gap={16}
78
+ horizontal
79
+ justify={'space-between'}
80
+ padding={12}
81
+ wrap={'wrap'}
82
+ >
97
83
  <DeviceName />
98
- <Flexbox className={styles.cards} gap={12}>
84
+ <Flexbox flex={1} gap={12} horizontal>
99
85
  <Card icon={<SystemIcon title={os} />} title={os || t('sync.device.unknownOS')} />
100
86
  <Card
101
- icon={browser && <BrowserIcon browser={browser} size={32} />}
87
+ icon={browser && <BrowserIcon browser={browser} size={24} />}
102
88
  title={browser || t('sync.device.unknownBrowser')}
103
89
  />
104
90
  </Flexbox>
@@ -5,13 +5,13 @@ import { LucideDices } from 'lucide-react';
5
5
  import { memo, useState } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
- import { generateRandomRoomName } from '../util';
8
+ import { generateRandomRoomName } from './generateRandomRoomName';
9
9
 
10
10
  interface ChannelNameInputProps extends Omit<InputProps, 'form'> {
11
11
  form: FormInstance;
12
12
  }
13
13
 
14
- const ChannelNameInput = memo<ChannelNameInputProps>(({ form, ...res }) => {
14
+ const ChannelNameInput = memo<ChannelNameInputProps>(({ form, ...rest }) => {
15
15
  const { t } = useTranslation('setting');
16
16
  const [loading, setLoading] = useState(false);
17
17
 
@@ -38,7 +38,7 @@ const ChannelNameInput = memo<ChannelNameInputProps>(({ form, ...res }) => {
38
38
  title={t('sync.webrtc.channelName.shuffle')}
39
39
  />
40
40
  }
41
- {...res}
41
+ {...rest}
42
42
  />
43
43
  );
44
44
  });
@@ -7,18 +7,18 @@ import { memo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { Flexbox } from 'react-layout-kit';
9
9
 
10
+ import { useSyncSettings } from '@/app/(main)/settings/hooks/useSyncSettings';
10
11
  import { FORM_STYLE } from '@/const/layoutTokens';
11
12
  import SyncStatusInspector from '@/features/SyncStatusInspector';
12
13
  import { useUserStore } from '@/store/user';
13
14
 
14
- import { useSyncSettings } from '../../hooks/useSyncSettings';
15
15
  import ChannelNameInput from './ChannelNameInput';
16
16
 
17
17
  type SettingItemGroup = ItemGroup;
18
18
 
19
19
  const WebRTC = memo(() => {
20
20
  const { t } = useTranslation('setting');
21
- const [form] = AntForm.useForm();
21
+ const [form] = Form.useForm();
22
22
 
23
23
  const [setSettings] = useUserStore((s) => [s.setSettings]);
24
24
 
@@ -70,15 +70,14 @@ const WebRTC = memo(() => {
70
70
  </div>
71
71
  ),
72
72
  title: (
73
- <Flexbox gap={8} horizontal>
74
- {/* @ts-ignore */}
75
- <SiWebrtc />
76
- <Flexbox align={'baseline'} gap={8} horizontal>
73
+ <Flexbox align={'center'} gap={12} horizontal wrap={'wrap'}>
74
+ <Flexbox align={'center'} gap={8} horizontal>
75
+ <SiWebrtc style={{ flex: 'none' }} />
77
76
  {t('sync.webrtc.title')}
78
- <Typography.Text style={{ fontWeight: 'normal' }} type={'secondary'}>
79
- {t('sync.webrtc.desc')}
80
- </Typography.Text>
81
77
  </Flexbox>
78
+ <Typography.Text style={{ fontWeight: 'normal' }} type={'secondary'}>
79
+ {t('sync.webrtc.desc')}
80
+ </Typography.Text>
82
81
  </Flexbox>
83
82
  ),
84
83
  };
@@ -87,8 +86,10 @@ const WebRTC = memo(() => {
87
86
  <Form
88
87
  form={form}
89
88
  items={[config]}
89
+ itemsType={'group'}
90
90
  onFinish={setSettings}
91
91
  onValuesChange={setSettings}
92
+ variant={'pure'}
92
93
  {...FORM_STYLE}
93
94
  />
94
95
  );
@@ -1,28 +1,36 @@
1
1
  import { notFound } from 'next/navigation';
2
2
 
3
3
  import { serverFeatureFlags } from '@/config/server/featureFlags';
4
+ import { translation } from '@/server/translation';
4
5
  import { gerServerDeviceInfo, isMobileDevice } from '@/utils/responsive';
5
6
 
6
- import Alert from './Alert';
7
- import DeviceCard from './DeviceInfo';
8
- import PageTitle from './PageTitle';
9
- import WebRTC from './WebRTC';
7
+ import Alert from './features/Alert';
8
+ import DeviceInfo from './features/DeviceInfo';
9
+ import WebRTC from './features/WebRTC';
10
10
 
11
- export default () => {
12
- const enableWebrtc = serverFeatureFlags().enableWebrtc;
11
+ export const generateMetadata = async () => {
12
+ const { t } = await translation('setting');
13
+ return {
14
+ title: t('tab.sync'),
15
+ };
16
+ };
13
17
 
18
+ const Page = () => {
19
+ const enableWebrtc = serverFeatureFlags().enableWebrtc;
14
20
  if (!enableWebrtc) return notFound();
15
21
 
16
- const { os, browser } = gerServerDeviceInfo();
17
22
  const isMobile = isMobileDevice();
23
+ const { os, browser } = gerServerDeviceInfo();
18
24
 
19
25
  return (
20
26
  <>
21
- {isMobile && <Alert mobile />}
22
- <PageTitle />
23
- <DeviceCard browser={browser} os={os} />
27
+ <DeviceInfo browser={browser} os={os} />
24
28
  <WebRTC />
25
- {!isMobile && <Alert />}
29
+ <Alert mobile={isMobile} />
26
30
  </>
27
31
  );
28
32
  };
33
+
34
+ Page.displayName = 'SyncSetting';
35
+
36
+ export default Page;
@@ -0,0 +1,54 @@
1
+ 'use client';
2
+
3
+ import { Form, type ItemGroup } from '@lobehub/ui';
4
+ import { Select } from 'antd';
5
+ import isEqual from 'fast-deep-equal';
6
+ import { memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+
9
+ import { FORM_STYLE } from '@/const/layoutTokens';
10
+ import { useUserStore } from '@/store/user';
11
+ import { settingsSelectors } from '@/store/user/selectors';
12
+
13
+ import { opeanaiSTTOptions, opeanaiTTSOptions } from './const';
14
+
15
+ type SettingItemGroup = ItemGroup;
16
+
17
+ const TTS_SETTING_KEY = 'tts';
18
+
19
+ const OpenAI = memo(() => {
20
+ const { t } = useTranslation('setting');
21
+ const [form] = Form.useForm();
22
+ const settings = useUserStore(settingsSelectors.currentSettings, isEqual);
23
+ const [setSettings] = useUserStore((s) => [s.setSettings]);
24
+
25
+ const openai: SettingItemGroup = {
26
+ children: [
27
+ {
28
+ children: <Select options={opeanaiTTSOptions} />,
29
+ label: t('settingTTS.openai.ttsModel'),
30
+ name: [TTS_SETTING_KEY, 'openAI', 'ttsModel'],
31
+ },
32
+ {
33
+ children: <Select options={opeanaiSTTOptions} />,
34
+ label: t('settingTTS.openai.sttModel'),
35
+ name: [TTS_SETTING_KEY, 'openAI', 'sttModel'],
36
+ },
37
+ ],
38
+ title: t('settingTTS.openai.title'),
39
+ };
40
+
41
+ return (
42
+ <Form
43
+ form={form}
44
+ initialValues={settings}
45
+ items={[openai]}
46
+ itemsType={'group'}
47
+ onValuesChange={setSettings}
48
+ variant={'pure'}
49
+ {...FORM_STYLE}
50
+ />
51
+ );
52
+ });
53
+
54
+ export default OpenAI;
@@ -1,8 +1,8 @@
1
+ 'use client';
2
+
1
3
  import { Form, type ItemGroup } from '@lobehub/ui';
2
- import { Form as AntForm, Select, Switch } from 'antd';
4
+ import { Select, Switch } from 'antd';
3
5
  import isEqual from 'fast-deep-equal';
4
- import { debounce } from 'lodash-es';
5
- import { Mic, Webhook } from 'lucide-react';
6
6
  import { memo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
@@ -10,15 +10,15 @@ import { FORM_STYLE } from '@/const/layoutTokens';
10
10
  import { useUserStore } from '@/store/user';
11
11
  import { settingsSelectors } from '@/store/user/selectors';
12
12
 
13
- import { opeanaiSTTOptions, opeanaiTTSOptions, sttOptions } from './options';
13
+ import { sttOptions } from './const';
14
14
 
15
15
  type SettingItemGroup = ItemGroup;
16
16
 
17
17
  const TTS_SETTING_KEY = 'tts';
18
18
 
19
- const TTS = memo(() => {
19
+ const STT = memo(() => {
20
20
  const { t } = useTranslation('setting');
21
- const [form] = AntForm.useForm();
21
+ const [form] = Form.useForm();
22
22
  const settings = useUserStore(settingsSelectors.currentSettings, isEqual);
23
23
  const [setSettings] = useUserStore((s) => [s.setSettings]);
24
24
 
@@ -39,36 +39,20 @@ const TTS = memo(() => {
39
39
  valuePropName: 'checked',
40
40
  },
41
41
  ],
42
- icon: Mic,
43
42
  title: t('settingTTS.stt'),
44
43
  };
45
44
 
46
- const openai: SettingItemGroup = {
47
- children: [
48
- {
49
- children: <Select options={opeanaiTTSOptions} />,
50
- label: t('settingTTS.openai.ttsModel'),
51
- name: [TTS_SETTING_KEY, 'openAI', 'ttsModel'],
52
- },
53
- {
54
- children: <Select options={opeanaiSTTOptions} />,
55
- label: t('settingTTS.openai.sttModel'),
56
- name: [TTS_SETTING_KEY, 'openAI', 'sttModel'],
57
- },
58
- ],
59
- icon: Webhook,
60
- title: t('settingTTS.openai.title'),
61
- };
62
-
63
45
  return (
64
46
  <Form
65
47
  form={form}
66
48
  initialValues={settings}
67
- items={[stt, openai]}
68
- onValuesChange={debounce(setSettings, 100)}
49
+ items={[stt]}
50
+ itemsType={'group'}
51
+ onValuesChange={setSettings}
52
+ variant={'pure'}
69
53
  {...FORM_STYLE}
70
54
  />
71
55
  );
72
56
  });
73
57
 
74
- export default TTS;
58
+ export default STT;
@@ -1,18 +1,24 @@
1
- 'use client';
1
+ import { translation } from '@/server/translation';
2
2
 
3
- import { memo } from 'react';
4
- import { useTranslation } from 'react-i18next';
3
+ import OpenAI from './features/OpenAI';
4
+ import STT from './features/STT';
5
5
 
6
- import PageTitle from '@/components/PageTitle';
6
+ export const generateMetadata = async () => {
7
+ const { t } = await translation('setting');
8
+ return {
9
+ title: t('tab.tts'),
10
+ };
11
+ };
7
12
 
8
- import TTS from './TTS';
9
-
10
- export default memo(() => {
11
- const { t } = useTranslation('setting');
13
+ const Page = () => {
12
14
  return (
13
15
  <>
14
- <PageTitle title={t('tab.tts')} />
15
- <TTS />
16
+ <STT />
17
+ <OpenAI />
16
18
  </>
17
19
  );
18
- });
20
+ };
21
+
22
+ Page.displayName = 'TtsSetting';
23
+
24
+ export default Page;
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/about/layout';
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/about/page';
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/agent/layout';
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/agent/page';
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/common/page';
@@ -0,0 +1,28 @@
1
+ import { Skeleton } from 'antd';
2
+ import dynamic from 'next/dynamic';
3
+ import { PropsWithChildren } from 'react';
4
+
5
+ import SettingModalLayout from '../_layout/SettingModalLayout';
6
+
7
+ const CategoryContent = dynamic(
8
+ () => import('@/app/(main)/settings/@category/features/CategoryContent'),
9
+ { loading: () => <Skeleton paragraph={{ rows: 6 }} title={false} /> },
10
+ );
11
+ const UpgradeAlert = dynamic(() => import('@/app/(main)/settings/features/UpgradeAlert'), {});
12
+
13
+ const Layout = ({ children }: PropsWithChildren) => {
14
+ return (
15
+ <SettingModalLayout
16
+ category={
17
+ <>
18
+ <CategoryContent modal />
19
+ <UpgradeAlert />
20
+ </>
21
+ }
22
+ >
23
+ {children}
24
+ </SettingModalLayout>
25
+ );
26
+ };
27
+
28
+ export default Layout;
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/llm/page';
@@ -0,0 +1,5 @@
1
+ import { Skeleton } from 'antd';
2
+
3
+ export default () => {
4
+ return <Skeleton paragraph={{ rows: 6 }} style={{ paddingBlock: 16 }} />;
5
+ };
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/sync/page';
@@ -0,0 +1 @@
1
+ export { default } from '@/app/(main)/settings/tts/page';
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+
3
+ import { useResponsive, useTheme, useThemeMode } from 'antd-style';
4
+ import { ReactNode, useRef } from 'react';
5
+ import { Flexbox } from 'react-layout-kit';
6
+
7
+ import Header from '@/app/(main)/settings/_layout/Desktop/Header';
8
+ import SideBar from '@/app/(main)/settings/_layout/Desktop/SideBar';
9
+
10
+ interface SettingLayoutProps {
11
+ category: ReactNode;
12
+ children: ReactNode;
13
+ desc?: string;
14
+ title?: string;
15
+ }
16
+
17
+ const SettingModalLayout = ({ children, category, desc, title }: SettingLayoutProps) => {
18
+ const ref = useRef<any>(null);
19
+ const theme = useTheme();
20
+ const { isDarkMode } = useThemeMode();
21
+ const { md = true } = useResponsive();
22
+
23
+ return (
24
+ <>
25
+ {md ? (
26
+ <SideBar
27
+ desc={desc}
28
+ style={{
29
+ background: isDarkMode ? theme.colorBgContainer : theme.colorFillTertiary,
30
+ borderColor: theme.colorFillTertiary,
31
+ }}
32
+ title={title}
33
+ >
34
+ {category}
35
+ </SideBar>
36
+ ) : (
37
+ <Header getContainer={() => ref.current}>{category}</Header>
38
+ )}
39
+ <Flexbox
40
+ align={'center'}
41
+ gap={64}
42
+ style={{
43
+ background: isDarkMode ? theme.colorFillQuaternary : theme.colorBgElevated,
44
+ overflowX: 'hidden',
45
+ overflowY: 'auto',
46
+ paddingBlock: 32,
47
+ paddingInline: 56,
48
+ }}
49
+ width={'100%'}
50
+ >
51
+ {children}
52
+ </Flexbox>
53
+ </>
54
+ );
55
+ };
56
+
57
+ SettingModalLayout.displayName = 'SettingModalLayout';
58
+
59
+ export default SettingModalLayout;
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
7
+ import Menu from '@/components/Menu';
8
+ import { useQuery } from '@/hooks/useQuery';
9
+ import { useQueryRoute } from '@/hooks/useQueryRoute';
10
+
11
+ import { SettingsTabs, useCategory } from './useCategory';
12
+
13
+ const CategoryContent = memo(() => {
14
+ const cateItems = useCategory();
15
+ const router = useQueryRoute();
16
+ const { tab = SettingsTabs.Meta } = useQuery();
17
+
18
+ return (
19
+ <>
20
+ <Menu
21
+ items={cateItems}
22
+ onClick={({ key }) => {
23
+ router.replace('/chat/settings', { tab: key });
24
+ }}
25
+ selectable
26
+ selectedKeys={[tab as any]}
27
+ variant={'compact'}
28
+ />
29
+ <Flexbox align={'center'} gap={8} paddingInline={8} width={'100%'}>
30
+ <HeaderContent modal />
31
+ </Flexbox>
32
+ </>
33
+ );
34
+ });
35
+
36
+ export default CategoryContent;
@@ -0,0 +1,62 @@
1
+ import { Icon } from '@lobehub/ui';
2
+ import { Blocks, Bot, BrainCog, MessagesSquare, Mic2, UserCircle } from 'lucide-react';
3
+ import { useMemo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import type { MenuProps } from '@/components/Menu';
7
+
8
+ export enum SettingsTabs {
9
+ Chat = 'chat',
10
+ Meta = 'meta',
11
+ Modal = 'modal',
12
+ Plugin = 'plugin',
13
+ Prompt = 'prompt',
14
+ TTS = 'tts',
15
+ }
16
+
17
+ interface UseCategoryOptions {
18
+ mobile?: boolean;
19
+ }
20
+
21
+ export const useCategory = ({ mobile }: UseCategoryOptions = {}) => {
22
+ const { t } = useTranslation('setting');
23
+ const iconSize = mobile ? { fontSize: 20 } : undefined;
24
+
25
+ const cateItems: MenuProps['items'] = useMemo(
26
+ () => [
27
+ {
28
+ icon: <Icon icon={UserCircle} size={iconSize} />,
29
+ key: SettingsTabs.Meta,
30
+ label: t('settingAgent.title'),
31
+ },
32
+ {
33
+ icon: <Icon icon={Bot} size={iconSize} />,
34
+ key: SettingsTabs.Prompt,
35
+ label: t('settingAgent.prompt.title'),
36
+ },
37
+ {
38
+ icon: <Icon icon={MessagesSquare} size={iconSize} />,
39
+ key: SettingsTabs.Chat,
40
+ label: t('settingChat.title'),
41
+ },
42
+ {
43
+ icon: <Icon icon={BrainCog} size={iconSize} />,
44
+ key: SettingsTabs.Modal,
45
+ label: t('settingModel.title'),
46
+ },
47
+ {
48
+ icon: <Icon icon={Mic2} size={iconSize} />,
49
+ key: SettingsTabs.TTS,
50
+ label: t('settingTTS.title'),
51
+ },
52
+ {
53
+ icon: <Icon icon={Blocks} size={iconSize} />,
54
+ key: SettingsTabs.Plugin,
55
+ label: t('settingPlugin.title'),
56
+ },
57
+ ],
58
+ [t],
59
+ );
60
+
61
+ return cateItems;
62
+ };
@@ -0,0 +1,55 @@
1
+ 'use client';
2
+
3
+ import { Skeleton } from 'antd';
4
+ import isEqual from 'fast-deep-equal';
5
+ import dynamic from 'next/dynamic';
6
+ import { PropsWithChildren } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+
9
+ import StoreUpdater from '@/features/AgentSetting/StoreUpdater';
10
+ import { Provider, createStore } from '@/features/AgentSetting/store';
11
+ import { useAgentStore } from '@/store/agent';
12
+ import { agentSelectors } from '@/store/agent/slices/chat';
13
+ import { useSessionStore } from '@/store/session';
14
+ import { sessionMetaSelectors } from '@/store/session/selectors';
15
+
16
+ import SettingModalLayout from '../../_layout/SettingModalLayout';
17
+
18
+ const CategoryContent = dynamic(() => import('./features/CategoryContent'), {
19
+ loading: () => <Skeleton paragraph={{ rows: 6 }} title={false} />,
20
+ ssr: false,
21
+ });
22
+
23
+ const Layout = ({ children }: PropsWithChildren) => {
24
+ const { t } = useTranslation('setting');
25
+ const id = useSessionStore((s) => s.activeId);
26
+ const config = useAgentStore(agentSelectors.currentAgentConfig, isEqual);
27
+ const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
28
+ const [updateAgentConfig] = useAgentStore((s) => [s.updateAgentConfig]);
29
+
30
+ const [updateAgentMeta] = useSessionStore((s) => [
31
+ s.updateSessionMeta,
32
+ sessionMetaSelectors.currentAgentTitle(s),
33
+ ]);
34
+
35
+ return (
36
+ <SettingModalLayout
37
+ category={<CategoryContent />}
38
+ desc={t('header.sessionDesc')}
39
+ title={t('header.session')}
40
+ >
41
+ <Provider createStore={createStore}>
42
+ <StoreUpdater
43
+ config={config}
44
+ id={id}
45
+ meta={meta}
46
+ onConfigChange={updateAgentConfig}
47
+ onMetaChange={updateAgentMeta}
48
+ />
49
+ {children}
50
+ </Provider>
51
+ </SettingModalLayout>
52
+ );
53
+ };
54
+
55
+ export default Layout;
@@ -0,0 +1,5 @@
1
+ import { Skeleton } from 'antd';
2
+
3
+ export default () => {
4
+ return <Skeleton paragraph={{ rows: 6 }} style={{ paddingBlock: 16 }} />;
5
+ };