@lobehub/chat 0.152.12 → 0.153.0

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 (57) 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 +1 -0
  5. package/locales/bg-BG/common.json +1 -0
  6. package/locales/de-DE/common.json +1 -0
  7. package/locales/en-US/common.json +1 -0
  8. package/locales/es-ES/common.json +1 -0
  9. package/locales/fr-FR/common.json +1 -0
  10. package/locales/it-IT/common.json +1 -0
  11. package/locales/ja-JP/common.json +1 -0
  12. package/locales/ko-KR/common.json +1 -0
  13. package/locales/nl-NL/common.json +1 -0
  14. package/locales/pl-PL/common.json +1 -0
  15. package/locales/pt-BR/common.json +1 -0
  16. package/locales/ru-RU/common.json +1 -0
  17. package/locales/tr-TR/common.json +1 -0
  18. package/locales/vi-VN/common.json +1 -0
  19. package/locales/zh-CN/common.json +1 -0
  20. package/locales/zh-TW/common.json +1 -0
  21. package/package.json +1 -1
  22. package/src/app/(main)/chat/(desktop)/features/ChatHeader/Main.tsx +4 -9
  23. package/src/app/(main)/chat/(desktop)/features/SideBar/SystemRole/index.tsx +5 -6
  24. package/src/app/(main)/chat/features/SettingButton.tsx +3 -17
  25. package/src/app/(main)/chat/features/TopicListContent/Header.tsx +1 -1
  26. package/src/app/(main)/chat/settings/_layout/Desktop/Header.tsx +2 -1
  27. package/src/app/(main)/chat/settings/_layout/Mobile/Header.tsx +2 -1
  28. package/src/app/(main)/chat/settings/modal/page.tsx +23 -0
  29. package/src/app/(main)/settings/@category/features/CategoryContent.tsx +5 -1
  30. package/src/app/(main)/settings/modal/page.tsx +27 -0
  31. package/src/app/@modal/(.)settings/modal/index.tsx +40 -0
  32. package/src/app/@modal/(.)settings/modal/layout.tsx +32 -0
  33. package/src/app/@modal/(.)settings/modal/loading.tsx +5 -0
  34. package/src/app/@modal/(.)settings/modal/page.tsx +19 -0
  35. package/src/app/@modal/_layout/SettingModalLayout.tsx +59 -0
  36. package/src/app/@modal/chat/(.)settings/modal/features/CategoryContent.tsx +37 -0
  37. package/src/app/@modal/chat/(.)settings/modal/features/useCategory.tsx +54 -0
  38. package/src/app/@modal/chat/(.)settings/modal/layout.tsx +55 -0
  39. package/src/app/@modal/chat/(.)settings/modal/loading.tsx +5 -0
  40. package/src/app/@modal/chat/(.)settings/modal/page.tsx +55 -0
  41. package/src/app/@modal/default.tsx +3 -0
  42. package/src/app/@modal/error.tsx +5 -0
  43. package/src/app/@modal/layout.tsx +30 -0
  44. package/src/app/@modal/loading.tsx +5 -0
  45. package/src/app/layout.tsx +6 -2
  46. package/src/features/Conversation/Messages/index.ts +9 -12
  47. package/src/features/MobileTabBar/index.tsx +3 -3
  48. package/src/features/User/UserPanel/useMenu.tsx +31 -16
  49. package/src/hooks/useInterceptingRoutes.test.ts +70 -0
  50. package/src/hooks/useInterceptingRoutes.ts +46 -0
  51. package/src/hooks/useQuery.test.ts +0 -1
  52. package/src/hooks/useQuery.ts +2 -1
  53. package/src/layout/GlobalProvider/StoreInitialization.tsx +12 -5
  54. package/src/locales/default/common.ts +2 -1
  55. package/src/store/global/initialState.ts +9 -0
  56. package/src/features/User/UserPanel/UserInfo.tsx +0 -35
  57. /package/src/{app/(main)/chat/components → components}/SidebarHeader/index.tsx +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 0.153.0](https://github.com/lobehub/lobe-chat/compare/v0.152.12...v0.153.0)
6
+
7
+ <sup>Released on **2024-05-04**</sup>
8
+
9
+ #### ✨ Features
10
+
11
+ - **misc**: Add Settings Intercepting Routes.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's improved
19
+
20
+ - **misc**: Add Settings Intercepting Routes, closes [#2346](https://github.com/lobehub/lobe-chat/issues/2346) ([29b6442](https://github.com/lobehub/lobe-chat/commit/29b6442))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 0.152.12](https://github.com/lobehub/lobe-chat/compare/v0.152.11...v0.152.12)
6
31
 
7
32
  <sup>Released on **2024-05-04**</sup>
package/README.md CHANGED
@@ -222,14 +222,14 @@ In addition, these plugins are not limited to news aggregation, but can also ext
222
222
 
223
223
  <!-- PLUGIN LIST -->
224
224
 
225
- | Recent Submits | Description |
226
- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
227
- | [Social Search](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-05-02**</sup> | The Social Search provides access to tweets, users, followers, images, media and more.<br/>`social` `twitter` `x` `search` |
228
- | [Search Google via Serper](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Barry** on **2024-04-30**</sup> | Google search engine via Serper.dev free API (2500x🆓/month)<br/>`web` `search` |
229
- | [Speak](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **speak** on **2024-04-30**</sup> | Learn how to say anything in another language with Speak, your AI-powered language tutor.<br/>`education` `language` |
230
- | [NFT Guru](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **swap** on **2024-04-03**</sup> | Discover current prices of NFTs across major platforms and keep track of the rapidly changing marketplace with real-time<br/>`crypto` `nft` |
231
-
232
- > 📊 Total plugins: [<kbd>**57**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
225
+ | Recent Submits | Description |
226
+ | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
227
+ | [Social Search](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-05-02**</sup> | The Social Search provides access to tweets, users, followers, images, media and more.<br/>`social` `twitter` `x` `search` |
228
+ | [Search Google via Serper](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Barry** on **2024-04-30**</sup> | Google search engine via Serper.dev free API (2500x🆓/month)<br/>`web` `search` |
229
+ | [NFT Guru](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **swap** on **2024-04-03**</sup> | Discover current prices of NFTs across major platforms and keep track of the rapidly changing marketplace with real-time<br/>`crypto` `nft` |
230
+ | [Calendar Assistant](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **cc** on **2024-03-13**</sup> | A plugin to manage your calendar events # will auto generate i18n in workflow<br/>`calendar` `schedule` `will-auto-generate-i-18-n-in-workflow` |
231
+
232
+ > 📊 Total plugins: [<kbd>**56**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
233
233
 
234
234
  <!-- PLUGIN LIST -->
235
235
 
package/README.zh-CN.md CHANGED
@@ -214,14 +214,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
214
214
 
215
215
  <!-- PLUGIN LIST -->
216
216
 
217
- | 最近新增 | 插件描述 |
218
- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
219
- | [社交搜索](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-05-02**</sup> | 社交搜索提供访问推文、用户、关注者、图片、媒体等功能。<br/>`社交` `推特` `x` `搜索` |
220
- | [通过 Serper 搜索 Google](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Barry** on **2024-04-30**</sup> | 通过 Serper.dev 免费 API 进行 Google 搜索引擎(每月 2500 次🆓)<br/>`网络` `搜索` |
221
- | [Speak](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **speak** on **2024-04-30**</sup> | 使用 Speak,您的 AI 语言导师,学习如何用另一种语言说任何事情。<br/>`教育` `语言` |
222
- | [NFT Guru](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **swap** on **2024-04-03**</sup> | 发现主要平台上 NFT 的当前价格,并通过实时跟踪快速变化的市场了解情况<br/>`加密货币` `nft` |
223
-
224
- > 📊 Total plugins: [<kbd>**57**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
217
+ | 最近新增 | 插件描述 |
218
+ | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
219
+ | [社交搜索](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-05-02**</sup> | 社交搜索提供访问推文、用户、关注者、图片、媒体等功能。<br/>`社交` `推特` `x` `搜索` |
220
+ | [通过 Serper 搜索 Google](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **Barry** on **2024-04-30**</sup> | 通过 Serper.dev 免费 API 进行 Google 搜索引擎(每月 2500 次🆓)<br/>`网络` `搜索` |
221
+ | [NFT Guru](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **swap** on **2024-04-03**</sup> | 发现主要平台上 NFT 的当前价格,并通过实时跟踪快速变化的市场了解情况<br/>`加密货币` `nft` |
222
+ | [日历助手](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **cc** on **2024-03-13**</sup> | 一个用于管理日历事件的插件 # 将自动生成工作流程中的 i18n<br/>`日历` `日程安排` `将自动生成工作流程中的-i-18-n` |
223
+
224
+ > 📊 Total plugins: [<kbd>**56**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
225
225
 
226
226
  <!-- PLUGIN LIST -->
227
227
 
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "تقديم ملاحظات",
30
30
  "follow": "تابعنا على {{name}}",
31
+ "fullscreen": "وضع كامل الشاشة",
31
32
  "historyRange": "نطاق التاريخ",
32
33
  "import": "استيراد الإعدادات",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Обратна връзка",
30
30
  "follow": "Следете ни на {{name}}",
31
+ "fullscreen": "Цял екран",
31
32
  "historyRange": "Диапазон на историята",
32
33
  "import": "Импортирай конфигурация",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Feedback und Vorschläge",
30
30
  "follow": "Folge uns auf {{name}}",
31
+ "fullscreen": "Vollbildmodus",
31
32
  "historyRange": "Verlaufsbereich",
32
33
  "import": "Importieren",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Feedback",
30
30
  "follow": "Follow us on {{name}}",
31
+ "fullscreen": "Full Screen Mode",
31
32
  "historyRange": "History Range",
32
33
  "import": "Import Configuration",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Comentarios y sugerencias",
30
30
  "follow": "Síguenos en {{name}}",
31
+ "fullscreen": "Pantalla completa",
31
32
  "historyRange": "Rango de historial",
32
33
  "import": "Importar configuración",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Retour d'information et suggestions",
30
30
  "follow": "Suivez-nous sur {{name}}",
31
+ "fullscreen": "Mode plein écran",
31
32
  "historyRange": "Plage d'historique",
32
33
  "import": "Importer",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Feedback e suggerimenti",
30
30
  "follow": "Seguici su {{name}}",
31
+ "fullscreen": "Modalità a schermo intero",
31
32
  "historyRange": "Intervallo cronologico",
32
33
  "import": "Importa configurazione",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "フィードバック",
30
30
  "follow": " {{name}} で私たちをフォローする",
31
+ "fullscreen": "フルスクリーンモード",
31
32
  "historyRange": "履歴範囲",
32
33
  "import": "インポート",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "피드백 및 제안",
30
30
  "follow": "{{name}}에서 우리를 팔로우하세요",
31
+ "fullscreen": "전체 화면",
31
32
  "historyRange": "기록 범위",
32
33
  "import": "가져오기",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Feedback en suggesties",
30
30
  "follow": "Volg ons op {{name}}",
31
+ "fullscreen": "Volledig scherm",
31
32
  "historyRange": "Geschiedenisbereik",
32
33
  "import": "Importeren",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Opinie i sugestie",
30
30
  "follow": "Zaobserwuj nas na {{name}}",
31
+ "fullscreen": "Tryb pełnoekranowy",
31
32
  "historyRange": "Zakres historii",
32
33
  "import": "Importuj ustawienia",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Feedback e sugestões",
30
30
  "follow": "Siga-nos no {{name}}",
31
+ "fullscreen": "Modo de Tela Cheia",
31
32
  "historyRange": "Intervalo de histórico",
32
33
  "import": "Importar configuração",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Обратная связь и предложения",
30
30
  "follow": "Подпишитесь на нас на {{name}}",
31
+ "fullscreen": "Полноэкранный режим",
31
32
  "historyRange": "История",
32
33
  "import": "Импорт настроек",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Feedback",
30
30
  "follow": "Bizi {{name}} üzerinde takip edin",
31
+ "fullscreen": "Tam Ekran Modu",
31
32
  "historyRange": "Geçmiş Aralığı",
32
33
  "import": "İçe Aktar",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "Phản hồi và đề xuất",
30
30
  "follow": "Theo dõi chúng tôi trên {{name}}",
31
+ "fullscreen": "Chế độ toàn màn hình",
31
32
  "historyRange": "Phạm vi lịch sử",
32
33
  "import": "Nhập cấu hình",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "反馈与建议",
30
30
  "follow": "在 {{name}} 上关注我们",
31
+ "fullscreen": "全屏模式",
31
32
  "historyRange": "历史范围",
32
33
  "import": "导入配置",
33
34
  "importModal": {
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "feedback": "回饋與建議",
30
30
  "follow": "在 {{name}} 上關注我們",
31
+ "fullscreen": "全螢幕模式",
31
32
  "historyRange": "歷史範圍",
32
33
  "import": "匯入設定",
33
34
  "importModal": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.152.12",
3
+ "version": "0.153.0",
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",
@@ -1,21 +1,18 @@
1
1
  import { Avatar, ChatHeaderTitle } from '@lobehub/ui';
2
2
  import { Skeleton } from 'antd';
3
- import { useRouter } from 'next/navigation';
4
3
  import { memo } from 'react';
5
4
  import { useTranslation } from 'react-i18next';
6
5
  import { Flexbox } from 'react-layout-kit';
7
6
 
7
+ import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
8
8
  import { useSessionStore } from '@/store/session';
9
9
  import { sessionMetaSelectors, sessionSelectors } from '@/store/session/selectors';
10
- import { pathString } from '@/utils/url';
11
10
 
12
11
  import Tags from './Tags';
13
12
 
14
13
  const Main = memo(() => {
15
14
  const { t } = useTranslation('chat');
16
15
 
17
- const router = useRouter();
18
-
19
16
  const [init, isInbox, title, description, avatar, backgroundColor] = useSessionStore((s) => [
20
17
  sessionSelectors.isSomeSessionActive(s),
21
18
  sessionSelectors.isInboxSession(s),
@@ -25,6 +22,8 @@ const Main = memo(() => {
25
22
  sessionMetaSelectors.currentAgentBackgroundColor(s),
26
23
  ]);
27
24
 
25
+ const openChatSettings = useOpenChatSettings();
26
+
28
27
  const displayTitle = isInbox ? t('inbox.title') : title;
29
28
  const displayDesc = isInbox ? t('inbox.desc') : description;
30
29
 
@@ -42,11 +41,7 @@ const Main = memo(() => {
42
41
  <Avatar
43
42
  avatar={avatar}
44
43
  background={backgroundColor}
45
- onClick={() =>
46
- isInbox
47
- ? router.push('/settings/agent')
48
- : router.push(pathString('/chat/settings', { search: location.search }))
49
- }
44
+ onClick={openChatSettings}
50
45
  size={40}
51
46
  title={title}
52
47
  />
@@ -1,28 +1,27 @@
1
1
  import { ActionIcon, EditableMessage } from '@lobehub/ui';
2
2
  import { Skeleton } from 'antd';
3
3
  import { Edit } from 'lucide-react';
4
- import { useRouter } from 'next/navigation';
5
4
  import { memo, useState } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
  import { Flexbox } from 'react-layout-kit';
8
7
  import useMergeState from 'use-merge-value';
9
8
 
9
+ import SidebarHeader from '@/components/SidebarHeader';
10
10
  import AgentInfo from '@/features/AgentInfo';
11
+ import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
11
12
  import { useAgentStore } from '@/store/agent';
12
13
  import { agentSelectors } from '@/store/agent/selectors';
13
14
  import { useGlobalStore } from '@/store/global';
15
+ import { ChatSettingsTabs } from '@/store/global/initialState';
14
16
  import { useSessionStore } from '@/store/session';
15
17
  import { sessionMetaSelectors, sessionSelectors } from '@/store/session/selectors';
16
- import { pathString } from '@/utils/url';
17
18
 
18
- import SidebarHeader from '../../../../components/SidebarHeader';
19
19
  import { useStyles } from './style';
20
20
 
21
21
  const SystemRole = memo(() => {
22
- const router = useRouter();
23
22
  const [editing, setEditing] = useState(false);
24
23
  const { styles } = useStyles();
25
-
24
+ const openChatSettings = useOpenChatSettings(ChatSettingsTabs.Prompt);
26
25
  const [init, meta] = useSessionStore((s) => [
27
26
  sessionSelectors.isSomeSessionActive(s),
28
27
  sessionMetaSelectors.currentAgentMeta(s),
@@ -93,7 +92,7 @@ const SystemRole = memo(() => {
93
92
  onAvatarClick={() => {
94
93
  setOpen(false);
95
94
  setEditing(false);
96
- router.push(pathString('/chat/settings', { search: location.search }));
95
+ openChatSettings();
97
96
  }}
98
97
  style={{ marginBottom: 16 }}
99
98
  />
@@ -4,30 +4,16 @@ import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
6
  import { DESKTOP_HEADER_ICON_SIZE, MOBILE_HEADER_ICON_SIZE } from '@/const/layoutTokens';
7
- import { useQueryRoute } from '@/hooks/useQueryRoute';
8
- import { useGlobalStore } from '@/store/global';
9
- import { SidebarTabKey } from '@/store/global/initialState';
10
- import { useSessionStore } from '@/store/session';
11
- import { sessionSelectors } from '@/store/session/selectors';
7
+ import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
12
8
 
13
9
  const SettingButton = memo<{ mobile?: boolean }>(({ mobile }) => {
14
- const isInbox = useSessionStore(sessionSelectors.isInboxSession);
15
10
  const { t } = useTranslation('common');
16
- const router = useQueryRoute();
11
+ const openChatSettings = useOpenChatSettings();
17
12
 
18
13
  return (
19
14
  <ActionIcon
20
15
  icon={AlignJustify}
21
- onClick={() => {
22
- if (isInbox) {
23
- useGlobalStore.setState({
24
- sidebarKey: SidebarTabKey.Setting,
25
- });
26
- router.push('/settings/agent');
27
- } else {
28
- router.push('/chat/settings');
29
- }
30
- }}
16
+ onClick={openChatSettings}
31
17
  size={mobile ? MOBILE_HEADER_ICON_SIZE : DESKTOP_HEADER_ICON_SIZE}
32
18
  title={t('header.session', { ns: 'setting' })}
33
19
  />
@@ -5,10 +5,10 @@ import { memo, useMemo, useState } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { Flexbox } from 'react-layout-kit';
7
7
 
8
+ import SidebarHeader from '@/components/SidebarHeader';
8
9
  import { useChatStore } from '@/store/chat';
9
10
  import { topicSelectors } from '@/store/chat/selectors';
10
11
 
11
- import SidebarHeader from '../../components/SidebarHeader';
12
12
  import TopicSearchBar from './TopicSearchBar';
13
13
 
14
14
  const Header = memo(() => {
@@ -5,9 +5,10 @@ import { useRouter } from 'next/navigation';
5
5
  import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
- import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
9
8
  import { pathString } from '@/utils/url';
10
9
 
10
+ import HeaderContent from '../../features/HeaderContent';
11
+
11
12
  const Header = memo(() => {
12
13
  const { t } = useTranslation('setting');
13
14
  const router = useRouter();
@@ -5,10 +5,11 @@ import { useRouter } from 'next/navigation';
5
5
  import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
- import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
9
8
  import { mobileHeaderSticky } from '@/styles/mobileHeader';
10
9
  import { pathString } from '@/utils/url';
11
10
 
11
+ import HeaderContent from '../../features/HeaderContent';
12
+
12
13
  const Header = memo(() => {
13
14
  const { t } = useTranslation('setting');
14
15
  const router = useRouter();
@@ -0,0 +1,23 @@
1
+ 'use client';
2
+
3
+ import { useLayoutEffect } from 'react';
4
+
5
+ import { useQueryRoute } from '@/hooks/useQueryRoute';
6
+
7
+ /**
8
+ * @description: Chat Settings Modal (intercepting routes fallback when hard refresh)
9
+ * @example: /chat/settings/modal?tab=prompt => /chat/settings
10
+ * @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
11
+ */
12
+
13
+ const ChatSettingsModalFallback = () => {
14
+ const router = useQueryRoute();
15
+
16
+ useLayoutEffect(() => {
17
+ router.replace('/chat/settings', { query: { tab: '' } });
18
+ }, []);
19
+
20
+ return null;
21
+ };
22
+
23
+ export default ChatSettingsModalFallback;
@@ -21,7 +21,11 @@ const CategoryContent = memo<{ modal?: boolean }>(({ modal }) => {
21
21
  <Menu
22
22
  items={cateItems}
23
23
  onClick={({ key }) => {
24
- router.push(urlJoin('/settings', key));
24
+ if (modal) {
25
+ router.replace('/settings/modal', { query: { tab: key } });
26
+ } else {
27
+ router.push(urlJoin('/settings', key));
28
+ }
25
29
  }}
26
30
  selectable
27
31
  selectedKeys={[modal ? tab : (activeTab as any)]}
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+
3
+ import { useLayoutEffect } from 'react';
4
+ import urlJoin from 'url-join';
5
+
6
+ import { useQuery } from '@/hooks/useQuery';
7
+ import { useQueryRoute } from '@/hooks/useQueryRoute';
8
+ import { SettingsTabs } from '@/store/global/initialState';
9
+
10
+ /**
11
+ * @description: Settings Modal (intercepting routes fallback when hard refresh)
12
+ * @example: /settings/modal?tab=common => /settings/common
13
+ * @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
14
+ */
15
+
16
+ const SettingsModalFallback = () => {
17
+ const { tab = SettingsTabs.Common } = useQuery();
18
+ const router = useQueryRoute();
19
+
20
+ useLayoutEffect(() => {
21
+ router.replace(urlJoin('/settings', tab as SettingsTabs), { query: { tab: '' } });
22
+ }, []);
23
+
24
+ return null;
25
+ };
26
+
27
+ export default SettingsModalFallback;
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+
3
+ import dynamic from 'next/dynamic';
4
+ import { memo } from 'react';
5
+
6
+ import { useQuery } from '@/hooks/useQuery';
7
+ import { SettingsTabs } from '@/store/global/initialState';
8
+
9
+ import Skeleton from './loading';
10
+
11
+ const loading = () => <Skeleton />;
12
+
13
+ const Common = dynamic(() => import('@/app/(main)/settings/common'), { loading, ssr: false });
14
+ const About = dynamic(() => import('@/app/(main)/settings/about'), { loading, ssr: false });
15
+ const LLM = dynamic(() => import('@/app/(main)/settings/llm'), { loading, ssr: false });
16
+ const TTS = dynamic(() => import('@/app/(main)/settings/tts'), { loading, ssr: false });
17
+ const Agent = dynamic(() => import('@/app/(main)/settings/agent'), { loading, ssr: false });
18
+ const Sync = dynamic(() => import('@/app/(main)/settings/sync'), { loading, ssr: false });
19
+
20
+ interface SettingsModalProps {
21
+ browser?: string;
22
+ mobile?: boolean;
23
+ os?: string;
24
+ }
25
+
26
+ const SettingsModal = memo<SettingsModalProps>(({ browser, os, mobile }) => {
27
+ const { tab = SettingsTabs.Common } = useQuery();
28
+ return (
29
+ <>
30
+ {tab === SettingsTabs.Common && <Common />}
31
+ {tab === SettingsTabs.Sync && <Sync browser={browser} mobile={mobile} os={os} />}
32
+ {tab === SettingsTabs.LLM && <LLM />}
33
+ {tab === SettingsTabs.TTS && <TTS />}
34
+ {tab === SettingsTabs.Agent && <Agent />}
35
+ {tab === SettingsTabs.About && <About mobile={mobile} />}
36
+ </>
37
+ );
38
+ });
39
+
40
+ export default SettingsModal;
@@ -0,0 +1,32 @@
1
+ 'use client';
2
+
3
+ import { Skeleton } from 'antd';
4
+ import dynamic from 'next/dynamic';
5
+ import { PropsWithChildren, memo } from 'react';
6
+
7
+ import SettingModalLayout from '../../_layout/SettingModalLayout';
8
+
9
+ const CategoryContent = dynamic(
10
+ () => import('@/app/(main)/settings/@category/features/CategoryContent'),
11
+ { loading: () => <Skeleton paragraph={{ rows: 6 }} title={false} />, ssr: false },
12
+ );
13
+ const UpgradeAlert = dynamic(() => import('@/app/(main)/settings/features/UpgradeAlert'), {
14
+ ssr: false,
15
+ });
16
+
17
+ const Layout = memo<PropsWithChildren>(({ children }) => {
18
+ return (
19
+ <SettingModalLayout
20
+ category={
21
+ <>
22
+ <CategoryContent modal />
23
+ <UpgradeAlert />
24
+ </>
25
+ }
26
+ >
27
+ {children}
28
+ </SettingModalLayout>
29
+ );
30
+ });
31
+
32
+ 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
+ };
@@ -0,0 +1,19 @@
1
+ import { gerServerDeviceInfo, isMobileDevice } from '@/utils/responsive';
2
+
3
+ import SettingsModal from './index';
4
+
5
+ /**
6
+ * @description: Settings Modal (intercepting route: /settings/modal )
7
+ * @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
8
+ */
9
+
10
+ const Page = () => {
11
+ const isMobile = isMobileDevice();
12
+ const { os, browser } = gerServerDeviceInfo();
13
+
14
+ return <SettingsModal browser={browser} mobile={isMobile} os={os} />;
15
+ };
16
+
17
+ Page.displayName = 'SettingModal';
18
+
19
+ export default Page;
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+
3
+ import { useResponsive, useTheme, useThemeMode } from 'antd-style';
4
+ import { ReactNode, memo, 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 = memo<SettingLayoutProps>(({ children, category, desc, title }) => {
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: 40,
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;