@lobehub/chat 0.84.0-beta.2 → 0.85.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 (203) hide show
  1. package/.github/workflows/lighthouse-badger-advanced.yml +74 -0
  2. package/.github/workflows/pre-welcome.yml +22 -0
  3. package/.github/workflows/release.yml +0 -3
  4. package/.github/workflows/sync.yml +11 -2
  5. package/.i18nrc.js +1 -2
  6. package/.releaserc.js +1 -14
  7. package/CHANGELOG.md +47 -10
  8. package/README.md +21 -0
  9. package/README.zh-CN.md +21 -0
  10. package/docs/Home.md +1 -0
  11. package/docs/Lighthouse.md +65 -0
  12. package/docs/Lighthouse.zh-CN.md +65 -0
  13. package/docs/_Sidebar.md +1 -0
  14. package/locales/en_US/common.json +5 -0
  15. package/locales/ja_JP/common.json +103 -0
  16. package/locales/ja_JP/empty.json +6 -0
  17. package/locales/ja_JP/error.json +42 -0
  18. package/locales/ja_JP/market.json +16 -0
  19. package/locales/ja_JP/plugin.json +107 -0
  20. package/locales/ja_JP/setting.json +225 -0
  21. package/locales/ja_JP/welcome.json +14 -0
  22. package/locales/ko_KR/common.json +103 -0
  23. package/locales/ko_KR/empty.json +6 -0
  24. package/locales/ko_KR/error.json +42 -0
  25. package/locales/ko_KR/market.json +16 -0
  26. package/locales/ko_KR/plugin.json +107 -0
  27. package/locales/ko_KR/setting.json +225 -0
  28. package/locales/ko_KR/welcome.json +14 -0
  29. package/locales/ru_RU/common.json +5 -0
  30. package/locales/zh_CN/common.json +5 -0
  31. package/locales/zh_TW/common.json +5 -0
  32. package/next.config.mjs +0 -3
  33. package/package.json +4 -4
  34. package/public/icons/maskable-icon-192x192.png +0 -0
  35. package/public/icons/maskable-icon-512x512.png +0 -0
  36. package/public/manifest.json +34 -5
  37. package/public/screenshots/screenshot-1.png +0 -0
  38. package/public/screenshots/screenshot-2.png +0 -0
  39. package/public/screenshots/screenshot-3.png +0 -0
  40. package/public/screenshots/screenshot-4.png +0 -0
  41. package/src/app/chat/(desktop)/features/{ChatHeader/Desktop.tsx → ChatHeader.tsx} +2 -2
  42. package/src/app/chat/(desktop)/features/{ChatInput/Desktop.tsx → ChatInput.tsx} +5 -7
  43. package/src/app/chat/(desktop)/features/{SessionHeader/Desktop.tsx → SessionHeader.tsx} +1 -1
  44. package/src/app/chat/(desktop)/features/{SessionList/Desktop.tsx → SessionList.tsx} +5 -4
  45. package/src/app/chat/(desktop)/features/{SideBar/Desktop.tsx → SideBar.tsx} +5 -4
  46. package/src/app/chat/(desktop)/index.tsx +14 -8
  47. package/src/app/chat/(desktop)/{layout/Desktop.tsx → layout.desktop.tsx} +7 -8
  48. package/src/app/chat/(desktop)/layout.responsive.tsx +12 -0
  49. package/src/app/chat/(mobile)/features/ChatHeader.tsx +54 -1
  50. package/src/app/chat/(mobile)/features/ChatInput.tsx +28 -8
  51. package/src/app/chat/(mobile)/features/SessionList.tsx +13 -8
  52. package/src/app/chat/{components/Inspector/Mobile.tsx → (mobile)/features/TopicList.tsx} +6 -4
  53. package/src/app/chat/(mobile)/index.tsx +3 -5
  54. package/src/app/chat/(mobile)/layout.mobile.tsx +17 -0
  55. package/src/app/chat/(mobile)/mobile/index.tsx +19 -0
  56. package/src/app/chat/(mobile)/mobile/layout.mobile.tsx +11 -0
  57. package/src/app/chat/(mobile)/mobile/page.tsx +2 -20
  58. package/src/app/chat/{components → features}/ChatHeader/ShareButton/Preview.tsx +25 -9
  59. package/src/app/chat/{components → features}/ChatHeader/ShareButton/style.ts +7 -7
  60. package/src/app/chat/{components/ChatInput → features/ChatInputContent}/Footer/SaveTopic.tsx +1 -1
  61. package/src/app/chat/{components/ChatInput → features/ChatInputContent}/index.tsx +3 -1
  62. package/src/app/chat/{components/SessionList → features/SessionListContent}/Inbox/index.tsx +7 -5
  63. package/src/app/chat/{components/SessionList → features/SessionListContent}/index.tsx +3 -1
  64. package/src/app/chat/{components/Inspector → features/TopicListContent}/index.tsx +3 -1
  65. package/src/app/chat/page.tsx +3 -1
  66. package/src/app/chat/settings/(desktop)/index.tsx +14 -0
  67. package/src/app/chat/settings/(desktop)/layout.desktop.tsx +10 -15
  68. package/src/app/chat/settings/(desktop)/layout.responsive.tsx +12 -0
  69. package/src/app/chat/settings/(mobile)/index.tsx +14 -0
  70. package/src/app/chat/settings/(mobile)/layout.mobile.tsx +4 -8
  71. package/src/app/chat/settings/features/EditPage.tsx +38 -0
  72. package/src/app/chat/settings/page.tsx +9 -33
  73. package/src/app/market/(desktop)/{AgentDetail/Desktop.tsx → features/AgentDetail.tsx} +5 -3
  74. package/src/app/market/(desktop)/index.tsx +12 -0
  75. package/src/app/market/(desktop)/{layout/Desktop.tsx → layout.desktop.tsx} +5 -5
  76. package/src/app/market/(desktop)/layout.responsive.tsx +16 -0
  77. package/src/app/market/{components/AgentDetail/Mobile.tsx → (mobile)/features/AgentDetail.tsx} +6 -4
  78. package/src/app/market/(mobile)/index.tsx +12 -0
  79. package/src/app/market/(mobile)/layout.mobile.tsx +5 -5
  80. package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/Header.tsx +1 -0
  81. package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/index.tsx +3 -1
  82. package/src/app/market/features/TagList/index.tsx +2 -1
  83. package/src/app/market/page.tsx +8 -5
  84. package/src/app/settings/{features/Header/Desktop.tsx → (desktop)/features/Header.tsx} +2 -2
  85. package/src/app/settings/(desktop)/index.tsx +17 -0
  86. package/src/app/settings/{layout.desktop/Desktop.tsx → (desktop)/layout.desktop.tsx} +10 -9
  87. package/src/app/settings/(desktop)/layout.responsive.tsx +14 -0
  88. package/src/app/settings/{mobile → (mobile)/features}/ExtraList.tsx +1 -1
  89. package/src/app/settings/(mobile)/features/Header/Home.tsx +8 -0
  90. package/src/app/settings/{features/Header/Mobile.tsx → (mobile)/features/Header/index.tsx} +1 -0
  91. package/src/app/settings/(mobile)/index.tsx +3 -0
  92. package/src/app/settings/(mobile)/layout.mobile.tsx +19 -0
  93. package/src/app/settings/{mobile → (mobile)/mobile}/index.tsx +9 -9
  94. package/src/app/settings/(mobile)/mobile/layout.mobile.tsx +14 -0
  95. package/src/app/settings/agent/Agent.tsx +30 -0
  96. package/src/app/settings/agent/index.tsx +23 -0
  97. package/src/app/settings/agent/layout.tsx +1 -0
  98. package/src/app/settings/agent/page.tsx +2 -31
  99. package/src/app/settings/common/index.tsx +23 -0
  100. package/src/app/settings/common/layout.tsx +1 -0
  101. package/src/app/settings/common/page.tsx +2 -14
  102. package/src/app/settings/features/SideBar/index.tsx +2 -0
  103. package/src/app/settings/features/UpgradeAlert.tsx +32 -0
  104. package/src/app/settings/layout.server.tsx +12 -0
  105. package/src/app/settings/llm/index.tsx +23 -0
  106. package/src/app/settings/llm/layout.tsx +1 -0
  107. package/src/app/settings/llm/page.tsx +2 -14
  108. package/src/app/settings/page.tsx +14 -1
  109. package/src/app/welcome/{features/Footer/index.tsx → (desktop)/features/Footer.tsx} +14 -3
  110. package/src/app/welcome/(desktop)/features/Showcase.tsx +23 -0
  111. package/src/app/welcome/(desktop)/index.tsx +19 -0
  112. package/src/app/welcome/{DesktopLayout/Desktop.tsx → (desktop)/layout.desktop.tsx} +5 -8
  113. package/src/app/welcome/(desktop)/layout.responsive.tsx +14 -0
  114. package/src/app/welcome/(mobile)/features/Header.tsx +6 -0
  115. package/src/app/welcome/(mobile)/features/Showcase.tsx +16 -0
  116. package/src/app/welcome/(mobile)/index.tsx +10 -0
  117. package/src/app/welcome/(mobile)/layout.mobile.tsx +20 -0
  118. package/src/app/welcome/features/Banner/Hero.tsx +2 -3
  119. package/src/app/welcome/features/Banner/index.tsx +34 -31
  120. package/src/app/welcome/features/Banner/style.ts +10 -1
  121. package/src/app/welcome/page.tsx +9 -7
  122. package/src/components/ResponsiveIndex.tsx +17 -0
  123. package/src/const/url.ts +2 -1
  124. package/src/const/version.ts +6 -0
  125. package/src/features/MobileTabBar/index.tsx +1 -1
  126. package/src/features/SideBar/BottomActions.tsx +107 -81
  127. package/src/layout/{AppLayout.tsx → AppLayout.desktop.tsx} +2 -2
  128. package/src/layout/{AppMobileLayout.tsx → AppLayout.mobile.tsx} +2 -2
  129. package/src/layout/GlobalLayout/AppTheme.tsx +3 -3
  130. package/src/layout/GlobalLayout/Locale.tsx +2 -2
  131. package/src/layout/GlobalLayout/StoreHydration.tsx +15 -1
  132. package/src/layout/ResponsiveLayout.client.tsx +18 -0
  133. package/src/{components/ResponsiveLayout.tsx → layout/ResponsiveLayout.server.tsx} +4 -3
  134. package/src/locales/default/common.ts +5 -0
  135. package/src/locales/options.ts +8 -1
  136. package/src/locales/resources/index.ts +4 -0
  137. package/src/locales/resources/ja_JP.ts +19 -0
  138. package/src/locales/resources/ko_KR.ts +19 -0
  139. package/src/services/latestVersion.ts +11 -1
  140. package/src/store/global/initialState.ts +11 -9
  141. package/src/store/global/slices/common.ts +12 -0
  142. package/src/store/session/slices/session/initialState.ts +2 -2
  143. package/src/utils/VersionController.ts +1 -1
  144. package/src/utils/responsive.ts +1 -1
  145. package/.dockerignore +0 -10
  146. package/Dockerfile +0 -47
  147. package/src/app/chat/(desktop)/features/ChatHeader/index.tsx +0 -14
  148. package/src/app/chat/(desktop)/features/ChatInput/index.tsx +0 -22
  149. package/src/app/chat/(desktop)/features/SessionHeader/index.tsx +0 -14
  150. package/src/app/chat/(desktop)/features/SessionList/index.tsx +0 -20
  151. package/src/app/chat/(desktop)/features/SideBar/index.tsx +0 -20
  152. package/src/app/chat/(desktop)/layout/index.tsx +0 -25
  153. package/src/app/chat/(mobile)/features/Topics.tsx +0 -12
  154. package/src/app/chat/(mobile)/layout.tsx +0 -15
  155. package/src/app/chat/components/ChatHeader/Mobile.tsx +0 -54
  156. package/src/app/chat/components/ChatInput/Mobile.tsx +0 -35
  157. package/src/app/chat/components/SessionList/Mobile.tsx +0 -16
  158. package/src/app/chat/layout.tsx +0 -15
  159. package/src/app/chat/settings/layout.tsx +0 -14
  160. package/src/app/market/(desktop)/AgentDetail/index.tsx +0 -16
  161. package/src/app/market/(desktop)/Header/index.tsx +0 -13
  162. package/src/app/market/(desktop)/layout/index.tsx +0 -17
  163. package/src/app/market/(mobile)/AgentDetail.tsx +0 -12
  164. package/src/app/market/layout.tsx +0 -13
  165. package/src/app/settings/features/Header/index.tsx +0 -14
  166. package/src/app/settings/layout.desktop/index.tsx +0 -32
  167. package/src/app/settings/layout.mobile.tsx +0 -16
  168. package/src/app/settings/layout.tsx +0 -15
  169. package/src/app/settings/mobile/page.tsx +0 -7
  170. package/src/app/welcome/DesktopLayout/index.tsx +0 -15
  171. package/src/app/welcome/MobileLayout.tsx +0 -23
  172. package/src/app/welcome/layout.tsx +0 -22
  173. /package/src/app/chat/{components → features}/ChatHeader/PluginTag/PluginStatus.tsx +0 -0
  174. /package/src/app/chat/{components → features}/ChatHeader/PluginTag/index.tsx +0 -0
  175. /package/src/app/chat/{components → features}/ChatHeader/ShareButton/Inner.tsx +0 -0
  176. /package/src/app/chat/{components → features}/ChatHeader/ShareButton/index.tsx +0 -0
  177. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/ActionBar/ActionLeft.tsx +0 -0
  178. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/ActionBar/ActionRight.tsx +0 -0
  179. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/ActionBar/Token.tsx +0 -0
  180. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/Footer/index.tsx +0 -0
  181. /package/src/app/chat/features/{PageTitle.tsx → PageTitle/index.tsx} +0 -0
  182. /package/src/app/chat/{components/SessionList → features/SessionListContent}/CollapseGroup/index.tsx +0 -0
  183. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/AddButton.tsx +0 -0
  184. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/Item/Actions.tsx +0 -0
  185. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/Item/index.tsx +0 -0
  186. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/SkeletonList.tsx +0 -0
  187. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/index.tsx +0 -0
  188. /package/src/app/chat/{components/Inspector → features/TopicListContent}/SystemRole/Header.tsx +0 -0
  189. /package/src/app/chat/{components/Inspector → features/TopicListContent}/SystemRole/index.tsx +0 -0
  190. /package/src/app/chat/{components/Inspector → features/TopicListContent}/SystemRole/style.ts +0 -0
  191. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/DefaultContent.tsx +0 -0
  192. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/SkeletonList.tsx +0 -0
  193. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/TopicContent.tsx +0 -0
  194. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/TopicItem.tsx +0 -0
  195. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/index.tsx +0 -0
  196. /package/src/app/chat/{components/Inspector → features/TopicListContent}/TopicSearchBar/index.tsx +0 -0
  197. /package/src/app/market/(desktop)/{Header/Desktop.tsx → features/Header.tsx} +0 -0
  198. /package/src/app/market/(mobile)/{Header.tsx → features/Header.tsx} +0 -0
  199. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/Comment.tsx +0 -0
  200. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/Loading.tsx +0 -0
  201. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/TokenTag.tsx +0 -0
  202. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/index.tsx +0 -0
  203. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/style.ts +0 -0
@@ -3,20 +3,26 @@
3
3
  import { memo } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
+ import ResponsiveIndex from '@/components/ResponsiveIndex';
7
+
8
+ import Mobile from '../(mobile)';
6
9
  import Conversation from '../features/Conversation';
7
10
  import PageTitle from '../features/PageTitle';
8
11
  import ChatHeader from './features/ChatHeader';
9
12
  import ChatInput from './features/ChatInput';
10
13
  import SideBar from './features/SideBar';
14
+ import Layout from './layout.responsive';
11
15
 
12
16
  const DesktopPage = memo(() => (
13
- <>
14
- <PageTitle />
15
- <ChatHeader />
16
- <Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
17
- <Conversation chatInput={<ChatInput />} />
18
- <SideBar />
19
- </Flexbox>
20
- </>
17
+ <ResponsiveIndex Mobile={Mobile}>
18
+ <Layout>
19
+ <PageTitle />
20
+ <ChatHeader />
21
+ <Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
22
+ <Conversation chatInput={<ChatInput />} />
23
+ <SideBar />
24
+ </Flexbox>
25
+ </Layout>
26
+ </ResponsiveIndex>
21
27
  ));
22
28
  export default DesktopPage;
@@ -1,17 +1,18 @@
1
+ 'use client';
2
+
1
3
  import { PropsWithChildren, memo } from 'react';
2
4
  import { Flexbox } from 'react-layout-kit';
3
5
 
4
- import AppLayout from '@/layout/AppLayout';
6
+ import AppLayoutDesktop from '@/layout/AppLayout.desktop';
5
7
  import { useSwitchSideBarOnInit } from '@/store/global';
6
8
  import { SidebarTabKey } from '@/store/global/initialState';
7
9
 
8
- import ResponsiveSessionList from '../features/SessionList';
10
+ import ResponsiveSessionList from './features/SessionList';
9
11
 
10
- const Desktop = memo<PropsWithChildren>(({ children }) => {
12
+ export default memo(({ children }: PropsWithChildren) => {
11
13
  useSwitchSideBarOnInit(SidebarTabKey.Chat);
12
-
13
14
  return (
14
- <AppLayout>
15
+ <AppLayoutDesktop>
15
16
  <ResponsiveSessionList />
16
17
  <Flexbox
17
18
  flex={1}
@@ -21,8 +22,6 @@ const Desktop = memo<PropsWithChildren>(({ children }) => {
21
22
  >
22
23
  {children}
23
24
  </Flexbox>
24
- </AppLayout>
25
+ </AppLayoutDesktop>
25
26
  );
26
27
  });
27
-
28
- export default Desktop;
@@ -0,0 +1,12 @@
1
+ import { PropsWithChildren, memo } from 'react';
2
+
3
+ import ResponsiveLayout from '@/layout/ResponsiveLayout.client';
4
+
5
+ import Mobile from '../(mobile)/layout.mobile';
6
+ import Desktop from './layout.desktop';
7
+
8
+ export default memo(({ children }: PropsWithChildren) => (
9
+ <ResponsiveLayout Desktop={Desktop} Mobile={Mobile}>
10
+ {children}
11
+ </ResponsiveLayout>
12
+ ));
@@ -1 +1,54 @@
1
- export { default } from '../../components/ChatHeader/Mobile';
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 '../../features/ChatHeader/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;
@@ -1,14 +1,34 @@
1
+ import { createStyles } from 'antd-style';
1
2
  import { memo } from 'react';
2
3
 
3
- import { ChatInputContent } from '../../components/ChatInput';
4
- import Mobile from '../../components/ChatInput/Mobile';
4
+ import SafeSpacing from '@/components/SafeSpacing';
5
+ import { CHAT_TEXTAREA_HEIGHT_MOBILE } from '@/const/layoutTokens';
5
6
 
6
- const ChatInput = () => {
7
+ import ChatInputContent from '../../features/ChatInputContent';
8
+
9
+ const useStyles = createStyles(
10
+ ({ css, token }) => css`
11
+ position: fixed;
12
+ right: 0;
13
+ bottom: 0;
14
+ left: 0;
15
+
16
+ width: 100vw;
17
+
18
+ background: ${token.colorBgLayout};
19
+ `,
20
+ );
21
+
22
+ const ChatInputMobileLayout = memo(() => {
23
+ const { styles } = useStyles();
7
24
  return (
8
- <Mobile>
9
- <ChatInputContent mobile />
10
- </Mobile>
25
+ <>
26
+ <SafeSpacing height={CHAT_TEXTAREA_HEIGHT_MOBILE} mobile position={'bottom'} />
27
+ <div className={styles}>
28
+ <ChatInputContent mobile />
29
+ </div>
30
+ </>
11
31
  );
12
- };
32
+ });
13
33
 
14
- export default memo(ChatInput);
34
+ export default ChatInputMobileLayout;
@@ -1,12 +1,17 @@
1
1
  import { memo } from 'react';
2
2
 
3
- import { SessionListContent } from '../../components/SessionList';
4
- import Wrapper from '../../components/SessionList/Mobile';
3
+ import SessionListContent from '../../features/SessionListContent';
4
+ import SessionSearchBar from '../../features/SessionSearchBar';
5
5
 
6
- const SessionList = memo(() => (
7
- <Wrapper>
8
- <SessionListContent />
9
- </Wrapper>
10
- ));
6
+ const Sessions = memo(() => {
7
+ return (
8
+ <>
9
+ <div style={{ padding: '8px 16px' }}>
10
+ <SessionSearchBar />
11
+ </div>
12
+ <SessionListContent />
13
+ </>
14
+ );
15
+ });
11
16
 
12
- export default SessionList;
17
+ export default Sessions;
@@ -1,10 +1,12 @@
1
1
  import { Modal } from '@lobehub/ui';
2
- import { PropsWithChildren, memo } from 'react';
2
+ import { memo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
5
5
  import { useGlobalStore } from '@/store/global';
6
6
 
7
- const Mobile = memo<PropsWithChildren>(({ children }) => {
7
+ import TopicListContent from '../../features/TopicListContent';
8
+
9
+ const Topics = memo(() => {
8
10
  const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
9
11
  s.preference.mobileShowTopic,
10
12
  s.toggleMobileTopic,
@@ -14,9 +16,9 @@ const Mobile = memo<PropsWithChildren>(({ children }) => {
14
16
 
15
17
  return (
16
18
  <Modal onCancel={() => toggleConfig(false)} open={showAgentSettings} title={t('topic.title')}>
17
- {children}
19
+ <TopicListContent />
18
20
  </Modal>
19
21
  );
20
22
  });
21
23
 
22
- export default Mobile;
24
+ export default Topics;
@@ -2,18 +2,16 @@
2
2
 
3
3
  import { memo } from 'react';
4
4
 
5
- import AppMobileLayout from '@/layout/AppMobileLayout';
6
-
7
5
  import PageTitle from '../features/PageTitle';
8
- import SessionHeader from './features/SessionHeader';
9
6
  import SessionList from './features/SessionList';
7
+ import Layout from './layout.mobile';
10
8
 
11
9
  const ChatMobilePage = memo(() => {
12
10
  return (
13
- <AppMobileLayout navBar={<SessionHeader />} showTabBar>
11
+ <Layout>
14
12
  <PageTitle />
15
13
  <SessionList />
16
- </AppMobileLayout>
14
+ </Layout>
17
15
  );
18
16
  });
19
17
 
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, memo } from 'react';
4
+
5
+ import SessionHeader from '@/app/chat/(mobile)/features/SessionHeader';
6
+ import AppLayoutMobile from '@/layout/AppLayout.mobile';
7
+ import { useSwitchSideBarOnInit } from '@/store/global';
8
+ import { SidebarTabKey } from '@/store/global/initialState';
9
+
10
+ export default memo(({ children }: PropsWithChildren) => {
11
+ useSwitchSideBarOnInit(SidebarTabKey.Chat);
12
+ return (
13
+ <AppLayoutMobile navBar={<SessionHeader />} showTabBar>
14
+ {children}
15
+ </AppLayoutMobile>
16
+ );
17
+ });
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import Conversation from '../../features/Conversation';
7
+ import ChatInput from '../features/ChatInput';
8
+ import TopicList from '../features/TopicList';
9
+ import Layout from './layout.mobile';
10
+
11
+ const Chat = memo(() => (
12
+ <Layout>
13
+ <Flexbox height={'calc(100vh - 44px)'} horizontal>
14
+ <Conversation chatInput={<ChatInput />} mobile />
15
+ <TopicList />
16
+ </Flexbox>
17
+ </Layout>
18
+ ));
19
+ export default Chat;
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren } from 'react';
4
+
5
+ import AppLayoutMobile from '@/layout/AppLayout.mobile';
6
+
7
+ import ChatHeader from '../features/ChatHeader';
8
+
9
+ export default ({ children }: PropsWithChildren) => (
10
+ <AppLayoutMobile navBar={<ChatHeader />}>{children}</AppLayoutMobile>
11
+ );
@@ -1,21 +1,3 @@
1
- 'use client';
1
+ import Index from './index';
2
2
 
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;
3
+ export default () => <Index />;
@@ -2,24 +2,25 @@ 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 { toJpeg, toPng, toSvg } from 'html-to-image';
5
+ import { domToJpeg, domToPng, domToSvg, domToWebp } from 'modern-screenshot';
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 PluginTag from '@/app/chat/components/ChatHeader/PluginTag';
11
+ import pkg from '@/../package.json';
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 pkg from '../../../../../../package.json';
16
+ import PluginTag from '../../ChatHeader/PluginTag';
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',
23
24
  }
24
25
 
25
26
  export const imageTypeOptions: SegmentedProps['options'] = [
@@ -35,6 +36,10 @@ export const imageTypeOptions: SegmentedProps['options'] = [
35
36
  label: 'SVG',
36
37
  value: ImageType.SVG,
37
38
  },
39
+ {
40
+ label: 'WEBP',
41
+ value: ImageType.WEBP,
42
+ },
38
43
  ];
39
44
 
40
45
  interface PreviewProps {
@@ -69,26 +74,37 @@ const Preview = memo<PreviewProps>(({ withSystemRole, imageType, withBackground,
69
74
  let screenshotFn: any;
70
75
  switch (imageType) {
71
76
  case ImageType.JPG: {
72
- screenshotFn = toJpeg;
77
+ screenshotFn = domToJpeg;
73
78
  break;
74
79
  }
75
80
  case ImageType.PNG: {
76
- screenshotFn = toPng;
81
+ screenshotFn = domToPng;
77
82
  break;
78
83
  }
79
84
  case ImageType.SVG: {
80
- screenshotFn = toSvg;
85
+ screenshotFn = domToSvg;
86
+ break;
87
+ }
88
+ case ImageType.WEBP: {
89
+ screenshotFn = domToWebp;
81
90
  break;
82
91
  }
83
92
  }
84
- const dataUrl = await screenshotFn(document.querySelector('#preview') as HTMLDivElement);
93
+
94
+ const dataUrl = await screenshotFn(document.querySelector('#preview') as HTMLDivElement, {
95
+ features: {
96
+ // 不启用移除控制符,否则会导致 safari emoji 报错
97
+ removeControlCharacter: false,
98
+ },
99
+ scale: 2,
100
+ });
85
101
  const link = document.createElement('a');
86
102
  link.download = `LobeChat_${title}_${dayjs().format('YYYY-MM-DD')}.${imageType}`;
87
103
  link.href = dataUrl;
88
104
  link.click();
89
105
  setLoading(false);
90
- } catch {
91
- console.error('Failed to download image');
106
+ } catch (error) {
107
+ console.error('Failed to download image', error);
92
108
  setLoading(false);
93
109
  }
94
110
  }, [imageType, title]);
@@ -1,22 +1,22 @@
1
1
  import { createStyles } from 'antd-style';
2
- import { rgba } from 'polished';
3
2
 
4
3
  export const useStyles = createStyles(({ css, token, stylish, cx }, withBackground: boolean) => ({
5
4
  background: css`
6
5
  padding: 24px;
7
- background: url('/images/screenshot_background.webp') no-repeat;
8
- background-size: 100% 100%;
6
+
7
+ background-color: ${token.colorBgLayout};
8
+ background-image: url('/images/screenshot_background.webp');
9
+ background-position: center;
10
+ background-size: 120% 120%;
9
11
  `,
10
12
  container: cx(
11
13
  withBackground &&
12
14
  css`
13
15
  overflow: hidden;
14
- border: 1px solid ${rgba(token.colorText, 0.15)};
16
+ border: 2px solid ${token.colorBorder};
15
17
  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%);
19
18
  `,
19
+
20
20
  css`
21
21
  background: ${token.colorBgLayout};
22
22
  `,
@@ -19,7 +19,7 @@ const SaveTopic = memo(() => {
19
19
 
20
20
  return (
21
21
  <Tooltip title={t('topic.saveCurrentMessages')}>
22
- <Render icon={icon} onClick={saveToTopic} />
22
+ <Render aria-label={t('topic.saveCurrentMessages')} icon={icon} onClick={saveToTopic} />
23
23
  </Tooltip>
24
24
  );
25
25
  });
@@ -19,7 +19,7 @@ interface ChatContentProps {
19
19
  onExpandChange?: (expand: boolean) => void;
20
20
  }
21
21
 
22
- export const ChatInputContent = memo<ChatContentProps>(
22
+ const ChatInputContent = memo<ChatContentProps>(
23
23
  ({ expand, onExpandChange, mobile: defaultMobile }) => {
24
24
  const { t } = useTranslation('common');
25
25
 
@@ -63,3 +63,5 @@ export const ChatInputContent = memo<ChatContentProps>(
63
63
  );
64
64
  },
65
65
  );
66
+
67
+ export default ChatInputContent;
@@ -1,5 +1,6 @@
1
1
  import { Avatar, List } from '@lobehub/ui';
2
2
  import { useHover } from 'ahooks';
3
+ import { useResponsive } from 'antd-style';
3
4
  import Link from 'next/link';
4
5
  import { memo, useMemo, useRef } from 'react';
5
6
  import { useTranslation } from 'react-i18next';
@@ -15,10 +16,10 @@ const Inbox = memo(() => {
15
16
  const ref = useRef(null);
16
17
  const isHovering = useHover(ref);
17
18
  const { t } = useTranslation('common');
18
-
19
- const [mobile, activeId, switchSession] = useSessionStore((s) => [
20
- s.isMobile,
19
+ const { mobile } = useResponsive();
20
+ const [activeId, activeSession, switchSession] = useSessionStore((s) => [
21
21
  s.activeId,
22
+ s.activeSession,
22
23
  s.switchSession,
23
24
  ]);
24
25
 
@@ -39,11 +40,12 @@ const Inbox = memo(() => {
39
40
  href={SESSION_CHAT_URL(INBOX_SESSION_ID, mobile)}
40
41
  onClick={(e) => {
41
42
  e.preventDefault();
42
- switchSession(INBOX_SESSION_ID);
43
+ if (mobile) switchSession(INBOX_SESSION_ID);
44
+ else activeSession(INBOX_SESSION_ID);
43
45
  }}
44
46
  >
45
47
  <Item
46
- active={activeId === INBOX_SESSION_ID}
48
+ active={mobile ? false : activeId === INBOX_SESSION_ID}
47
49
  avatar={avatarRender}
48
50
  ref={ref}
49
51
  style={{ alignItems: 'center' }}
@@ -6,7 +6,7 @@ import CollapseGroup from './CollapseGroup';
6
6
  import Inbox from './Inbox';
7
7
  import SessionList from './List';
8
8
 
9
- export const SessionListContent = memo(() => {
9
+ const SessionListContent = memo(() => {
10
10
  const { t } = useTranslation('common');
11
11
  const items: CollapseProps['items'] = useMemo(
12
12
  () => [
@@ -26,3 +26,5 @@ export const SessionListContent = memo(() => {
26
26
  </>
27
27
  );
28
28
  });
29
+
30
+ export default SessionListContent;
@@ -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
- export const InspectorContent = () => {
6
+ const TopicListContent = () => {
7
7
  return (
8
8
  <Flexbox height={'100%'} style={{ overflow: 'hidden' }}>
9
9
  <Flexbox padding={16}>
@@ -15,3 +15,5 @@ export const InspectorContent = () => {
15
15
  </Flexbox>
16
16
  );
17
17
  };
18
+
19
+ export default TopicListContent;
@@ -6,7 +6,9 @@ import MobilePage from './(mobile)';
6
6
  const Page = () => {
7
7
  const mobile = isMobileDevice();
8
8
 
9
- return mobile ? <MobilePage /> : <DesktopPage />;
9
+ const Page = mobile ? MobilePage : DesktopPage;
10
+
11
+ return <Page />;
10
12
  };
11
13
 
12
14
  export default Page;
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+
5
+ import EditPage from '../features/EditPage';
6
+ import Layout from './layout.responsive';
7
+
8
+ const ChatSettings = memo(() => (
9
+ <Layout>
10
+ <EditPage />
11
+ </Layout>
12
+ ));
13
+
14
+ export default ChatSettings;
@@ -1,23 +1,18 @@
1
- 'use client';
2
-
3
1
  import { PropsWithChildren, memo } from 'react';
4
2
  import { Flexbox } from 'react-layout-kit';
5
3
 
6
4
  import SafeSpacing from '@/components/SafeSpacing';
7
5
  import { HEADER_HEIGHT } from '@/const/layoutTokens';
8
6
 
7
+ import Layout from '../../(desktop)/layout.desktop';
9
8
  import Header from './Header';
10
9
 
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;
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
+ ));
@@ -0,0 +1,12 @@
1
+ import { PropsWithChildren, memo } from 'react';
2
+
3
+ import ResponsiveLayout from '@/layout/ResponsiveLayout.client';
4
+
5
+ import Mobile from '../(mobile)/layout.mobile';
6
+ import Desktop from './layout.desktop';
7
+
8
+ export default memo(({ children }: PropsWithChildren) => (
9
+ <ResponsiveLayout Desktop={Desktop} Mobile={Mobile}>
10
+ {children}
11
+ </ResponsiveLayout>
12
+ ));
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+
5
+ import EditPage from '../features/EditPage';
6
+ import Layout from './layout.mobile';
7
+
8
+ const ChatSettings = memo(() => (
9
+ <Layout>
10
+ <EditPage />
11
+ </Layout>
12
+ ));
13
+
14
+ export default ChatSettings;
@@ -1,13 +1,9 @@
1
- 'use client';
2
-
3
1
  import { PropsWithChildren, memo } from 'react';
4
2
 
5
- import AppMobileLayout from '@/layout/AppMobileLayout';
3
+ import AppLayoutMobile from '@/layout/AppLayout.mobile';
6
4
 
7
5
  import Header from './Header';
8
6
 
9
- const MobileLayout = memo<PropsWithChildren>(({ children }) => {
10
- return <AppMobileLayout navBar={<Header />}>{children}</AppMobileLayout>;
11
- });
12
-
13
- export default MobileLayout;
7
+ export default memo(({ children }: PropsWithChildren) => (
8
+ <AppLayoutMobile navBar={<Header />}>{children}</AppLayoutMobile>
9
+ ));