@lobehub/chat 0.70.1 → 0.70.3

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 (70) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/package.json +1 -1
  3. package/src/const/url.ts +4 -1
  4. package/src/features/MobileTabBar/index.tsx +4 -12
  5. package/src/features/SideBar/BottomActions.tsx +12 -2
  6. package/src/features/SideBar/TopActions.tsx +7 -1
  7. package/src/layout/AppMobileLayout.tsx +16 -8
  8. package/src/pages/chat/features/Conversation/Input/index.tsx +4 -3
  9. package/src/pages/chat/features/Conversation/index.tsx +5 -0
  10. package/src/pages/chat/features/Header/Mobile.tsx +1 -1
  11. package/src/pages/chat/features/Header/index.tsx +3 -4
  12. package/src/pages/chat/features/SessionList/Desktop.tsx +24 -0
  13. package/src/pages/chat/features/SessionList/{Header.tsx → Header/Desktop.tsx} +2 -26
  14. package/src/pages/chat/features/SessionList/Header/Mobile.tsx +42 -0
  15. package/src/pages/chat/features/SessionList/Header/index.tsx +14 -0
  16. package/src/pages/chat/features/SessionList/{Inbox.tsx → Inbox/index.tsx} +7 -2
  17. package/src/pages/chat/features/SessionList/List/index.tsx +8 -3
  18. package/src/pages/chat/features/SessionList/Mobile.tsx +26 -0
  19. package/src/pages/chat/features/SessionList/index.tsx +11 -25
  20. package/src/pages/chat/features/Sidebar/Desktop.tsx +58 -0
  21. package/src/pages/chat/features/Sidebar/{SystemRole.tsx → SystemRole/index.tsx} +3 -37
  22. package/src/pages/chat/features/Sidebar/SystemRole/style.ts +36 -0
  23. package/src/pages/chat/features/Sidebar/index.tsx +20 -78
  24. package/src/pages/chat/index.page.tsx +14 -13
  25. package/src/pages/chat/{mobile.tsx → layout.mobile.tsx} +2 -8
  26. package/src/pages/chat/layout.tsx +8 -17
  27. package/src/pages/chat/mobile/index.page.tsx +4 -7
  28. package/src/pages/chat/setting/features/Header/Desktop.tsx +21 -0
  29. package/src/pages/chat/setting/features/Header/Mobile.tsx +19 -0
  30. package/src/pages/chat/setting/features/Header/index.tsx +57 -0
  31. package/src/pages/chat/setting/index.page.tsx +5 -21
  32. package/src/pages/chat/setting/layout.mobile.tsx +18 -0
  33. package/src/pages/chat/setting/layout.tsx +22 -0
  34. package/src/pages/market/features/Header/Desktop.tsx +54 -0
  35. package/src/pages/market/features/Header/Mobile.tsx +42 -0
  36. package/src/pages/market/features/Header/index.tsx +13 -0
  37. package/src/pages/market/index.page.tsx +30 -0
  38. package/src/pages/market/layout.mobile.tsx +19 -0
  39. package/src/pages/market/layout.tsx +23 -0
  40. package/src/pages/settings/{Header.tsx → features/Header/Desktop.tsx} +2 -2
  41. package/src/pages/settings/features/Header/Mobile.tsx +18 -0
  42. package/src/pages/settings/features/Header/index.tsx +14 -0
  43. package/src/pages/settings/{Settings → features/Settings}/index.tsx +1 -2
  44. package/src/pages/settings/index.page.tsx +8 -21
  45. package/src/pages/settings/layout.mobile.tsx +18 -0
  46. package/src/pages/settings/layout.tsx +8 -1
  47. package/src/pages/welcome/{Banner → features/Banner}/AgentTemplate.tsx +1 -1
  48. package/src/pages/welcome/{Banner → features/Banner}/Hero.tsx +1 -1
  49. package/src/pages/welcome/{Banner → features/Banner}/index.tsx +1 -1
  50. package/src/pages/welcome/index.page.tsx +3 -3
  51. package/src/pages/welcome/layout.tsx +1 -1
  52. package/src/store/session/slices/session/action.ts +2 -2
  53. package/src/store/session/slices/session/initialState.ts +2 -0
  54. package/src/pages/chat/setting/Header.tsx +0 -82
  55. package/src/pages/chat/setting/mobile.tsx +0 -11
  56. package/src/pages/settings/mobile.tsx +0 -20
  57. /package/src/pages/chat/features/Header/{PC.tsx → Desktop.tsx} +0 -0
  58. /package/src/pages/chat/features/Header/{PluginTag.tsx → PluginTag/index.tsx} +0 -0
  59. /package/src/pages/chat/features/Header/{ShareButton.tsx → ShareButton/index.tsx} +0 -0
  60. /package/src/pages/chat/features/SessionList/{CollapseGroup.tsx → CollapseGroup/index.tsx} +0 -0
  61. /package/src/pages/chat/features/Sidebar/{Header.tsx → SystemRole/Header.tsx} +0 -0
  62. /package/src/pages/settings/{Settings → features/Settings}/Agent.tsx +0 -0
  63. /package/src/pages/settings/{Settings → features/Settings}/Common.tsx +0 -0
  64. /package/src/pages/settings/{ThemeSwatches → features/ThemeSwatches}/ThemeSwatchesNeutral.tsx +0 -0
  65. /package/src/pages/settings/{ThemeSwatches → features/ThemeSwatches}/ThemeSwatchesPrimary.tsx +0 -0
  66. /package/src/pages/settings/{ThemeSwatches → features/ThemeSwatches}/index.ts +0 -0
  67. /package/src/pages/welcome/{Banner → features/Banner}/AgentCard.tsx +0 -0
  68. /package/src/pages/welcome/{style.ts → features/Banner/style.ts} +0 -0
  69. /package/src/pages/welcome/{Footer → features/Footer}/index.tsx +0 -0
  70. /package/src/pages/welcome/{mobile.tsx → layout.mobile.tsx} +0 -0
@@ -1,51 +1,17 @@
1
1
  import { ActionIcon, EditableMessage } from '@lobehub/ui';
2
2
  import { Skeleton } from 'antd';
3
- import { createStyles } from 'antd-style';
4
3
  import { Edit } from 'lucide-react';
5
4
  import { memo, useState } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
  import { Flexbox } from 'react-layout-kit';
8
7
 
9
- import Header from '@/pages/chat/features/Sidebar/Header';
10
8
  import { useSessionChatInit, useSessionStore } from '@/store/session';
11
9
  import { agentSelectors } from '@/store/session/selectors';
12
10
 
13
- const useStyles = createStyles(({ css, token }) => ({
14
- prompt: css`
15
- overflow-x: hidden;
16
- overflow-y: auto;
11
+ import Header from './Header';
12
+ import { useStyles } from './style';
17
13
 
18
- padding: 0 16px 16px;
19
-
20
- opacity: 0.75;
21
-
22
- transition: opacity 200ms ${token.motionEaseOut};
23
-
24
- &:hover {
25
- opacity: 1;
26
- }
27
- `,
28
- promptBox: css`
29
- position: relative;
30
- overflow: hidden;
31
- border-bottom: 1px solid ${token.colorBorder};
32
- `,
33
- promptMask: css`
34
- pointer-events: none;
35
-
36
- position: absolute;
37
- z-index: 10;
38
- bottom: 0;
39
- left: 0;
40
-
41
- width: 100%;
42
- height: 32px;
43
-
44
- background: linear-gradient(to bottom, transparent, ${token.colorBgLayout});
45
- `,
46
- }));
47
-
48
- const SystemRole = memo<{ mobile?: boolean }>(() => {
14
+ const SystemRole = memo(() => {
49
15
  const [openModal, setOpenModal] = useState(false);
50
16
 
51
17
  const { styles } = useStyles();
@@ -0,0 +1,36 @@
1
+ import { createStyles } from 'antd-style';
2
+
3
+ export const useStyles = createStyles(({ css, token }) => ({
4
+ prompt: css`
5
+ overflow-x: hidden;
6
+ overflow-y: auto;
7
+
8
+ padding: 0 16px 16px;
9
+
10
+ opacity: 0.75;
11
+
12
+ transition: opacity 200ms ${token.motionEaseOut};
13
+
14
+ &:hover {
15
+ opacity: 1;
16
+ }
17
+ `,
18
+ promptBox: css`
19
+ position: relative;
20
+ overflow: hidden;
21
+ border-bottom: 1px solid ${token.colorBorder};
22
+ `,
23
+ promptMask: css`
24
+ pointer-events: none;
25
+
26
+ position: absolute;
27
+ z-index: 10;
28
+ bottom: 0;
29
+ left: 0;
30
+
31
+ width: 100%;
32
+ height: 32px;
33
+
34
+ background: linear-gradient(to bottom, transparent, ${token.colorBgLayout});
35
+ `,
36
+ }));
@@ -1,93 +1,35 @@
1
- import { DraggablePanel, DraggablePanelContainer, SearchBar } from '@lobehub/ui';
2
- import { createStyles } from 'antd-style';
3
- import { rgba } from 'polished';
1
+ import { SearchBar } from '@lobehub/ui';
2
+ import { useResponsive } from 'antd-style';
4
3
  import { memo } from 'react';
5
4
  import { useTranslation } from 'react-i18next';
6
5
  import { Flexbox } from 'react-layout-kit';
7
6
 
8
- import SafeSpacing from '@/components/SafeSpacing';
9
- import { CHAT_SIDEBAR_WIDTH } from '@/const/layoutTokens';
10
- import { useGlobalStore } from '@/store/global';
11
- import { useSessionStore } from '@/store/session';
12
- import { sessionSelectors } from '@/store/session/slices/session/selectors';
13
-
7
+ import Desktop from './Desktop';
14
8
  import Mobile from './Mobile';
15
- import SystemRole from './SystemRole';
16
9
  import { Topic } from './Topic';
17
10
 
18
- const useStyles = createStyles(({ cx, css, token, stylish }, mobile: boolean) => ({
19
- content: css`
20
- display: flex;
21
- flex-direction: column;
22
- `,
23
- drawer: cx(
24
- mobile
25
- ? css`
26
- background: ${token.colorBgLayout} !important;
27
- `
28
- : stylish.blurStrong,
29
- css`
30
- background: ${rgba(token.colorBgLayout, 0.4)};
31
- `,
32
- ),
33
- header: css`
34
- border-bottom: 1px solid ${token.colorBorder};
35
- `,
36
- }));
37
-
38
- interface SideBarProps {
39
- mobile?: boolean;
40
- systemRole?: boolean;
41
- }
42
- const SideBar = memo<SideBarProps>(({ mobile }) => {
43
- const { styles } = useStyles(mobile);
44
- const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
45
- s.preference.showChatSideBar,
46
- s.toggleChatSideBar,
47
- ]);
11
+ const SideBar = memo(() => {
12
+ const { mobile } = useResponsive();
48
13
 
49
- const isInbox = useSessionStore(sessionSelectors.isInboxSession);
14
+ const Render = mobile ? Mobile : Desktop;
50
15
 
51
16
  const { t } = useTranslation('common');
52
17
 
53
- const topic = (
54
- <Flexbox height={'100%'} style={{ overflow: 'hidden' }}>
55
- <Flexbox padding={16}>
56
- <SearchBar
57
- placeholder={t('topic.searchPlaceholder')}
58
- spotlight={!mobile}
59
- type={mobile ? 'block' : 'ghost'}
60
- />
61
- </Flexbox>
62
- <Flexbox gap={16} paddingInline={16} style={{ overflowY: 'auto', position: 'relative' }}>
63
- <Topic />
64
- </Flexbox>
65
- </Flexbox>
66
- );
67
-
68
- if (mobile) return <Mobile>{topic}</Mobile>;
69
-
70
18
  return (
71
- <DraggablePanel
72
- className={styles.drawer}
73
- classNames={{
74
- content: styles.content,
75
- }}
76
- expand={showAgentSettings}
77
- minWidth={CHAT_SIDEBAR_WIDTH}
78
- mode={'fixed'}
79
- onExpandChange={toggleConfig}
80
- placement={'right'}
81
- >
82
- <DraggablePanelContainer
83
- style={{ flex: 'none', height: '100%', minWidth: CHAT_SIDEBAR_WIDTH }}
84
- >
85
- <SafeSpacing />
86
- {!isInbox && <SystemRole mobile={mobile} />}
87
-
88
- {topic}
89
- </DraggablePanelContainer>
90
- </DraggablePanel>
19
+ <Render>
20
+ <Flexbox height={'100%'} style={{ overflow: 'hidden' }}>
21
+ <Flexbox padding={16}>
22
+ <SearchBar
23
+ placeholder={t('topic.searchPlaceholder')}
24
+ spotlight={!mobile}
25
+ type={mobile ? 'block' : 'ghost'}
26
+ />
27
+ </Flexbox>
28
+ <Flexbox gap={16} paddingInline={16} style={{ overflowY: 'auto', position: 'relative' }}>
29
+ <Topic />
30
+ </Flexbox>
31
+ </Flexbox>
32
+ </Render>
91
33
  );
92
34
  });
93
35
 
@@ -10,8 +10,8 @@ import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
10
10
  import Conversation from './features/Conversation';
11
11
  import Header from './features/Header';
12
12
  import SideBar from './features/Sidebar';
13
- import Layout from './layout';
14
- import Mobile from './mobile';
13
+ import DesktopLayout from './layout';
14
+ import MobileLayout from './layout.mobile';
15
15
 
16
16
  const Chat = memo(() => {
17
17
  const { mobile } = useResponsive();
@@ -20,23 +20,24 @@ const Chat = memo(() => {
20
20
  agentSelectors.currentAgentTitle(s),
21
21
  ]);
22
22
  const pageTitle = genSiteHeadTitle([avatar, title].filter(Boolean).join(' '));
23
+ const RenderLayout = mobile ? MobileLayout : DesktopLayout;
23
24
 
24
25
  return (
25
26
  <>
26
27
  <Head>
27
28
  <title>{pageTitle}</title>
28
29
  </Head>
29
- {mobile ? (
30
- <Mobile />
31
- ) : (
32
- <Layout>
33
- <Header />
34
- <Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
35
- <Conversation />
36
- <SideBar />
37
- </Flexbox>
38
- </Layout>
39
- )}
30
+ <RenderLayout>
31
+ {!mobile && (
32
+ <>
33
+ <Header />
34
+ <Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
35
+ <Conversation />
36
+ <SideBar />
37
+ </Flexbox>
38
+ </>
39
+ )}
40
+ </RenderLayout>
40
41
  </>
41
42
  );
42
43
  });
@@ -1,4 +1,3 @@
1
- import { useTheme } from 'antd-style';
2
1
  import { memo } from 'react';
3
2
 
4
3
  import AppMobileLayout from '@/layout/AppMobileLayout';
@@ -9,15 +8,10 @@ import Header from './features/SessionList/Header';
9
8
 
10
9
  const ChatMobileLayout = memo(() => {
11
10
  useSwitchSideBarOnInit('chat');
12
- const theme = useTheme();
13
11
 
14
12
  return (
15
- <AppMobileLayout
16
- navBar={<Header mobile={'navbar'} />}
17
- showTabBar
18
- style={{ background: theme.colorBgContainer }}
19
- >
20
- <Sessions mobile />
13
+ <AppMobileLayout navBar={<Header />} showTabBar>
14
+ <Sessions />
21
15
  </AppMobileLayout>
22
16
  );
23
17
  });
@@ -1,34 +1,25 @@
1
- import { useResponsive } from 'antd-style';
2
1
  import { PropsWithChildren, memo } from 'react';
3
2
  import { Flexbox } from 'react-layout-kit';
4
3
 
5
4
  import AppLayout from '@/layout/AppLayout';
6
5
  import { useSwitchSideBarOnInit } from '@/store/global';
7
- import { usePluginStore } from '@/store/plugin';
8
6
 
9
7
  import { Sessions } from './features/SessionList';
10
8
 
11
9
  const ChatLayout = memo<PropsWithChildren>(({ children }) => {
12
- const { mobile } = useResponsive();
13
-
14
10
  useSwitchSideBarOnInit('chat');
15
11
 
16
- const useFetchPluginList = usePluginStore((s) => s.useFetchPluginList);
17
- useFetchPluginList();
18
-
19
12
  return (
20
13
  <AppLayout>
21
14
  <Sessions />
22
- {!mobile && (
23
- <Flexbox
24
- flex={1}
25
- height={'100vh'}
26
- id={'lobe-conversion-container'}
27
- style={{ position: 'relative' }}
28
- >
29
- {children}
30
- </Flexbox>
31
- )}
15
+ <Flexbox
16
+ flex={1}
17
+ height={'100vh'}
18
+ id={'lobe-conversion-container'}
19
+ style={{ position: 'relative' }}
20
+ >
21
+ {children}
22
+ </Flexbox>
32
23
  </AppLayout>
33
24
  );
34
25
  });
@@ -10,7 +10,6 @@ import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
10
10
 
11
11
  import Conversation from '../features/Conversation';
12
12
  import SideBar from '../features/Sidebar';
13
- import ChatLayout from '../layout';
14
13
 
15
14
  const Chat = memo(() => {
16
15
  const [avatar, title] = useSessionStore((s) => [
@@ -26,12 +25,10 @@ const Chat = memo(() => {
26
25
  <title>{pageTitle}</title>
27
26
  </Head>
28
27
  <AppMobileLayout navBar={<Header />}>
29
- <ChatLayout>
30
- <Flexbox height={'calc(100vh - 44px)'} horizontal>
31
- <Conversation mobile />
32
- <SideBar mobile />
33
- </Flexbox>
34
- </ChatLayout>
28
+ <Flexbox height={'calc(100vh - 44px)'} horizontal>
29
+ <Conversation mobile />
30
+ <SideBar />
31
+ </Flexbox>
35
32
  </AppMobileLayout>
36
33
  </>
37
34
  );
@@ -0,0 +1,21 @@
1
+ import { ChatHeader, ChatHeaderTitle } from '@lobehub/ui';
2
+ import { ReactNode, memo } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+
5
+ import { useSessionStore } from '@/store/session';
6
+
7
+ const Header = memo<{ children: ReactNode }>(({ children }) => {
8
+ const { t } = useTranslation('setting');
9
+ const onBack = useSessionStore((s) => s.switchBackToChat);
10
+
11
+ return (
12
+ <ChatHeader
13
+ left={<ChatHeaderTitle title={t('header.session')} />}
14
+ onBackClick={onBack}
15
+ right={children}
16
+ showBackButton
17
+ />
18
+ );
19
+ });
20
+
21
+ export default Header;
@@ -0,0 +1,19 @@
1
+ import { MobileNavBar, MobileNavBarTitle } from '@lobehub/ui';
2
+ import Router from 'next/router';
3
+ import { type ReactNode, memo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ const Header = memo<{ children: ReactNode }>(({ children }) => {
7
+ const { t } = useTranslation('setting');
8
+
9
+ return (
10
+ <MobileNavBar
11
+ center={<MobileNavBarTitle title={t('header.session')} />}
12
+ onBackClick={() => Router.back()}
13
+ right={children}
14
+ showBackButton
15
+ />
16
+ );
17
+ });
18
+
19
+ export default Header;
@@ -0,0 +1,57 @@
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { Dropdown, MenuProps } from 'antd';
3
+ import { useResponsive } from 'antd-style';
4
+ import { HardDriveDownload, Share2 } from 'lucide-react';
5
+ import { memo, useMemo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ import { exportSingleAgent, exportSingleSession } from '@/helpers/export';
9
+ import { useSessionStore } from '@/store/session';
10
+
11
+ import Desktop from './Desktop';
12
+ import Mobile from './Mobile';
13
+
14
+ const Header = memo<{ mobile?: boolean }>(() => {
15
+ const { t } = useTranslation('setting');
16
+ const id = useSessionStore((s) => s.activeId);
17
+ const { mobile } = useResponsive();
18
+
19
+ const Render = mobile ? Mobile : Desktop;
20
+
21
+ const items = useMemo<MenuProps['items']>(
22
+ () => [
23
+ {
24
+ key: 'agent',
25
+ label: <div>{t('exportType.agent', { ns: 'common' })}</div>,
26
+ onClick: () => {
27
+ if (!id) return;
28
+
29
+ exportSingleAgent(id);
30
+ },
31
+ },
32
+ {
33
+ key: 'agentWithMessage',
34
+ label: <div>{t('exportType.agentWithMessage', { ns: 'common' })}</div>,
35
+ onClick: () => {
36
+ if (!id) return;
37
+
38
+ exportSingleSession(id);
39
+ },
40
+ },
41
+ ],
42
+ [],
43
+ );
44
+
45
+ const size = mobile ? undefined : { fontSize: 24 };
46
+
47
+ return (
48
+ <Render>
49
+ <ActionIcon icon={Share2} size={size} title={t('share', { ns: 'common' })} />
50
+ <Dropdown arrow={false} menu={{ items }} trigger={['click']}>
51
+ <ActionIcon icon={HardDriveDownload} size={size} title={t('export', { ns: 'common' })} />
52
+ </Dropdown>
53
+ </Render>
54
+ );
55
+ });
56
+
57
+ export default Header;
@@ -3,18 +3,14 @@ import isEqual from 'fast-deep-equal';
3
3
  import Head from 'next/head';
4
4
  import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
- import { Flexbox } from 'react-layout-kit';
7
6
 
8
- import SafeSpacing from '@/components/SafeSpacing';
9
- import { HEADER_HEIGHT } from '@/const/layoutTokens';
10
7
  import AgentSetting from '@/features/AgentSetting';
11
8
  import { useSessionStore } from '@/store/session';
12
9
  import { agentSelectors } from '@/store/session/selectors';
13
10
  import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
14
11
 
15
- import ChatLayout from '../layout';
16
- import Header from './Header';
17
- import Mobile from './mobile';
12
+ import DesktopLayout from './layout';
13
+ import MobileLayout from './layout.mobile';
18
14
 
19
15
  const EditPage = memo(() => {
20
16
  const { mobile } = useResponsive();
@@ -38,26 +34,14 @@ const EditPage = memo(() => {
38
34
  />
39
35
  );
40
36
 
37
+ const RenderLayout = mobile ? MobileLayout : DesktopLayout;
38
+
41
39
  return (
42
40
  <>
43
41
  <Head>
44
42
  <title>{pageTitle}</title>
45
43
  </Head>
46
- {mobile ? (
47
- <Mobile>
48
- <Flexbox gap={16} padding={16}>
49
- {settings}
50
- </Flexbox>
51
- </Mobile>
52
- ) : (
53
- <ChatLayout>
54
- <Header />
55
- <Flexbox align={'center'} flex={1} gap={16} padding={24} style={{ overflow: 'auto' }}>
56
- <SafeSpacing height={HEADER_HEIGHT - 16} />
57
- {settings}
58
- </Flexbox>
59
- </ChatLayout>
60
- )}
44
+ <RenderLayout>{settings}</RenderLayout>
61
45
  </>
62
46
  );
63
47
  });
@@ -0,0 +1,18 @@
1
+ import { PropsWithChildren, memo } from 'react';
2
+ import { Flexbox } from 'react-layout-kit';
3
+
4
+ import AppMobileLayout from '@/layout/AppMobileLayout';
5
+
6
+ import Header from './features/Header';
7
+
8
+ const MobileLayout = memo<PropsWithChildren>(({ children }) => {
9
+ return (
10
+ <AppMobileLayout navBar={<Header />}>
11
+ <Flexbox gap={16} padding={16}>
12
+ {children}
13
+ </Flexbox>
14
+ </AppMobileLayout>
15
+ );
16
+ });
17
+
18
+ export default MobileLayout;
@@ -0,0 +1,22 @@
1
+ import { PropsWithChildren, memo } from 'react';
2
+ import { Flexbox } from 'react-layout-kit';
3
+
4
+ import SafeSpacing from '@/components/SafeSpacing';
5
+ import { HEADER_HEIGHT } from '@/const/layoutTokens';
6
+
7
+ import ChatLayout from '../layout';
8
+ import Header from './features/Header';
9
+
10
+ const DesktopLayout = memo<PropsWithChildren>(({ children }) => {
11
+ return (
12
+ <ChatLayout>
13
+ <Header />
14
+ <Flexbox align={'center'} flex={1} gap={16} padding={24} style={{ overflow: 'auto' }}>
15
+ <SafeSpacing height={HEADER_HEIGHT - 16} />
16
+ {children}
17
+ </Flexbox>
18
+ </ChatLayout>
19
+ );
20
+ });
21
+
22
+ export default DesktopLayout;
@@ -0,0 +1,54 @@
1
+ import { ActionIcon, Logo, SearchBar } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { MessageSquarePlus } from 'lucide-react';
4
+ import Link from 'next/link';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Flexbox } from 'react-layout-kit';
8
+
9
+ import { useSessionStore } from '@/store/session';
10
+
11
+ export const useStyles = createStyles(({ css, token }) => ({
12
+ logo: css`
13
+ fill: ${token.colorText};
14
+ `,
15
+ top: css`
16
+ position: sticky;
17
+ top: 0;
18
+ `,
19
+ }));
20
+
21
+ const Header = memo(() => {
22
+ const { styles } = useStyles();
23
+ const { t } = useTranslation('common');
24
+ const [keywords, createSession] = useSessionStore((s) => [s.searchKeywords, s.createSession]);
25
+
26
+ return (
27
+ <Flexbox className={styles.top} gap={16} padding={16}>
28
+ <Flexbox distribution={'space-between'} horizontal>
29
+ <Link href={'/'}>
30
+ <Logo className={styles.logo} size={36} type={'text'} />
31
+ </Link>
32
+ <ActionIcon
33
+ icon={MessageSquarePlus}
34
+ onClick={createSession}
35
+ size={{ fontSize: 24 }}
36
+ style={{ flex: 'none' }}
37
+ title={t('newAgent')}
38
+ />
39
+ </Flexbox>
40
+ <SearchBar
41
+ allowClear
42
+ enableShortKey
43
+ onChange={(e) => useSessionStore.setState({ searchKeywords: e.target.value })}
44
+ placeholder={t('searchAgentPlaceholder')}
45
+ shortKey={'k'}
46
+ spotlight
47
+ type={'ghost'}
48
+ value={keywords}
49
+ />
50
+ </Flexbox>
51
+ );
52
+ });
53
+
54
+ export default Header;
@@ -0,0 +1,42 @@
1
+ import { ActionIcon, Logo, MobileNavBar } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { MessageSquarePlus, Settings2 } from 'lucide-react';
4
+ import Router from 'next/router';
5
+ import { memo } from 'react';
6
+
7
+ import AvatarWithUpload from '@/features/AvatarWithUpload';
8
+ import { useSessionStore } from '@/store/session';
9
+
10
+ export const useStyles = createStyles(({ css, token }) => ({
11
+ logo: css`
12
+ fill: ${token.colorText};
13
+ `,
14
+ top: css`
15
+ position: sticky;
16
+ top: 0;
17
+ `,
18
+ }));
19
+
20
+ const Header = memo(() => {
21
+ const [createSession] = useSessionStore((s) => [s.createSession]);
22
+
23
+ return (
24
+ <MobileNavBar
25
+ center={<Logo type={'text'} />}
26
+ left={<AvatarWithUpload size={28} style={{ marginLeft: 8 }} />}
27
+ right={
28
+ <>
29
+ <ActionIcon icon={MessageSquarePlus} onClick={createSession} />
30
+ <ActionIcon
31
+ icon={Settings2}
32
+ onClick={() => {
33
+ Router.push({ pathname: `/settings` });
34
+ }}
35
+ />
36
+ </>
37
+ }
38
+ />
39
+ );
40
+ });
41
+
42
+ export default Header;
@@ -0,0 +1,13 @@
1
+ import { useResponsive } from 'antd-style';
2
+ import { memo } from 'react';
3
+
4
+ import Desktop from './Desktop';
5
+ import Mobile from './Mobile';
6
+
7
+ const Header = memo(() => {
8
+ const { mobile } = useResponsive();
9
+ const Render = mobile ? Mobile : Desktop;
10
+ return <Render />;
11
+ });
12
+
13
+ export default Header;