@lobehub/chat 0.83.10 → 0.84.0-beta.1

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 (152) hide show
  1. package/.dockerignore +10 -0
  2. package/.github/workflows/release.yml +3 -0
  3. package/.releaserc.js +14 -1
  4. package/CHANGELOG.md +5 -17
  5. package/Dockerfile +46 -0
  6. package/next.config.mjs +3 -0
  7. package/package.json +4 -2
  8. package/src/app/chat/(desktop)/features/{ChatHeader.tsx → ChatHeader/Desktop.tsx} +2 -2
  9. package/src/app/chat/(desktop)/features/ChatHeader/index.tsx +14 -0
  10. package/src/app/chat/(desktop)/features/{ChatInput.tsx → ChatInput/Desktop.tsx} +7 -5
  11. package/src/app/chat/(desktop)/features/ChatInput/index.tsx +22 -0
  12. package/src/app/chat/(desktop)/features/{SessionHeader.tsx → SessionHeader/Desktop.tsx} +1 -1
  13. package/src/app/chat/(desktop)/features/SessionHeader/index.tsx +14 -0
  14. package/src/app/chat/(desktop)/features/{SessionList.tsx → SessionList/Desktop.tsx} +4 -5
  15. package/src/app/chat/(desktop)/features/SessionList/index.tsx +20 -0
  16. package/src/app/chat/(desktop)/features/{SideBar.tsx → SideBar/Desktop.tsx} +4 -5
  17. package/src/app/chat/(desktop)/features/SideBar/index.tsx +20 -0
  18. package/src/app/chat/(desktop)/index.tsx +8 -14
  19. package/src/app/chat/(desktop)/{layout.desktop.tsx → layout/Desktop.tsx} +8 -7
  20. package/src/app/chat/(desktop)/layout/index.tsx +25 -0
  21. package/src/app/chat/(mobile)/features/ChatHeader.tsx +1 -54
  22. package/src/app/chat/(mobile)/features/ChatInput.tsx +8 -28
  23. package/src/app/chat/(mobile)/features/SessionList.tsx +8 -13
  24. package/src/app/chat/(mobile)/features/Topics.tsx +12 -0
  25. package/src/app/chat/(mobile)/index.tsx +5 -3
  26. package/src/app/chat/(mobile)/layout.tsx +15 -0
  27. package/src/app/chat/(mobile)/mobile/page.tsx +20 -2
  28. package/src/app/chat/components/ChatHeader/Mobile.tsx +54 -0
  29. package/src/app/chat/{features → components}/ChatHeader/ShareButton/Preview.tsx +9 -25
  30. package/src/app/chat/{features → components}/ChatHeader/ShareButton/style.ts +7 -7
  31. package/src/app/chat/components/ChatInput/Mobile.tsx +35 -0
  32. package/src/app/chat/{features/ChatInputContent → components/ChatInput}/index.tsx +1 -3
  33. package/src/app/chat/{(mobile)/features/TopicList.tsx → components/Inspector/Mobile.tsx} +4 -6
  34. package/src/app/chat/{features/TopicListContent → components/Inspector}/index.tsx +1 -3
  35. package/src/app/chat/{features/SessionListContent → components/SessionList}/Inbox/index.tsx +5 -7
  36. package/src/app/chat/components/SessionList/Mobile.tsx +16 -0
  37. package/src/app/chat/{features/SessionListContent → components/SessionList}/index.tsx +1 -3
  38. package/src/app/chat/layout.tsx +15 -0
  39. package/src/app/chat/page.tsx +1 -3
  40. package/src/app/chat/settings/(desktop)/layout.desktop.tsx +15 -10
  41. package/src/app/chat/settings/(mobile)/layout.mobile.tsx +8 -4
  42. package/src/app/chat/settings/layout.tsx +14 -0
  43. package/src/app/chat/settings/page.tsx +33 -9
  44. package/src/app/market/(desktop)/{features/AgentDetail.tsx → AgentDetail/Desktop.tsx} +3 -5
  45. package/src/app/market/(desktop)/AgentDetail/index.tsx +16 -0
  46. package/src/app/market/(desktop)/Header/index.tsx +13 -0
  47. package/src/app/market/(desktop)/{layout.desktop.tsx → layout/Desktop.tsx} +5 -5
  48. package/src/app/market/(desktop)/layout/index.tsx +17 -0
  49. package/src/app/market/(mobile)/AgentDetail.tsx +12 -0
  50. package/src/app/market/(mobile)/layout.mobile.tsx +5 -5
  51. package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/AgentInfo/Header.tsx +0 -1
  52. package/src/app/market/{(mobile)/features/AgentDetail.tsx → components/AgentDetail/Mobile.tsx} +4 -6
  53. package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/index.tsx +1 -3
  54. package/src/app/market/features/TagList/index.tsx +1 -2
  55. package/src/app/market/layout.tsx +13 -0
  56. package/src/app/market/page.tsx +5 -8
  57. package/src/app/settings/agent/page.tsx +31 -2
  58. package/src/app/settings/common/page.tsx +14 -2
  59. package/src/app/settings/{(desktop)/features/Header.tsx → features/Header/Desktop.tsx} +2 -2
  60. package/src/app/settings/{(mobile)/features/Header/index.tsx → features/Header/Mobile.tsx} +0 -1
  61. package/src/app/settings/features/Header/index.tsx +14 -0
  62. package/src/app/settings/{(desktop)/layout.desktop.tsx → layout.desktop/Desktop.tsx} +9 -10
  63. package/src/app/settings/layout.desktop/index.tsx +32 -0
  64. package/src/app/settings/layout.mobile.tsx +16 -0
  65. package/src/app/settings/layout.tsx +15 -0
  66. package/src/app/settings/llm/page.tsx +14 -2
  67. package/src/app/settings/{(mobile)/features → mobile}/ExtraList.tsx +1 -1
  68. package/src/app/settings/{(mobile)/mobile → mobile}/index.tsx +7 -7
  69. package/src/app/settings/mobile/page.tsx +7 -0
  70. package/src/app/settings/page.tsx +1 -14
  71. package/src/app/welcome/{(desktop)/layout.desktop.tsx → DesktopLayout/Desktop.tsx} +4 -4
  72. package/src/app/welcome/DesktopLayout/index.tsx +15 -0
  73. package/src/app/welcome/MobileLayout.tsx +23 -0
  74. package/src/app/welcome/features/Banner/Hero.tsx +3 -2
  75. package/src/app/welcome/features/Banner/index.tsx +31 -34
  76. package/src/app/welcome/features/Banner/style.ts +1 -10
  77. package/src/app/welcome/layout.tsx +22 -0
  78. package/src/app/welcome/page.tsx +7 -9
  79. package/src/{layout/ResponsiveLayout.server.tsx → components/ResponsiveLayout.tsx} +3 -4
  80. package/src/features/MobileTabBar/index.tsx +1 -1
  81. package/src/features/SideBar/BottomActions.tsx +1 -1
  82. package/src/layout/{AppLayout.desktop.tsx → AppLayout.tsx} +2 -2
  83. package/src/layout/{AppLayout.mobile.tsx → AppMobileLayout.tsx} +2 -2
  84. package/src/layout/GlobalLayout/StoreHydration.tsx +1 -15
  85. package/src/store/session/slices/session/initialState.ts +2 -2
  86. package/src/app/chat/(desktop)/layout.responsive.tsx +0 -12
  87. package/src/app/chat/(mobile)/layout.mobile.tsx +0 -17
  88. package/src/app/chat/(mobile)/mobile/index.tsx +0 -19
  89. package/src/app/chat/(mobile)/mobile/layout.mobile.tsx +0 -11
  90. package/src/app/chat/settings/(desktop)/index.tsx +0 -14
  91. package/src/app/chat/settings/(desktop)/layout.responsive.tsx +0 -12
  92. package/src/app/chat/settings/(mobile)/index.tsx +0 -14
  93. package/src/app/chat/settings/features/EditPage.tsx +0 -38
  94. package/src/app/market/(desktop)/index.tsx +0 -12
  95. package/src/app/market/(desktop)/layout.responsive.tsx +0 -16
  96. package/src/app/market/(mobile)/index.tsx +0 -12
  97. package/src/app/settings/(desktop)/index.tsx +0 -17
  98. package/src/app/settings/(desktop)/layout.responsive.tsx +0 -14
  99. package/src/app/settings/(mobile)/features/Header/Home.tsx +0 -8
  100. package/src/app/settings/(mobile)/index.tsx +0 -3
  101. package/src/app/settings/(mobile)/layout.mobile.tsx +0 -19
  102. package/src/app/settings/(mobile)/mobile/layout.mobile.tsx +0 -14
  103. package/src/app/settings/agent/Agent.tsx +0 -30
  104. package/src/app/settings/agent/index.tsx +0 -23
  105. package/src/app/settings/agent/layout.tsx +0 -1
  106. package/src/app/settings/common/index.tsx +0 -23
  107. package/src/app/settings/common/layout.tsx +0 -1
  108. package/src/app/settings/layout.server.tsx +0 -12
  109. package/src/app/settings/llm/index.tsx +0 -23
  110. package/src/app/settings/llm/layout.tsx +0 -1
  111. package/src/app/welcome/(desktop)/features/Showcase.tsx +0 -23
  112. package/src/app/welcome/(desktop)/index.tsx +0 -19
  113. package/src/app/welcome/(desktop)/layout.responsive.tsx +0 -14
  114. package/src/app/welcome/(mobile)/features/Header.tsx +0 -6
  115. package/src/app/welcome/(mobile)/features/Showcase.tsx +0 -16
  116. package/src/app/welcome/(mobile)/index.tsx +0 -10
  117. package/src/app/welcome/(mobile)/layout.mobile.tsx +0 -20
  118. package/src/components/ResponsiveIndex.tsx +0 -17
  119. package/src/layout/ResponsiveLayout.client.tsx +0 -18
  120. /package/src/app/chat/{features → components}/ChatHeader/PluginTag/PluginStatus.tsx +0 -0
  121. /package/src/app/chat/{features → components}/ChatHeader/PluginTag/index.tsx +0 -0
  122. /package/src/app/chat/{features → components}/ChatHeader/ShareButton/Inner.tsx +0 -0
  123. /package/src/app/chat/{features → components}/ChatHeader/ShareButton/index.tsx +0 -0
  124. /package/src/app/chat/{features/ChatInputContent → components/ChatInput}/ActionBar/ActionLeft.tsx +0 -0
  125. /package/src/app/chat/{features/ChatInputContent → components/ChatInput}/ActionBar/ActionRight.tsx +0 -0
  126. /package/src/app/chat/{features/ChatInputContent → components/ChatInput}/ActionBar/Token.tsx +0 -0
  127. /package/src/app/chat/{features/ChatInputContent → components/ChatInput}/Footer/SaveTopic.tsx +0 -0
  128. /package/src/app/chat/{features/ChatInputContent → components/ChatInput}/Footer/index.tsx +0 -0
  129. /package/src/app/chat/{features/TopicListContent → components/Inspector}/SystemRole/Header.tsx +0 -0
  130. /package/src/app/chat/{features/TopicListContent → components/Inspector}/SystemRole/index.tsx +0 -0
  131. /package/src/app/chat/{features/TopicListContent → components/Inspector}/SystemRole/style.ts +0 -0
  132. /package/src/app/chat/{features/TopicListContent → components/Inspector}/Topic/DefaultContent.tsx +0 -0
  133. /package/src/app/chat/{features/TopicListContent → components/Inspector}/Topic/SkeletonList.tsx +0 -0
  134. /package/src/app/chat/{features/TopicListContent → components/Inspector}/Topic/TopicContent.tsx +0 -0
  135. /package/src/app/chat/{features/TopicListContent → components/Inspector}/Topic/TopicItem.tsx +0 -0
  136. /package/src/app/chat/{features/TopicListContent → components/Inspector}/Topic/index.tsx +0 -0
  137. /package/src/app/chat/{features/TopicListContent → components/Inspector}/TopicSearchBar/index.tsx +0 -0
  138. /package/src/app/chat/{features/SessionListContent → components/SessionList}/CollapseGroup/index.tsx +0 -0
  139. /package/src/app/chat/{features/SessionListContent → components/SessionList}/List/AddButton.tsx +0 -0
  140. /package/src/app/chat/{features/SessionListContent → components/SessionList}/List/Item/Actions.tsx +0 -0
  141. /package/src/app/chat/{features/SessionListContent → components/SessionList}/List/Item/index.tsx +0 -0
  142. /package/src/app/chat/{features/SessionListContent → components/SessionList}/List/SkeletonList.tsx +0 -0
  143. /package/src/app/chat/{features/SessionListContent → components/SessionList}/List/index.tsx +0 -0
  144. /package/src/app/chat/features/{PageTitle/index.tsx → PageTitle.tsx} +0 -0
  145. /package/src/app/market/(desktop)/{features/Header.tsx → Header/Desktop.tsx} +0 -0
  146. /package/src/app/market/(mobile)/{features/Header.tsx → Header.tsx} +0 -0
  147. /package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/AgentInfo/Comment.tsx +0 -0
  148. /package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/AgentInfo/Loading.tsx +0 -0
  149. /package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/AgentInfo/TokenTag.tsx +0 -0
  150. /package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/AgentInfo/index.tsx +0 -0
  151. /package/src/app/market/{features/AgentDetailContent → components/AgentDetail}/AgentInfo/style.ts +0 -0
  152. /package/src/app/welcome/{(desktop)/features/Footer.tsx → features/Footer/index.tsx} +0 -0
@@ -0,0 +1,15 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, memo } from 'react';
4
+
5
+ import { useEffectAfterSessionHydrated } from '@/store/session';
6
+
7
+ const ChatMobileLayout = memo<PropsWithChildren>(({ children }) => {
8
+ useEffectAfterSessionHydrated((store) => {
9
+ store.setState({ isMobile: true });
10
+ }, []);
11
+
12
+ return children;
13
+ });
14
+
15
+ export default ChatMobileLayout;
@@ -1,3 +1,21 @@
1
- import Index from './index';
1
+ 'use client';
2
2
 
3
- export default () => <Index />;
3
+ import { memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import AppMobileLayout from '@/layout/AppMobileLayout';
7
+
8
+ import Conversation from '../../features/Conversation';
9
+ import Header from '../features/ChatHeader';
10
+ import ChatInput from '../features/ChatInput';
11
+ import Topics from '../features/Topics';
12
+
13
+ const Chat = memo(() => (
14
+ <AppMobileLayout navBar={<Header />}>
15
+ <Flexbox height={'calc(100vh - 44px)'} horizontal>
16
+ <Conversation chatInput={<ChatInput />} mobile />
17
+ <Topics />
18
+ </Flexbox>
19
+ </AppMobileLayout>
20
+ ));
21
+ export default Chat;
@@ -0,0 +1,54 @@
1
+ import { ActionIcon, MobileNavBar, MobileNavBarTitle } from '@lobehub/ui';
2
+ import { LayoutList, Settings } from 'lucide-react';
3
+ import { useRouter } from 'next/navigation';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { MOBILE_HEADER_ICON_SIZE } from '@/const/layoutTokens';
8
+ import { useGlobalStore } from '@/store/global';
9
+ import { useSessionStore } from '@/store/session';
10
+ import { agentSelectors, sessionSelectors } from '@/store/session/selectors';
11
+ import { pathString } from '@/utils/url';
12
+
13
+ import ShareButton from './ShareButton';
14
+
15
+ const MobileHeader = memo(() => {
16
+ const { t } = useTranslation('common');
17
+ const router = useRouter();
18
+
19
+ const [isInbox, title] = useSessionStore((s) => [
20
+ sessionSelectors.isInboxSession(s),
21
+ agentSelectors.currentAgentTitle(s),
22
+ ]);
23
+
24
+ const [toggleConfig] = useGlobalStore((s) => [s.toggleMobileTopic]);
25
+
26
+ const displayTitle = isInbox ? t('inbox.title') : title;
27
+
28
+ return (
29
+ <MobileNavBar
30
+ center={<MobileNavBarTitle title={displayTitle} />}
31
+ onBackClick={() => router.push('/chat')}
32
+ right={
33
+ <>
34
+ <ShareButton />
35
+ <ActionIcon
36
+ icon={LayoutList}
37
+ onClick={() => toggleConfig()}
38
+ size={MOBILE_HEADER_ICON_SIZE}
39
+ />
40
+ {!isInbox && (
41
+ <ActionIcon
42
+ icon={Settings}
43
+ onClick={() => router.push(pathString('/chat/settings', { hash: location.hash }))}
44
+ size={MOBILE_HEADER_ICON_SIZE}
45
+ />
46
+ )}
47
+ </>
48
+ }
49
+ showBackButton
50
+ />
51
+ );
52
+ });
53
+
54
+ export default MobileHeader;
@@ -2,25 +2,24 @@ import { SiOpenai } from '@icons-pack/react-simple-icons';
2
2
  import { Avatar, ChatHeaderTitle, Logo, Markdown, Tag } from '@lobehub/ui';
3
3
  import { Button, SegmentedProps } from 'antd';
4
4
  import dayjs from 'dayjs';
5
- import { domToJpeg, domToPng, domToSvg, domToWebp } from 'modern-screenshot';
5
+ import { toJpeg, toPng, toSvg } from 'html-to-image';
6
6
  import { memo, useCallback, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { Flexbox } from 'react-layout-kit';
9
9
  import ChatList from 'src/app/chat/features/Conversation/ChatList';
10
10
 
11
- import pkg from '@/../package.json';
11
+ import PluginTag from '@/app/chat/components/ChatHeader/PluginTag';
12
12
  import { useSessionStore } from '@/store/session';
13
13
  import { agentSelectors } from '@/store/session/slices/agentConfig';
14
14
  import { sessionSelectors } from '@/store/session/slices/session/selectors';
15
15
 
16
- import PluginTag from '../../ChatHeader/PluginTag';
16
+ import pkg from '../../../../../../package.json';
17
17
  import { useStyles } from './style';
18
18
 
19
19
  export enum ImageType {
20
20
  JPG = 'jpg',
21
21
  PNG = 'png',
22
22
  SVG = 'svg',
23
- WEBP = 'webp',
24
23
  }
25
24
 
26
25
  export const imageTypeOptions: SegmentedProps['options'] = [
@@ -36,10 +35,6 @@ export const imageTypeOptions: SegmentedProps['options'] = [
36
35
  label: 'SVG',
37
36
  value: ImageType.SVG,
38
37
  },
39
- {
40
- label: 'WEBP',
41
- value: ImageType.WEBP,
42
- },
43
38
  ];
44
39
 
45
40
  interface PreviewProps {
@@ -74,37 +69,26 @@ const Preview = memo<PreviewProps>(({ withSystemRole, imageType, withBackground,
74
69
  let screenshotFn: any;
75
70
  switch (imageType) {
76
71
  case ImageType.JPG: {
77
- screenshotFn = domToJpeg;
72
+ screenshotFn = toJpeg;
78
73
  break;
79
74
  }
80
75
  case ImageType.PNG: {
81
- screenshotFn = domToPng;
76
+ screenshotFn = toPng;
82
77
  break;
83
78
  }
84
79
  case ImageType.SVG: {
85
- screenshotFn = domToSvg;
86
- break;
87
- }
88
- case ImageType.WEBP: {
89
- screenshotFn = domToWebp;
80
+ screenshotFn = toSvg;
90
81
  break;
91
82
  }
92
83
  }
93
-
94
- const dataUrl = await screenshotFn(document.querySelector('#preview') as HTMLDivElement, {
95
- features: {
96
- // 不启用移除控制符,否则会导致 safari emoji 报错
97
- removeControlCharacter: false,
98
- },
99
- scale: 2,
100
- });
84
+ const dataUrl = await screenshotFn(document.querySelector('#preview') as HTMLDivElement);
101
85
  const link = document.createElement('a');
102
86
  link.download = `LobeChat_${title}_${dayjs().format('YYYY-MM-DD')}.${imageType}`;
103
87
  link.href = dataUrl;
104
88
  link.click();
105
89
  setLoading(false);
106
- } catch (error) {
107
- console.error('Failed to download image', error);
90
+ } catch {
91
+ console.error('Failed to download image');
108
92
  setLoading(false);
109
93
  }
110
94
  }, [imageType, title]);
@@ -1,22 +1,22 @@
1
1
  import { createStyles } from 'antd-style';
2
+ import { rgba } from 'polished';
2
3
 
3
4
  export const useStyles = createStyles(({ css, token, stylish, cx }, withBackground: boolean) => ({
4
5
  background: css`
5
6
  padding: 24px;
6
-
7
- background-color: ${token.colorBgLayout};
8
- background-image: url('/images/screenshot_background.webp');
9
- background-position: center;
10
- background-size: 120% 120%;
7
+ background: url('/images/screenshot_background.webp') no-repeat;
8
+ background-size: 100% 100%;
11
9
  `,
12
10
  container: cx(
13
11
  withBackground &&
14
12
  css`
15
13
  overflow: hidden;
16
- border: 2px solid ${token.colorBorder};
14
+ border: 1px solid ${rgba(token.colorText, 0.15)};
17
15
  border-radius: ${token.borderRadiusLG}px;
16
+ box-shadow:
17
+ 0 8px 16px -4px rgba(0, 0, 0, 75%),
18
+ 0 8px 24px -4px rgba(0, 0, 0, 75%);
18
19
  `,
19
-
20
20
  css`
21
21
  background: ${token.colorBgLayout};
22
22
  `,
@@ -0,0 +1,35 @@
1
+ import { createStyles } from 'antd-style';
2
+ import { ReactNode, memo } from 'react';
3
+
4
+ import SafeSpacing from '@/components/SafeSpacing';
5
+ import { CHAT_TEXTAREA_HEIGHT_MOBILE } from '@/const/layoutTokens';
6
+
7
+ const useStyles = createStyles(
8
+ ({ css, token }) => css`
9
+ position: fixed;
10
+ right: 0;
11
+ bottom: 0;
12
+ left: 0;
13
+
14
+ width: 100vw;
15
+
16
+ background: ${token.colorBgLayout};
17
+ `,
18
+ );
19
+
20
+ interface ChatInputMobileLayoutProps {
21
+ children: ReactNode;
22
+ expand?: boolean;
23
+ }
24
+
25
+ const ChatInputMobileLayout = memo<ChatInputMobileLayoutProps>(({ children }) => {
26
+ const { styles } = useStyles();
27
+ return (
28
+ <>
29
+ <SafeSpacing height={CHAT_TEXTAREA_HEIGHT_MOBILE} mobile position={'bottom'} />
30
+ <div className={styles}>{children}</div>
31
+ </>
32
+ );
33
+ });
34
+
35
+ export default ChatInputMobileLayout;
@@ -19,7 +19,7 @@ interface ChatContentProps {
19
19
  onExpandChange?: (expand: boolean) => void;
20
20
  }
21
21
 
22
- const ChatInputContent = memo<ChatContentProps>(
22
+ export const ChatInputContent = memo<ChatContentProps>(
23
23
  ({ expand, onExpandChange, mobile: defaultMobile }) => {
24
24
  const { t } = useTranslation('common');
25
25
 
@@ -63,5 +63,3 @@ const ChatInputContent = memo<ChatContentProps>(
63
63
  );
64
64
  },
65
65
  );
66
-
67
- export default ChatInputContent;
@@ -1,12 +1,10 @@
1
1
  import { Modal } from '@lobehub/ui';
2
- import { memo } from 'react';
2
+ import { PropsWithChildren, memo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
5
5
  import { useGlobalStore } from '@/store/global';
6
6
 
7
- import TopicListContent from '../../features/TopicListContent';
8
-
9
- const Topics = memo(() => {
7
+ const Mobile = memo<PropsWithChildren>(({ children }) => {
10
8
  const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
11
9
  s.preference.mobileShowTopic,
12
10
  s.toggleMobileTopic,
@@ -16,9 +14,9 @@ const Topics = memo(() => {
16
14
 
17
15
  return (
18
16
  <Modal onCancel={() => toggleConfig(false)} open={showAgentSettings} title={t('topic.title')}>
19
- <TopicListContent />
17
+ {children}
20
18
  </Modal>
21
19
  );
22
20
  });
23
21
 
24
- export default Topics;
22
+ export default Mobile;
@@ -3,7 +3,7 @@ import { Flexbox } from 'react-layout-kit';
3
3
  import { Topic } from './Topic';
4
4
  import TopicSearchBar from './TopicSearchBar';
5
5
 
6
- const TopicListContent = () => {
6
+ export const InspectorContent = () => {
7
7
  return (
8
8
  <Flexbox height={'100%'} style={{ overflow: 'hidden' }}>
9
9
  <Flexbox padding={16}>
@@ -15,5 +15,3 @@ const TopicListContent = () => {
15
15
  </Flexbox>
16
16
  );
17
17
  };
18
-
19
- export default TopicListContent;
@@ -1,6 +1,5 @@
1
1
  import { Avatar, List } from '@lobehub/ui';
2
2
  import { useHover } from 'ahooks';
3
- import { useResponsive } from 'antd-style';
4
3
  import Link from 'next/link';
5
4
  import { memo, useMemo, useRef } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
@@ -16,10 +15,10 @@ const Inbox = memo(() => {
16
15
  const ref = useRef(null);
17
16
  const isHovering = useHover(ref);
18
17
  const { t } = useTranslation('common');
19
- const { mobile } = useResponsive();
20
- const [activeId, activeSession, switchSession] = useSessionStore((s) => [
18
+
19
+ const [mobile, activeId, switchSession] = useSessionStore((s) => [
20
+ s.isMobile,
21
21
  s.activeId,
22
- s.activeSession,
23
22
  s.switchSession,
24
23
  ]);
25
24
 
@@ -40,12 +39,11 @@ const Inbox = memo(() => {
40
39
  href={SESSION_CHAT_URL(INBOX_SESSION_ID, mobile)}
41
40
  onClick={(e) => {
42
41
  e.preventDefault();
43
- if (mobile) switchSession(INBOX_SESSION_ID);
44
- else activeSession(INBOX_SESSION_ID);
42
+ switchSession(INBOX_SESSION_ID);
45
43
  }}
46
44
  >
47
45
  <Item
48
- active={mobile ? false : activeId === INBOX_SESSION_ID}
46
+ active={activeId === INBOX_SESSION_ID}
49
47
  avatar={avatarRender}
50
48
  ref={ref}
51
49
  style={{ alignItems: 'center' }}
@@ -0,0 +1,16 @@
1
+ import { ReactNode, memo } from 'react';
2
+
3
+ import SessionSearchBar from '../../features/SessionSearchBar';
4
+
5
+ const Sessions = memo<{ children: ReactNode }>(({ children }) => {
6
+ return (
7
+ <>
8
+ <div style={{ padding: '8px 16px' }}>
9
+ <SessionSearchBar />
10
+ </div>
11
+ {children}
12
+ </>
13
+ );
14
+ });
15
+
16
+ export default Sessions;
@@ -6,7 +6,7 @@ import CollapseGroup from './CollapseGroup';
6
6
  import Inbox from './Inbox';
7
7
  import SessionList from './List';
8
8
 
9
- const SessionListContent = memo(() => {
9
+ export const SessionListContent = memo(() => {
10
10
  const { t } = useTranslation('common');
11
11
  const items: CollapseProps['items'] = useMemo(
12
12
  () => [
@@ -26,5 +26,3 @@ const SessionListContent = memo(() => {
26
26
  </>
27
27
  );
28
28
  });
29
-
30
- export default SessionListContent;
@@ -0,0 +1,15 @@
1
+ import { PropsWithChildren } from 'react';
2
+
3
+ import ResponsiveLayout from '@/components/ResponsiveLayout';
4
+ import { isMobileDevice } from '@/utils/responsive';
5
+
6
+ import Desktop from './(desktop)/layout';
7
+ import Mobile from './(mobile)/layout';
8
+
9
+ const Layout = ({ children }: PropsWithChildren) => (
10
+ <ResponsiveLayout Desktop={Desktop} Mobile={Mobile} isMobile={isMobileDevice}>
11
+ {children}
12
+ </ResponsiveLayout>
13
+ );
14
+
15
+ export default Layout;
@@ -6,9 +6,7 @@ import MobilePage from './(mobile)';
6
6
  const Page = () => {
7
7
  const mobile = isMobileDevice();
8
8
 
9
- const Page = mobile ? MobilePage : DesktopPage;
10
-
11
- return <Page />;
9
+ return mobile ? <MobilePage /> : <DesktopPage />;
12
10
  };
13
11
 
14
12
  export default Page;
@@ -1,18 +1,23 @@
1
+ 'use client';
2
+
1
3
  import { PropsWithChildren, memo } from 'react';
2
4
  import { Flexbox } from 'react-layout-kit';
3
5
 
4
6
  import SafeSpacing from '@/components/SafeSpacing';
5
7
  import { HEADER_HEIGHT } from '@/const/layoutTokens';
6
8
 
7
- import Layout from '../../(desktop)/layout.desktop';
8
9
  import Header from './Header';
9
10
 
10
- export default memo(({ children }: PropsWithChildren) => (
11
- <Layout>
12
- <Header />
13
- <Flexbox align={'center'} flex={1} gap={16} padding={24} style={{ overflow: 'auto' }}>
14
- <SafeSpacing height={HEADER_HEIGHT - 16} />
15
- {children}
16
- </Flexbox>
17
- </Layout>
18
- ));
11
+ const DesktopLayout = memo<PropsWithChildren>(({ children }) => {
12
+ return (
13
+ <>
14
+ <Header />
15
+ <Flexbox align={'center'} flex={1} gap={16} padding={24} style={{ overflow: 'auto' }}>
16
+ <SafeSpacing height={HEADER_HEIGHT - 16} />
17
+ {children}
18
+ </Flexbox>
19
+ </>
20
+ );
21
+ });
22
+
23
+ export default DesktopLayout;
@@ -1,9 +1,13 @@
1
+ 'use client';
2
+
1
3
  import { PropsWithChildren, memo } from 'react';
2
4
 
3
- import AppLayoutMobile from '@/layout/AppLayout.mobile';
5
+ import AppMobileLayout from '@/layout/AppMobileLayout';
4
6
 
5
7
  import Header from './Header';
6
8
 
7
- export default memo(({ children }: PropsWithChildren) => (
8
- <AppLayoutMobile navBar={<Header />}>{children}</AppLayoutMobile>
9
- ));
9
+ const MobileLayout = memo<PropsWithChildren>(({ children }) => {
10
+ return <AppMobileLayout navBar={<Header />}>{children}</AppMobileLayout>;
11
+ });
12
+
13
+ export default MobileLayout;
@@ -0,0 +1,14 @@
1
+ import { PropsWithChildren } from 'react';
2
+
3
+ import { isMobileDevice } from '@/utils/responsive';
4
+
5
+ import Desktop from './(desktop)/layout.desktop';
6
+ import Mobile from './(mobile)/layout.mobile';
7
+
8
+ const Layout = ({ children }: PropsWithChildren) => {
9
+ const mobile = isMobileDevice();
10
+
11
+ return mobile ? <Mobile>{children}</Mobile> : <Desktop>{children}</Desktop>;
12
+ };
13
+
14
+ export default Layout;
@@ -1,14 +1,38 @@
1
- import { isMobileDevice } from '@/utils/responsive';
1
+ 'use client';
2
2
 
3
- import DesktopPage from './(desktop)';
4
- import MobilePage from './(mobile)';
3
+ import isEqual from 'fast-deep-equal';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
5
6
 
6
- const Page = () => {
7
- const mobile = isMobileDevice();
7
+ import PageTitle from '@/components/PageTitle';
8
+ import AgentSetting from '@/features/AgentSetting';
9
+ import { useSessionStore } from '@/store/session';
10
+ import { agentSelectors } from '@/store/session/selectors';
11
+ import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
8
12
 
9
- const Page = mobile ? MobilePage : DesktopPage;
13
+ const EditPage = memo(() => {
14
+ const { t } = useTranslation('setting');
15
+ const config = useSessionStore(agentSelectors.currentAgentConfig, isEqual);
16
+ const meta = useSessionStore(agentSelectors.currentAgentMeta, isEqual);
17
+ const [updateAgentConfig, updateAgentMeta, title] = useSessionStore((s) => [
18
+ s.updateAgentConfig,
19
+ s.updateAgentMeta,
20
+ agentSelectors.currentAgentTitle(s),
21
+ ]);
10
22
 
11
- return <Page />;
12
- };
23
+ const pageTitle = genSiteHeadTitle(t('header.sessionWithName', { name: title }));
13
24
 
14
- export default Page;
25
+ return (
26
+ <>
27
+ <PageTitle title={pageTitle} />
28
+ <AgentSetting
29
+ config={config}
30
+ meta={meta}
31
+ onConfigChange={updateAgentConfig}
32
+ onMetaChange={updateAgentMeta}
33
+ />
34
+ </>
35
+ );
36
+ });
37
+
38
+ export default EditPage;
@@ -1,13 +1,11 @@
1
1
  import { DraggablePanel, DraggablePanelBody, DraggablePanelContainer } from '@lobehub/ui';
2
2
  import { createStyles } from 'antd-style';
3
- import { memo, useState } from 'react';
3
+ import { ReactNode, memo, useState } from 'react';
4
4
 
5
5
  import SafeSpacing from '@/components/SafeSpacing';
6
6
  import { MARKET_SIDEBAR_WIDTH } from '@/const/layoutTokens';
7
7
  import { agentMarketSelectors, useMarketStore } from '@/store/market';
8
8
 
9
- import AgentDetailContent from '../../features/AgentDetailContent';
10
-
11
9
  const useStyles = createStyles(({ css, token, stylish }) => ({
12
10
  content: css`
13
11
  display: flex;
@@ -22,7 +20,7 @@ const useStyles = createStyles(({ css, token, stylish }) => ({
22
20
  noScrollbar: stylish.noScrollbar,
23
21
  }));
24
22
 
25
- const SideBar = memo(() => {
23
+ const SideBar = memo<{ children?: ReactNode }>(({ children }) => {
26
24
  const { styles } = useStyles();
27
25
  const [tempId, setTempId] = useState<string>('');
28
26
  const [showAgentSidebar, deactivateAgent, activateAgent] = useMarketStore((s) => [
@@ -62,7 +60,7 @@ const SideBar = memo(() => {
62
60
  className={styles.noScrollbar}
63
61
  style={{ padding: 0, position: 'relative' }}
64
62
  >
65
- <AgentDetailContent />
63
+ {children}
66
64
  </DraggablePanelBody>
67
65
  </DraggablePanelContainer>
68
66
  </DraggablePanel>
@@ -0,0 +1,16 @@
1
+ import { memo } from 'react';
2
+
3
+ import Mobile from '@/app/market/components/AgentDetail/Mobile';
4
+ import ResponsiveLayout from '@/components/ResponsiveLayout';
5
+ import { useIsMobile } from '@/hooks/useIsMobile';
6
+
7
+ import { AgentDetailContent } from '../../components/AgentDetail';
8
+ import Desktop from './Desktop';
9
+
10
+ const AgentDetail = memo(() => (
11
+ <ResponsiveLayout Desktop={Desktop} Mobile={Mobile} isMobile={useIsMobile}>
12
+ <AgentDetailContent />
13
+ </ResponsiveLayout>
14
+ ));
15
+
16
+ export default AgentDetail;
@@ -0,0 +1,13 @@
1
+ import { memo } from 'react';
2
+
3
+ import ResponsiveLayout from '@/components/ResponsiveLayout';
4
+ import { useIsMobile } from '@/hooks/useIsMobile';
5
+
6
+ import Mobile from '../../(mobile)/Header';
7
+ import Desktop from './Desktop';
8
+
9
+ const Header = memo(() => (
10
+ <ResponsiveLayout Desktop={Desktop} Mobile={Mobile} isMobile={useIsMobile} />
11
+ ));
12
+
13
+ export default Header;
@@ -5,12 +5,12 @@ import { Center, Flexbox } from 'react-layout-kit';
5
5
 
6
6
  import SafeSpacing from '@/components/SafeSpacing';
7
7
  import { MAX_WIDTH } from '@/const/layoutTokens';
8
- import AppLayoutDesktop from '@/layout/AppLayout.desktop';
9
8
  import { useSwitchSideBarOnInit } from '@/store/global';
10
9
  import { SidebarTabKey } from '@/store/global/initialState';
11
10
 
12
- import SideBar from './features/AgentDetail';
13
- import Header from './features/Header';
11
+ import AppLayout from '../../../../layout/AppLayout';
12
+ import SideBar from '../AgentDetail';
13
+ import Header from '../Header';
14
14
 
15
15
  const useStyles = createStyles(({ css }) => ({
16
16
  background: css`
@@ -31,7 +31,7 @@ const MarketLayout = memo<PropsWithChildren>(({ children }) => {
31
31
  useSwitchSideBarOnInit(SidebarTabKey.Market);
32
32
 
33
33
  return (
34
- <AppLayoutDesktop>
34
+ <AppLayout>
35
35
  <Flexbox
36
36
  flex={1}
37
37
  height={'100vh'}
@@ -59,7 +59,7 @@ const MarketLayout = memo<PropsWithChildren>(({ children }) => {
59
59
  <SideBar />
60
60
  </Flexbox>
61
61
  </Flexbox>
62
- </AppLayoutDesktop>
62
+ </AppLayout>
63
63
  );
64
64
  });
65
65
 
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren } from 'react';
4
+
5
+ import ResponsiveLayout from '@/components/ResponsiveLayout';
6
+ import { useIsMobile } from '@/hooks/useIsMobile';
7
+
8
+ import Mobile from '../../(mobile)/layout.mobile';
9
+ import Desktop from './Desktop';
10
+
11
+ const Market = ({ children }: PropsWithChildren) => (
12
+ <ResponsiveLayout Desktop={Desktop} Mobile={Mobile} isMobile={useIsMobile}>
13
+ {children}
14
+ </ResponsiveLayout>
15
+ );
16
+
17
+ export default Market;
@@ -0,0 +1,12 @@
1
+ import { memo } from 'react';
2
+
3
+ import { AgentDetailContent } from '../components/AgentDetail';
4
+ import Mobile from '../components/AgentDetail/Mobile';
5
+
6
+ const AgentDetail = memo(() => (
7
+ <Mobile>
8
+ <AgentDetailContent />
9
+ </Mobile>
10
+ ));
11
+
12
+ export default AgentDetail;