@lobehub/lobehub 2.0.0-next.34 → 2.0.0-next.35

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 (139) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/package.json +1 -1
  4. package/src/app/[variants]/(main)/chat/ChatRouter.tsx +83 -0
  5. package/src/app/[variants]/(main)/chat/_layout/ChatLayout.tsx +22 -0
  6. package/src/app/[variants]/(main)/chat/_layout/Desktop/SessionPanel.tsx +12 -7
  7. package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +2 -2
  8. package/src/app/[variants]/(main)/chat/_layout/FeatureFlagsProvider.tsx +24 -0
  9. package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +3 -2
  10. package/src/app/[variants]/(main)/chat/_layout/type.ts +0 -1
  11. package/src/app/[variants]/(main)/chat/components/ConversationArea.tsx +29 -0
  12. package/src/app/[variants]/(main)/chat/components/MainChatPage.tsx +25 -0
  13. package/src/app/[variants]/(main)/chat/components/PortalPanel.tsx +28 -0
  14. package/src/app/[variants]/(main)/chat/components/SessionPanel.tsx +33 -0
  15. package/src/app/[variants]/(main)/chat/{settings/page.tsx → components/SettingsPage.tsx} +35 -3
  16. package/src/app/[variants]/(main)/chat/components/TopicSidebar.tsx +30 -0
  17. package/src/app/[variants]/(main)/chat/components/WorkspaceLayout.tsx +73 -0
  18. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/index.tsx +1 -1
  19. package/src/app/[variants]/(main)/chat/{layout.ts → layout.tsx} +0 -1
  20. package/src/app/[variants]/(main)/chat/page.tsx +12 -0
  21. package/src/features/Portal/GroupThread/Body/index.tsx +1 -1
  22. package/src/hooks/useHotkeys/chatScope.ts +1 -1
  23. package/src/app/[variants]/(main)/chat/(workspace)/layout.ts +0 -11
  24. package/src/app/[variants]/(main)/chat/(workspace)/page.tsx +0 -53
  25. package/src/app/[variants]/(main)/chat/@session/default.tsx +0 -31
  26. package/src/app/[variants]/(main)/chat/settings/layout.tsx +0 -21
  27. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/default.tsx +0 -0
  28. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatHydration/index.tsx +0 -0
  29. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/ClassicChat.tsx +0 -0
  30. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/GroupChat.tsx +0 -0
  31. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/MessageFromUrl.tsx +0 -0
  32. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/index.tsx +0 -0
  33. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/useSendMenuItems.tsx +0 -0
  34. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Mobile/MentionedUsers/MentionedUserItem.tsx +0 -0
  35. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Mobile/MentionedUsers/index.tsx +0 -0
  36. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Mobile/index.tsx +0 -0
  37. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/ActionBar.tsx +0 -0
  38. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/Files/index.tsx +0 -0
  39. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/InputArea/Container.tsx +0 -0
  40. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/InputArea/index.tsx +0 -0
  41. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/Send.tsx +0 -0
  42. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/index.tsx +0 -0
  43. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/useSend.ts +0 -0
  44. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/index.tsx +0 -0
  45. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/useSend.ts +0 -0
  46. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/OrchestratorThinking.tsx +0 -0
  47. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/Thread.tsx +0 -0
  48. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/ThreadItem.tsx +0 -0
  49. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/Content.tsx +0 -0
  50. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/AgentWelcome/AddButton.tsx +0 -0
  51. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/AgentWelcome/OpeningQuestions.tsx +0 -0
  52. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/AgentWelcome/index.tsx +0 -0
  53. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/GroupWelcome/GroupUsageSuggest.tsx +0 -0
  54. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/GroupWelcome/index.tsx +0 -0
  55. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/GroupWelcome/useTemplateMatching.ts +0 -0
  56. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/index.tsx +0 -0
  57. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/index.tsx +0 -0
  58. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatMinimap/index.tsx +0 -0
  59. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ThreadHydration.tsx +0 -0
  60. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ZenModeToast/Toast.tsx +0 -0
  61. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ZenModeToast/index.tsx +0 -0
  62. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/AgentSettings/index.tsx +0 -0
  63. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/AgentTeamSettings/index.tsx +0 -0
  64. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/ChangelogModal.tsx +0 -0
  65. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/SettingButton.tsx +0 -0
  66. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/ShareButton/index.tsx +0 -0
  67. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/TelemetryNotification.tsx +0 -0
  68. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/HeaderAction.tsx +0 -0
  69. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Main.tsx +0 -0
  70. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/HistoryLimitTags.tsx +0 -0
  71. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/KnowledgeTag.tsx +0 -0
  72. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/MemberCountTag.tsx +0 -0
  73. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/SearchTags.tsx +0 -0
  74. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/index.tsx +0 -0
  75. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/index.tsx +0 -0
  76. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/Portal.tsx +0 -0
  77. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/TopicPanel.tsx +0 -0
  78. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/index.tsx +0 -0
  79. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/ChatHeader/ChatHeaderTitle.tsx +0 -0
  80. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/ChatHeader/index.tsx +0 -0
  81. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/TopicModal.tsx +0 -0
  82. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/index.tsx +0 -0
  83. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/type.ts +0 -0
  84. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/_layout/Desktop.tsx +0 -0
  85. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/_layout/Mobile.tsx +0 -0
  86. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/default.tsx +0 -0
  87. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/error.tsx +0 -0
  88. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/features/Body.tsx +0 -0
  89. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/loading.tsx +0 -0
  90. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/_layout/Desktop.tsx +0 -0
  91. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/_layout/Mobile.tsx +0 -0
  92. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/default.tsx +0 -0
  93. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/AgentConfig/SystemRole.tsx +0 -0
  94. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/AgentConfig/index.tsx +0 -0
  95. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/ConfigLayout.tsx +0 -0
  96. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/ConfigSwitcher.tsx +0 -0
  97. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/GroupMember.tsx +0 -0
  98. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/GroupMemberItem.tsx +0 -0
  99. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/GroupRole.tsx +0 -0
  100. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/index.tsx +0 -0
  101. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/style.ts +0 -0
  102. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/SkeletonList.tsx +0 -0
  103. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/Header.tsx +0 -0
  104. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ByTimeMode/GroupItem.tsx +0 -0
  105. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ByTimeMode/index.tsx +0 -0
  106. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/FlatMode/index.tsx +0 -0
  107. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/SearchResult/index.tsx +0 -0
  108. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ThreadItem/Content.tsx +0 -0
  109. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ThreadItem/index.tsx +0 -0
  110. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ThreadList/index.tsx +0 -0
  111. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/TopicItem/DefaultContent.tsx +0 -0
  112. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/TopicItem/TopicContent.tsx +0 -0
  113. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/TopicItem/index.tsx +0 -0
  114. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/index.tsx +0 -0
  115. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicSearchBar/index.tsx +0 -0
  116. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/index.tsx +0 -0
  117. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionHydration.tsx +0 -0
  118. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/CollapseGroup/Actions.tsx +0 -0
  119. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/CollapseGroup/index.tsx +0 -0
  120. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/DefaultMode.tsx +0 -0
  121. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Inbox/index.tsx +0 -0
  122. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/AddButton.tsx +0 -0
  123. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/Item/Actions.tsx +0 -0
  124. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/Item/index.tsx +0 -0
  125. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/index.tsx +0 -0
  126. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/ListItem/index.tsx +0 -0
  127. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/ConfigGroupModal/GroupItem.tsx +0 -0
  128. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/ConfigGroupModal/index.tsx +0 -0
  129. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/CreateGroupModal.tsx +0 -0
  130. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/RenameGroupModal.tsx +0 -0
  131. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/SearchMode.tsx +0 -0
  132. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/index.tsx +0 -0
  133. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionSearchBar.tsx +0 -0
  134. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SkeletonList.tsx +0 -0
  135. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Desktop/PanelBody.tsx +0 -0
  136. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Desktop/SessionHeader.tsx +0 -0
  137. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Desktop/index.tsx +0 -0
  138. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Mobile/SessionHeader.tsx +0 -0
  139. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Mobile/index.tsx +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.35](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.34...v2.0.0-next.35)
6
+
7
+ <sup>Released on **2025-11-07**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Use react-router-dom change /chat page to spa mode.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Use react-router-dom change /chat page to spa mode, closes [#10077](https://github.com/lobehub/lobe-chat/issues/10077) ([9154606](https://github.com/lobehub/lobe-chat/commit/9154606))
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 2.0.0-next.34](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.33...v2.0.0-next.34)
6
31
 
7
32
  <sup>Released on **2025-11-07**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Use react-router-dom change /chat page to spa mode."
6
+ ]
7
+ },
8
+ "date": "2025-11-07",
9
+ "version": "2.0.0-next.35"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "improvements": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.34",
3
+ "version": "2.0.0-next.35",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent 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,83 @@
1
+ 'use client';
2
+
3
+ import { memo, useEffect } from 'react';
4
+ import { useMediaQuery } from 'react-responsive';
5
+ import { MemoryRouter, Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
6
+
7
+ import MainChatPage from './components/MainChatPage';
8
+ import SettingsPage from './components/SettingsPage';
9
+
10
+ // Get initial path from URL
11
+ const getInitialPath = () => {
12
+ if (typeof window === 'undefined') return '/';
13
+ const fullPath = window.location.pathname;
14
+ const searchParams = window.location.search;
15
+ const chatIndex = fullPath.indexOf('/chat');
16
+
17
+ if (chatIndex !== -1) {
18
+ const pathAfterChat = fullPath.slice(chatIndex + '/chat'.length) || '/';
19
+ return pathAfterChat + searchParams;
20
+ }
21
+ return '/';
22
+ };
23
+
24
+ // Helper component to sync URL with MemoryRouter
25
+ const UrlSynchronizer = () => {
26
+ const location = useLocation();
27
+ const navigate = useNavigate();
28
+
29
+ // Sync initial URL
30
+ useEffect(() => {
31
+ const fullPath = window.location.pathname;
32
+ const searchParams = window.location.search;
33
+ const chatIndex = fullPath.indexOf('/chat');
34
+
35
+ if (chatIndex !== -1) {
36
+ const pathAfterChat = fullPath.slice(chatIndex + '/chat'.length) || '/';
37
+ const targetPath = pathAfterChat + searchParams;
38
+
39
+ if (location.pathname + location.search !== targetPath) {
40
+ navigate(targetPath, { replace: true });
41
+ }
42
+ }
43
+ }, []);
44
+
45
+ // Update browser URL when location changes
46
+ useEffect(() => {
47
+ const normalizedPath = location.pathname === '/' ? '' : location.pathname;
48
+ const newUrl = `/chat${normalizedPath}${location.search}`;
49
+ if (window.location.pathname + window.location.search !== newUrl) {
50
+ window.history.replaceState({}, '', newUrl);
51
+ }
52
+ }, [location.pathname, location.search]);
53
+
54
+ return null;
55
+ };
56
+
57
+ const ChatRouter = memo(() => {
58
+ const mobile = useMediaQuery({ maxWidth: 768 });
59
+ const routes = (
60
+ <Routes>
61
+ <Route element={<MainChatPage mobile={true} />} path="/" />
62
+ <Route element={<SettingsPage mobile={true} />} path="/settings" />
63
+ <Route element={<Navigate replace to="/" />} path="*" />
64
+ </Routes>
65
+ );
66
+
67
+ return (
68
+ <MemoryRouter initialEntries={[getInitialPath()]} initialIndex={0}>
69
+ <UrlSynchronizer />
70
+ {mobile ? (
71
+ // Mobile Layout
72
+ routes
73
+ ) : (
74
+ // Desktop Layout
75
+ <MainChatPage mobile={false} />
76
+ )}
77
+ </MemoryRouter>
78
+ );
79
+ });
80
+
81
+ ChatRouter.displayName = 'ChatRouter';
82
+
83
+ export default ChatRouter;
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, memo } from 'react';
4
+
5
+ import Desktop from './Desktop';
6
+ import Mobile from './Mobile';
7
+
8
+ interface ChatLayoutProps extends PropsWithChildren {
9
+ mobile?: boolean;
10
+ }
11
+
12
+ const ChatLayout = memo<ChatLayoutProps>(({ children, mobile }) => {
13
+ if (mobile) {
14
+ return <Mobile>{children}</Mobile>;
15
+ }
16
+
17
+ return <Desktop>{children}</Desktop>;
18
+ });
19
+
20
+ ChatLayout.displayName = 'ChatLayout';
21
+
22
+ export default ChatLayout;
@@ -3,7 +3,7 @@
3
3
  import { DraggablePanel, DraggablePanelContainer, type DraggablePanelProps } from '@lobehub/ui';
4
4
  import { createStyles, useResponsive, useThemeMode } from 'antd-style';
5
5
  import isEqual from 'fast-deep-equal';
6
- import { PropsWithChildren, memo, useEffect, useMemo, useState } from 'react';
6
+ import { memo, useEffect, useMemo, useState } from 'react';
7
7
 
8
8
  import { withSuspense } from '@/components/withSuspense';
9
9
  import { FOLDER_WIDTH } from '@/const/layoutTokens';
@@ -12,6 +12,7 @@ import { usePinnedAgentState } from '@/hooks/usePinnedAgentState';
12
12
  import { useGlobalStore } from '@/store/global';
13
13
  import { systemStatusSelectors } from '@/store/global/selectors';
14
14
 
15
+ import SessionPanelContent from '../../components/SessionPanel';
15
16
  import { TOOGLE_PANEL_BUTTON_ID } from '../../features/TogglePanelButton';
16
17
 
17
18
  export const useStyles = createStyles(({ css, token }) => ({
@@ -33,7 +34,7 @@ export const useStyles = createStyles(({ css, token }) => ({
33
34
  `,
34
35
  }));
35
36
 
36
- const SessionPanel = memo<PropsWithChildren>(({ children }) => {
37
+ const SessionPanel = memo(() => {
37
38
  const isSingleMode = useIsSingleMode();
38
39
 
39
40
  const { md = true } = useResponsive();
@@ -75,11 +76,15 @@ const SessionPanel = memo<PropsWithChildren>(({ children }) => {
75
76
 
76
77
  const { appearance } = useThemeMode();
77
78
 
78
- const SessionPanel = useMemo(() => {
79
+ const PanelContent = useMemo(() => {
79
80
  if (isSingleMode) {
80
- // 在单一模式下,仍然渲染 children 以确保 SessionHydration 等逻辑组件正常工作
81
+ // 在单一模式下,仍然渲染 SessionPanelContent 以确保 SessionHydration 等逻辑组件正常工作
81
82
  // 但使用隐藏样式而不是 return null
82
- return <div style={{ display: 'none' }}>{children}</div>;
83
+ return (
84
+ <div style={{ display: 'none' }}>
85
+ <SessionPanelContent mobile={false} />
86
+ </div>
87
+ );
83
88
  }
84
89
 
85
90
  return (
@@ -98,13 +103,13 @@ const SessionPanel = memo<PropsWithChildren>(({ children }) => {
98
103
  size={{ height: '100%', width: sessionsWidth }}
99
104
  >
100
105
  <DraggablePanelContainer style={{ flex: 'none', height: '100%', minWidth: FOLDER_WIDTH }}>
101
- {children}
106
+ <SessionPanelContent mobile={false} />
102
107
  </DraggablePanelContainer>
103
108
  </DraggablePanel>
104
109
  );
105
110
  }, [sessionsWidth, md, isPinned, sessionExpandable, tmpWidth, appearance, isSingleMode]);
106
111
 
107
- return SessionPanel;
112
+ return PanelContent;
108
113
  });
109
114
 
110
115
  export default withSuspense(SessionPanel);
@@ -9,7 +9,7 @@ import RegisterHotkeys from './RegisterHotkeys';
9
9
  import SessionPanel from './SessionPanel';
10
10
  import Workspace from './Workspace';
11
11
 
12
- const Layout = ({ children, session }: LayoutProps) => {
12
+ const Layout = ({ children }: LayoutProps) => {
13
13
  return (
14
14
  <>
15
15
  <Flexbox
@@ -18,7 +18,7 @@ const Layout = ({ children, session }: LayoutProps) => {
18
18
  style={{ maxWidth: '100%', overflow: 'hidden', position: 'relative' }}
19
19
  width={'100%'}
20
20
  >
21
- <SessionPanel>{session}</SessionPanel>
21
+ <SessionPanel />
22
22
  <Workspace>{children}</Workspace>
23
23
  </Flexbox>
24
24
  {/* ↓ cloud slot ↓ */}
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, createContext, useContext } from 'react';
4
+
5
+ interface FeatureFlags {
6
+ hideDocs?: boolean;
7
+ showChangelog?: boolean;
8
+ }
9
+
10
+ const FeatureFlagsContext = createContext<FeatureFlags>({});
11
+
12
+ export const useFeatureFlags = () => useContext(FeatureFlagsContext);
13
+
14
+ export const FeatureFlagsProvider = ({
15
+ children,
16
+ hideDocs,
17
+ showChangelog,
18
+ }: PropsWithChildren<FeatureFlags>) => {
19
+ return (
20
+ <FeatureFlagsContext.Provider value={{ hideDocs, showChangelog }}>
21
+ {children}
22
+ </FeatureFlagsContext.Provider>
23
+ );
24
+ };
@@ -7,6 +7,7 @@ import { Flexbox } from 'react-layout-kit';
7
7
  import { withSuspense } from '@/components/withSuspense';
8
8
  import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
9
9
 
10
+ import SessionPanelContent from '../components/SessionPanel';
10
11
  import { LayoutProps } from './type';
11
12
 
12
13
  const useStyles = createStyles(({ css, token }) => ({
@@ -17,7 +18,7 @@ const useStyles = createStyles(({ css, token }) => ({
17
18
  `,
18
19
  }));
19
20
 
20
- const Layout = memo<LayoutProps>(({ children, session }) => {
21
+ const Layout = memo<LayoutProps>(({ children }) => {
21
22
  const showMobileWorkspace = useShowMobileWorkspace();
22
23
  const { styles } = useStyles();
23
24
 
@@ -29,7 +30,7 @@ const Layout = memo<LayoutProps>(({ children, session }) => {
29
30
  style={showMobileWorkspace ? { display: 'none' } : undefined}
30
31
  width="100%"
31
32
  >
32
- {session}
33
+ <SessionPanelContent mobile />
33
34
  </Flexbox>
34
35
  <Flexbox
35
36
  className={styles.main}
@@ -2,5 +2,4 @@ import { ReactNode } from 'react';
2
2
 
3
3
  export interface LayoutProps {
4
4
  children: ReactNode;
5
- session: ReactNode;
6
5
  }
@@ -0,0 +1,29 @@
1
+ import { memo } from 'react';
2
+
3
+ import ChatHydration from './conversation/features/ChatHydration';
4
+ import ChatInput from './conversation/features/ChatInput';
5
+ import ChatList from './conversation/features/ChatList';
6
+ import ChatMinimap from './conversation/features/ChatMinimap';
7
+ import ThreadHydration from './conversation/features/ThreadHydration';
8
+ import ZenModeToast from './conversation/features/ZenModeToast';
9
+
10
+ interface ConversationAreaProps {
11
+ mobile?: boolean;
12
+ }
13
+
14
+ const ConversationArea = memo<ConversationAreaProps>(({ mobile = false }) => {
15
+ return (
16
+ <>
17
+ <ZenModeToast />
18
+ <ChatList mobile={mobile} />
19
+ <ChatInput mobile={mobile} />
20
+ <ChatHydration />
21
+ <ThreadHydration />
22
+ {!mobile && <ChatMinimap />}
23
+ </>
24
+ );
25
+ });
26
+
27
+ ConversationArea.displayName = 'ConversationArea';
28
+
29
+ export default ConversationArea;
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+
5
+ import TelemetryNotification from '../components/features/TelemetryNotification';
6
+ import PageTitle from '../features/PageTitle';
7
+ import WorkspaceLayout from './WorkspaceLayout';
8
+
9
+ interface MainChatPageProps {
10
+ mobile?: boolean;
11
+ }
12
+
13
+ const MainChatPage = memo<MainChatPageProps>(({ mobile }) => {
14
+ return (
15
+ <>
16
+ <PageTitle />
17
+ <WorkspaceLayout mobile={mobile} />
18
+ <TelemetryNotification mobile={mobile} />
19
+ </>
20
+ );
21
+ });
22
+
23
+ MainChatPage.displayName = 'MainChatPage';
24
+
25
+ export default MainChatPage;
@@ -0,0 +1,28 @@
1
+ import { Suspense, lazy, memo } from 'react';
2
+
3
+ import Loading from '@/components/Loading/BrandTextLoading';
4
+
5
+ import DesktopLayout from './portal/_layout/Desktop';
6
+ import MobileLayout from './portal/_layout/Mobile';
7
+
8
+ const PortalBody = lazy(() => import('@/features/Portal/router'));
9
+
10
+ interface PortalPanelProps {
11
+ mobile?: boolean;
12
+ }
13
+
14
+ const PortalPanel = memo<PortalPanelProps>(({ mobile }) => {
15
+ const Layout = mobile ? MobileLayout : DesktopLayout;
16
+
17
+ return (
18
+ <Suspense fallback={<Loading />}>
19
+ <Layout>
20
+ <PortalBody />
21
+ </Layout>
22
+ </Suspense>
23
+ );
24
+ });
25
+
26
+ PortalPanel.displayName = 'PortalPanel';
27
+
28
+ export default PortalPanel;
@@ -0,0 +1,33 @@
1
+ import { Suspense, lazy, memo } from 'react';
2
+
3
+ import CircleLoading from '@/components/Loading/CircleLoading';
4
+
5
+ import DesktopLayout from '../session/layout/Desktop';
6
+ import MobileLayout from '../session/layout/Mobile';
7
+ import SessionHydration from '../session/features/SessionHydration';
8
+ import SkeletonList from '../session/features/SkeletonList';
9
+
10
+ const SessionListContent = lazy(() => import('../session/features/SessionListContent'));
11
+
12
+ interface SessionPanelProps {
13
+ mobile?: boolean;
14
+ }
15
+
16
+ const SessionPanel = memo<SessionPanelProps>(({ mobile }) => {
17
+ const Layout = mobile ? MobileLayout : DesktopLayout;
18
+
19
+ return (
20
+ <Suspense fallback={<CircleLoading />}>
21
+ <Layout>
22
+ <Suspense fallback={<SkeletonList />}>
23
+ <SessionListContent />
24
+ </Suspense>
25
+ </Layout>
26
+ <SessionHydration />
27
+ </Suspense>
28
+ );
29
+ });
30
+
31
+ SessionPanel.displayName = 'SessionPanel';
32
+
33
+ export default SessionPanel;
@@ -6,9 +6,14 @@ import isEqual from 'fast-deep-equal';
6
6
  import { memo, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
+ import MobileContentLayout from '@/components/server/MobileNavLayout';
9
10
  import PageTitle from '@/components/PageTitle';
11
+ import SafeSpacing from '@/components/SafeSpacing';
12
+ import { HEADER_HEIGHT } from '@/const/layoutTokens';
10
13
  import { useCategory } from '@/features/AgentSetting/AgentCategory/useCategory';
11
14
  import AgentSettings from '@/features/AgentSetting/AgentSettings';
15
+ import Footer from '@/features/Setting/Footer';
16
+ import SettingContainer from '@/features/Setting/SettingContainer';
12
17
  import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
13
18
  import { useAgentStore } from '@/store/agent';
14
19
  import { agentSelectors } from '@/store/agent/selectors';
@@ -16,7 +21,14 @@ import { ChatSettingsTabs } from '@/store/global/initialState';
16
21
  import { useSessionStore } from '@/store/session';
17
22
  import { sessionMetaSelectors } from '@/store/session/selectors';
18
23
 
19
- const EditPage = memo(() => {
24
+ import DesktopHeader from '../settings/_layout/Desktop/Header';
25
+ import MobileHeader from '../settings/_layout/Mobile/Header';
26
+
27
+ interface SettingsPageProps {
28
+ mobile?: boolean;
29
+ }
30
+
31
+ const SettingsPage = memo<SettingsPageProps>(({ mobile = false }) => {
20
32
  const { t } = useTranslation('setting');
21
33
  const [tab, setTab] = useState(ChatSettingsTabs.Prompt);
22
34
  const theme = useTheme();
@@ -34,7 +46,7 @@ const EditPage = memo(() => {
34
46
 
35
47
  const { isLoading } = useInitAgentConfig();
36
48
 
37
- return (
49
+ const content = (
38
50
  <>
39
51
  <PageTitle title={t('header.sessionWithName', { name: title })} />
40
52
  <Tabs
@@ -57,6 +69,26 @@ const EditPage = memo(() => {
57
69
  />
58
70
  </>
59
71
  );
72
+
73
+ if (mobile) {
74
+ return (
75
+ <MobileContentLayout header={<MobileHeader />}>
76
+ {content}
77
+ <Footer />
78
+ </MobileContentLayout>
79
+ );
80
+ }
81
+
82
+ return (
83
+ <>
84
+ <DesktopHeader />
85
+ <SettingContainer addonAfter={<Footer />} addonBefore={<SafeSpacing height={HEADER_HEIGHT} />}>
86
+ {content}
87
+ </SettingContainer>
88
+ </>
89
+ );
60
90
  });
61
91
 
62
- export default EditPage;
92
+ SettingsPage.displayName = 'SettingsPage';
93
+
94
+ export default SettingsPage;
@@ -0,0 +1,30 @@
1
+ import dynamic from 'next/dynamic';
2
+ import { memo } from 'react';
3
+
4
+ import DesktopLayout from './topic/_layout/Desktop';
5
+ import MobileLayout from './topic/_layout/Mobile';
6
+ import SkeletonList from './topic/features/SkeletonList';
7
+ import Topic from './topic/features/Topic';
8
+
9
+ const ConfigSwitcher = dynamic(() => import('./topic/features/ConfigSwitcher'), {
10
+ loading: () => <SkeletonList />,
11
+ });
12
+
13
+ interface TopicSidebarProps {
14
+ mobile?: boolean;
15
+ }
16
+
17
+ const TopicSidebar = memo<TopicSidebarProps>(({ mobile }) => {
18
+ const Layout = mobile ? MobileLayout : DesktopLayout;
19
+
20
+ return (
21
+ <Layout>
22
+ <ConfigSwitcher />
23
+ <Topic />
24
+ </Layout>
25
+ );
26
+ });
27
+
28
+ TopicSidebar.displayName = 'TopicSidebar';
29
+
30
+ export default TopicSidebar;
@@ -0,0 +1,73 @@
1
+ import { Suspense, memo } from 'react';
2
+ import { Flexbox } from 'react-layout-kit';
3
+
4
+ import MainInterfaceTracker from '@/components/Analytics/MainInterfaceTracker';
5
+ import BrandTextLoading from '@/components/Loading/BrandTextLoading';
6
+ import MobileContentLayout from '@/components/server/MobileNavLayout';
7
+
8
+ import ChatHeaderDesktop from '../components/layout/Desktop/ChatHeader';
9
+ import Portal from '../components/layout/Desktop/Portal';
10
+ import TopicPanel from '../components/layout/Desktop/TopicPanel';
11
+ import ChatHeaderMobile from '../components/layout/Mobile/ChatHeader';
12
+ import TopicModal from '../components/layout/Mobile/TopicModal';
13
+ import ConversationArea from './ConversationArea';
14
+ import PortalPanel from './PortalPanel';
15
+ import TopicSidebar from './TopicSidebar';
16
+
17
+ interface WorkspaceLayoutProps {
18
+ mobile?: boolean;
19
+ }
20
+
21
+ const DesktopWorkspace = memo(() => (
22
+ <>
23
+ <ChatHeaderDesktop />
24
+ <Flexbox
25
+ height={'100%'}
26
+ horizontal
27
+ style={{ overflow: 'hidden', position: 'relative' }}
28
+ width={'100%'}
29
+ >
30
+ <Flexbox height={'100%'} style={{ overflow: 'hidden', position: 'relative' }} width={'100%'}>
31
+ <ConversationArea mobile={false} />
32
+ </Flexbox>
33
+ <Portal>
34
+ <Suspense fallback={<BrandTextLoading />}>
35
+ <PortalPanel mobile={false} />
36
+ </Suspense>
37
+ </Portal>
38
+ <TopicPanel>
39
+ <TopicSidebar mobile={false} />
40
+ </TopicPanel>
41
+ </Flexbox>
42
+ <MainInterfaceTracker />
43
+ </>
44
+ ));
45
+
46
+ DesktopWorkspace.displayName = 'DesktopWorkspace';
47
+
48
+ const MobileWorkspace = memo(() => (
49
+ <>
50
+ <MobileContentLayout header={<ChatHeaderMobile />} style={{ overflowY: 'hidden' }}>
51
+ <ConversationArea mobile />
52
+ </MobileContentLayout>
53
+ <TopicModal>
54
+ <TopicSidebar mobile />
55
+ </TopicModal>
56
+ <PortalPanel mobile />
57
+ <MainInterfaceTracker />
58
+ </>
59
+ ));
60
+
61
+ MobileWorkspace.displayName = 'MobileWorkspace';
62
+
63
+ const WorkspaceLayout = memo<WorkspaceLayoutProps>(({ mobile }) => {
64
+ if (mobile) {
65
+ return <MobileWorkspace />;
66
+ }
67
+
68
+ return <DesktopWorkspace />;
69
+ });
70
+
71
+ WorkspaceLayout.displayName = 'WorkspaceLayout';
72
+
73
+ export default WorkspaceLayout;
@@ -1,7 +1,7 @@
1
1
  import { createStyles } from 'antd-style';
2
2
  import React, { memo } from 'react';
3
3
 
4
- import SupervisorThinkingTag from '@/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/OrchestratorThinking';
4
+ import SupervisorThinkingTag from '@/app/[variants]/(main)/chat/components/conversation/features/ChatList/ChatItem/OrchestratorThinking';
5
5
  import { ChatItem } from '@/features/Conversation';
6
6
  import { useAgentStore } from '@/store/agent';
7
7
  import { agentChatConfigSelectors } from '@/store/agent/selectors';
@@ -1,5 +1,4 @@
1
1
  import ServerLayout from '@/components/server/ServerLayout';
2
-
3
2
  import Desktop from './_layout/Desktop';
4
3
  import Mobile from './_layout/Mobile';
5
4
  import { LayoutProps } from './_layout/type';
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+
3
+ import dynamic from 'next/dynamic';
4
+
5
+ import { BrandTextLoading } from '@/components/Loading';
6
+
7
+ const ChatRouter = dynamic(() => import('./ChatRouter'), {
8
+ loading: BrandTextLoading,
9
+ ssr: false,
10
+ });
11
+
12
+ export default ChatRouter;
@@ -3,7 +3,7 @@
3
3
  import { memo } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
- import ChatInput from '@/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput';
6
+ import ChatInput from '@/app/[variants]/(main)/chat/components/conversation/features/ChatInput';
7
7
  import { useChatGroupStore } from '@/store/chatGroup';
8
8
 
9
9
  import ThreadChatList from './ThreadChatList';
@@ -2,7 +2,7 @@ import isEqual from 'fast-deep-equal';
2
2
  import { useEffect } from 'react';
3
3
  import { useHotkeysContext } from 'react-hotkeys-hook';
4
4
 
5
- import { useSend } from '@/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend';
5
+ import { useSend } from '@/app/[variants]/(main)/chat/components/conversation/features/ChatInput/useSend';
6
6
  import { useClearCurrentMessages } from '@/features/ChatInput/ActionBar/Clear';
7
7
  import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
8
8
  import { useActionSWR } from '@/libs/swr';
@@ -1,11 +0,0 @@
1
- import ServerLayout from '@/components/server/ServerLayout';
2
-
3
- import Desktop from './_layout/Desktop';
4
- import Mobile from './_layout/Mobile';
5
- import { LayoutProps } from './_layout/type';
6
-
7
- const Layout = ServerLayout<LayoutProps>({ Desktop, Mobile });
8
-
9
- Layout.displayName = 'ChatConversationLayout';
10
-
11
- export default Layout;