@lobehub/chat 0.57.0 → 0.58.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.
- package/CHANGELOG.md +25 -0
- package/package.json +1 -1
- package/src/components/SafeSpacing/index.tsx +27 -0
- package/src/const/layoutTokens.ts +2 -0
- package/src/features/AvatarWithUpload/index.tsx +4 -3
- package/src/features/MobileTabBar/index.tsx +60 -0
- package/src/features/SideBar/TopActions.tsx +1 -1
- package/src/layout/AppMobileLayout.tsx +76 -0
- package/src/locales/default/common.ts +3 -1
- package/src/pages/chat/SessionList/Header.tsx +26 -2
- package/src/pages/chat/SessionList/index.tsx +10 -1
- package/src/pages/chat/[id]/index.page.tsx +19 -7
- package/src/pages/chat/[id]/mobile.tsx +31 -0
- package/src/pages/chat/[id]/setting/Header.tsx +25 -2
- package/src/pages/chat/[id]/setting/index.page.tsx +33 -16
- package/src/pages/chat/[id]/setting/mobile.tsx +11 -0
- package/src/pages/chat/features/Conversation/index.tsx +5 -5
- package/src/pages/chat/features/Header/Mobile.tsx +47 -0
- package/src/pages/chat/features/Header/PC.tsx +101 -0
- package/src/pages/chat/features/Header/index.tsx +7 -93
- package/src/pages/chat/features/Sidebar/Header.tsx +6 -4
- package/src/pages/chat/features/Sidebar/Mobile.tsx +36 -0
- package/src/pages/chat/features/Sidebar/SystemRole.tsx +2 -2
- package/src/pages/chat/features/Sidebar/index.tsx +33 -15
- package/src/pages/chat/index.page.tsx +14 -8
- package/src/pages/chat/layout.tsx +12 -8
- package/src/pages/chat/mobile.tsx +25 -0
- package/src/pages/settings/index.page.tsx +40 -8
- package/src/pages/settings/layout.tsx +5 -27
- package/src/pages/settings/mobile.tsx +20 -0
- package/src/pages/welcome/Banner/Hero.tsx +3 -5
- package/src/pages/welcome/Banner/index.tsx +5 -5
- package/src/pages/welcome/index.page.tsx +13 -4
- package/src/pages/welcome/mobile.tsx +20 -0
- package/src/pages/welcome/style.ts +2 -2
- package/src/store/global/initialState.ts +2 -0
- package/src/store/global/slices/common.ts +7 -0
- package/src/components/HeaderSpacing/index.tsx +0 -9
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { SiOpenai } from '@icons-pack/react-simple-icons';
|
|
2
|
+
import { ActionIcon, Avatar, ChatHeader, ChatHeaderTitle, Tag } from '@lobehub/ui';
|
|
3
|
+
import { Skeleton } from 'antd';
|
|
4
|
+
import { PanelRightClose, PanelRightOpen, Settings } from 'lucide-react';
|
|
5
|
+
import Router from 'next/router';
|
|
6
|
+
import { memo } from 'react';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
import { Flexbox } from 'react-layout-kit';
|
|
9
|
+
|
|
10
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
|
11
|
+
import { useGlobalStore } from '@/store/global';
|
|
12
|
+
import { agentSelectors, useSessionChatInit, useSessionStore } from '@/store/session';
|
|
13
|
+
|
|
14
|
+
import PluginTag from './PluginTag';
|
|
15
|
+
|
|
16
|
+
const Header = memo<{ settings?: boolean }>(({ settings = true }) => {
|
|
17
|
+
const init = useSessionChatInit();
|
|
18
|
+
|
|
19
|
+
const { t } = useTranslation('common');
|
|
20
|
+
|
|
21
|
+
const [id, title, description, avatar, backgroundColor, model, plugins] = useSessionStore((s) => [
|
|
22
|
+
s.activeId,
|
|
23
|
+
|
|
24
|
+
agentSelectors.currentAgentTitle(s),
|
|
25
|
+
agentSelectors.currentAgentDescription(s),
|
|
26
|
+
agentSelectors.currentAgentAvatar(s),
|
|
27
|
+
agentSelectors.currentAgentBackgroundColor(s),
|
|
28
|
+
agentSelectors.currentAgentModel(s),
|
|
29
|
+
agentSelectors.currentAgentPlugins(s),
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
const isInbox = id === INBOX_SESSION_ID;
|
|
33
|
+
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
34
|
+
s.preference.showChatSideBar,
|
|
35
|
+
s.toggleChatSideBar,
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
const displayTitle = isInbox ? t('inbox.title') : title;
|
|
39
|
+
const displayDesc = isInbox ? t('inbox.desc') : description;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<ChatHeader
|
|
43
|
+
left={
|
|
44
|
+
!init ? (
|
|
45
|
+
<Flexbox horizontal>
|
|
46
|
+
<Skeleton
|
|
47
|
+
active
|
|
48
|
+
avatar={{ shape: 'circle', size: 'default' }}
|
|
49
|
+
paragraph={false}
|
|
50
|
+
title={{ style: { margin: 0, marginTop: 8 }, width: 200 }}
|
|
51
|
+
/>
|
|
52
|
+
</Flexbox>
|
|
53
|
+
) : (
|
|
54
|
+
<Flexbox align={'flex-start'} gap={12} horizontal>
|
|
55
|
+
<Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
|
|
56
|
+
<ChatHeaderTitle
|
|
57
|
+
desc={displayDesc}
|
|
58
|
+
tag={
|
|
59
|
+
<>
|
|
60
|
+
<Tag icon={<SiOpenai size={'1em'} />}>{model}</Tag>
|
|
61
|
+
{plugins?.length > 0 && <PluginTag plugins={plugins} />}
|
|
62
|
+
</>
|
|
63
|
+
}
|
|
64
|
+
title={displayTitle}
|
|
65
|
+
/>
|
|
66
|
+
</Flexbox>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
right={
|
|
70
|
+
<>
|
|
71
|
+
{/*<ActionIcon*/}
|
|
72
|
+
{/* icon={Share2}*/}
|
|
73
|
+
{/* onClick={() => {*/}
|
|
74
|
+
{/* // genShareUrl();*/}
|
|
75
|
+
{/* }}*/}
|
|
76
|
+
{/* size={{ fontSize: 24 }}*/}
|
|
77
|
+
{/* title={t('share')}*/}
|
|
78
|
+
{/*/>*/}
|
|
79
|
+
<ActionIcon
|
|
80
|
+
icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
|
|
81
|
+
onClick={() => toggleConfig()}
|
|
82
|
+
size={{ fontSize: 24 }}
|
|
83
|
+
title={t('roleAndArchive')}
|
|
84
|
+
/>
|
|
85
|
+
{settings && (
|
|
86
|
+
<ActionIcon
|
|
87
|
+
icon={Settings}
|
|
88
|
+
onClick={() => {
|
|
89
|
+
Router.push(`/chat/${id}/setting`);
|
|
90
|
+
}}
|
|
91
|
+
size={{ fontSize: 24 }}
|
|
92
|
+
title={t('header.session', { ns: 'setting' })}
|
|
93
|
+
/>
|
|
94
|
+
)}
|
|
95
|
+
</>
|
|
96
|
+
}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export default Header;
|
|
@@ -1,101 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ActionIcon, Avatar, ChatHeader, ChatHeaderTitle, Tag } from '@lobehub/ui';
|
|
3
|
-
import { Skeleton } from 'antd';
|
|
4
|
-
import { PanelRightClose, PanelRightOpen, Settings } from 'lucide-react';
|
|
5
|
-
import Router from 'next/router';
|
|
1
|
+
import { useResponsive } from 'antd-style';
|
|
6
2
|
import { memo } from 'react';
|
|
7
|
-
import { useTranslation } from 'react-i18next';
|
|
8
|
-
import { Flexbox } from 'react-layout-kit';
|
|
9
3
|
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import { agentSelectors, useSessionChatInit, useSessionStore } from '@/store/session';
|
|
4
|
+
import Mobile from './Mobile';
|
|
5
|
+
import PC from './PC';
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
const Header = memo<{ settings?: boolean }>((props) => {
|
|
8
|
+
const { mobile } = useResponsive();
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
const init = useSessionChatInit();
|
|
10
|
+
if (mobile) return <Mobile {...props} />;
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const [id, title, description, avatar, backgroundColor, model, plugins] = useSessionStore((s) => [
|
|
22
|
-
s.activeId,
|
|
23
|
-
|
|
24
|
-
agentSelectors.currentAgentTitle(s),
|
|
25
|
-
agentSelectors.currentAgentDescription(s),
|
|
26
|
-
agentSelectors.currentAgentAvatar(s),
|
|
27
|
-
agentSelectors.currentAgentBackgroundColor(s),
|
|
28
|
-
agentSelectors.currentAgentModel(s),
|
|
29
|
-
agentSelectors.currentAgentPlugins(s),
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
const isInbox = id === INBOX_SESSION_ID;
|
|
33
|
-
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
34
|
-
s.preference.showChatSideBar,
|
|
35
|
-
s.toggleChatSideBar,
|
|
36
|
-
]);
|
|
37
|
-
|
|
38
|
-
const displayTitle = isInbox ? t('inbox.title') : title;
|
|
39
|
-
const displayDesc = isInbox ? t('inbox.desc') : description;
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<ChatHeader
|
|
43
|
-
left={
|
|
44
|
-
!init ? (
|
|
45
|
-
<Flexbox horizontal>
|
|
46
|
-
<Skeleton
|
|
47
|
-
active
|
|
48
|
-
avatar={{ shape: 'circle', size: 'default' }}
|
|
49
|
-
paragraph={false}
|
|
50
|
-
title={{ style: { margin: 0, marginTop: 8 }, width: 200 }}
|
|
51
|
-
/>
|
|
52
|
-
</Flexbox>
|
|
53
|
-
) : (
|
|
54
|
-
<Flexbox align={'flex-start'} gap={12} horizontal>
|
|
55
|
-
<Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
|
|
56
|
-
<ChatHeaderTitle
|
|
57
|
-
desc={displayDesc}
|
|
58
|
-
tag={
|
|
59
|
-
<>
|
|
60
|
-
<Tag icon={<SiOpenai size={'1em'} />}>{model}</Tag>
|
|
61
|
-
{plugins?.length > 0 && <PluginTag plugins={plugins} />}
|
|
62
|
-
</>
|
|
63
|
-
}
|
|
64
|
-
title={displayTitle}
|
|
65
|
-
/>
|
|
66
|
-
</Flexbox>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
right={
|
|
70
|
-
<>
|
|
71
|
-
{/*<ActionIcon*/}
|
|
72
|
-
{/* icon={Share2}*/}
|
|
73
|
-
{/* onClick={() => {*/}
|
|
74
|
-
{/* // genShareUrl();*/}
|
|
75
|
-
{/* }}*/}
|
|
76
|
-
{/* size={{ fontSize: 24 }}*/}
|
|
77
|
-
{/* title={t('share')}*/}
|
|
78
|
-
{/*/>*/}
|
|
79
|
-
<ActionIcon
|
|
80
|
-
icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
|
|
81
|
-
onClick={() => toggleConfig()}
|
|
82
|
-
size={{ fontSize: 24 }}
|
|
83
|
-
title={t('roleAndArchive')}
|
|
84
|
-
/>
|
|
85
|
-
{settings && (
|
|
86
|
-
<ActionIcon
|
|
87
|
-
icon={Settings}
|
|
88
|
-
onClick={() => {
|
|
89
|
-
Router.push(`/chat/${id}/setting`);
|
|
90
|
-
}}
|
|
91
|
-
size={{ fontSize: 24 }}
|
|
92
|
-
title={t('header.session', { ns: 'setting' })}
|
|
93
|
-
/>
|
|
94
|
-
)}
|
|
95
|
-
</>
|
|
96
|
-
}
|
|
97
|
-
/>
|
|
98
|
-
);
|
|
12
|
+
return <PC {...props} />;
|
|
99
13
|
});
|
|
100
14
|
|
|
101
15
|
export default Header;
|
|
@@ -2,24 +2,26 @@ import { createStyles } from 'antd-style';
|
|
|
2
2
|
import { type ReactNode, memo } from 'react';
|
|
3
3
|
import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
5
|
-
const useStyles = createStyles(
|
|
6
|
-
|
|
5
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
6
|
+
header: css`
|
|
7
7
|
z-index: 10;
|
|
8
8
|
box-shadow: 0 2px 6px ${token.colorBgLayout};
|
|
9
9
|
`,
|
|
10
|
-
);
|
|
10
|
+
}));
|
|
11
11
|
|
|
12
12
|
interface HeaderProps {
|
|
13
13
|
actions?: ReactNode;
|
|
14
|
+
mobile?: boolean;
|
|
14
15
|
title: string;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const Header = memo<HeaderProps>(({ title, actions }) => {
|
|
18
19
|
const { styles } = useStyles();
|
|
20
|
+
|
|
19
21
|
return (
|
|
20
22
|
<Flexbox
|
|
21
23
|
align={'center'}
|
|
22
|
-
className={styles}
|
|
24
|
+
className={styles.header}
|
|
23
25
|
distribution={'space-between'}
|
|
24
26
|
horizontal
|
|
25
27
|
padding={12}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
+
import { Drawer } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { X } from 'lucide-react';
|
|
5
|
+
import { PropsWithChildren, memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
|
|
8
|
+
import { useGlobalStore } from '@/store/global';
|
|
9
|
+
|
|
10
|
+
const Mobile = memo<PropsWithChildren>(({ children }) => {
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
13
|
+
s.preference.mobileShowTopic,
|
|
14
|
+
s.toggleMobileTopic,
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
const { t } = useTranslation('common');
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Drawer
|
|
21
|
+
bodyStyle={{ padding: 0 }}
|
|
22
|
+
closeIcon={<ActionIcon icon={X} size={{ blockSize: 32, fontSize: 20 }} />}
|
|
23
|
+
drawerStyle={{ background: theme.colorBgContainer }}
|
|
24
|
+
headerStyle={{ padding: '8px 4px' }}
|
|
25
|
+
height={'75vh'}
|
|
26
|
+
onClose={() => toggleConfig(false)}
|
|
27
|
+
open={showAgentSettings}
|
|
28
|
+
placement={'bottom'}
|
|
29
|
+
title={t('topic.title')}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</Drawer>
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default Mobile;
|
|
@@ -44,7 +44,7 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
44
44
|
`,
|
|
45
45
|
}));
|
|
46
46
|
|
|
47
|
-
const SystemRole = memo(() => {
|
|
47
|
+
const SystemRole = memo<{ mobile?: boolean }>(() => {
|
|
48
48
|
const [openModal, setOpenModal] = useState(false);
|
|
49
49
|
|
|
50
50
|
const { styles } = useStyles();
|
|
@@ -62,7 +62,7 @@ const SystemRole = memo(() => {
|
|
|
62
62
|
<ActionIcon
|
|
63
63
|
icon={Edit}
|
|
64
64
|
onClick={() => setOpenModal(true)}
|
|
65
|
-
size=
|
|
65
|
+
size={'small'}
|
|
66
66
|
title={t('edit')}
|
|
67
67
|
/>
|
|
68
68
|
}
|
|
@@ -5,20 +5,25 @@ import { memo } from 'react';
|
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Flexbox } from 'react-layout-kit';
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import SafeSpacing from '@/components/SafeSpacing';
|
|
9
9
|
import { CHAT_SIDEBAR_WIDTH } from '@/const/layoutTokens';
|
|
10
10
|
import { useGlobalStore } from '@/store/global';
|
|
11
11
|
|
|
12
|
+
import Mobile from './Mobile';
|
|
12
13
|
import SystemRole from './SystemRole';
|
|
13
14
|
import { Topic } from './Topic';
|
|
14
15
|
|
|
15
|
-
const useStyles = createStyles(({ cx, css, token, stylish }) => ({
|
|
16
|
+
const useStyles = createStyles(({ cx, css, token, stylish }, mobile: boolean) => ({
|
|
16
17
|
content: css`
|
|
17
18
|
display: flex;
|
|
18
19
|
flex-direction: column;
|
|
19
20
|
`,
|
|
20
21
|
drawer: cx(
|
|
21
|
-
|
|
22
|
+
mobile
|
|
23
|
+
? css`
|
|
24
|
+
background: ${token.colorBgLayout} !important;
|
|
25
|
+
`
|
|
26
|
+
: stylish.blurStrong,
|
|
22
27
|
css`
|
|
23
28
|
background: ${rgba(token.colorBgLayout, 0.4)};
|
|
24
29
|
`,
|
|
@@ -29,10 +34,11 @@ const useStyles = createStyles(({ cx, css, token, stylish }) => ({
|
|
|
29
34
|
}));
|
|
30
35
|
|
|
31
36
|
interface SideBarProps {
|
|
37
|
+
mobile?: boolean;
|
|
32
38
|
systemRole?: boolean;
|
|
33
39
|
}
|
|
34
|
-
const SideBar = memo<SideBarProps>(({ systemRole = true }) => {
|
|
35
|
-
const { styles } = useStyles();
|
|
40
|
+
const SideBar = memo<SideBarProps>(({ systemRole = true, mobile }) => {
|
|
41
|
+
const { styles } = useStyles(mobile);
|
|
36
42
|
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
37
43
|
s.preference.showChatSideBar,
|
|
38
44
|
s.toggleChatSideBar,
|
|
@@ -40,6 +46,23 @@ const SideBar = memo<SideBarProps>(({ systemRole = true }) => {
|
|
|
40
46
|
|
|
41
47
|
const { t } = useTranslation('common');
|
|
42
48
|
|
|
49
|
+
const topic = (
|
|
50
|
+
<Flexbox height={'100%'} style={{ overflow: 'hidden' }}>
|
|
51
|
+
<Flexbox padding={16}>
|
|
52
|
+
<SearchBar
|
|
53
|
+
placeholder={t('topic.searchPlaceholder')}
|
|
54
|
+
spotlight={!mobile}
|
|
55
|
+
type={mobile ? 'block' : 'ghost'}
|
|
56
|
+
/>
|
|
57
|
+
</Flexbox>
|
|
58
|
+
<Flexbox gap={16} paddingInline={16} style={{ overflowY: 'auto', position: 'relative' }}>
|
|
59
|
+
<Topic />
|
|
60
|
+
</Flexbox>
|
|
61
|
+
</Flexbox>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (mobile) return <Mobile>{topic}</Mobile>;
|
|
65
|
+
|
|
43
66
|
return (
|
|
44
67
|
<DraggablePanel
|
|
45
68
|
className={styles.drawer}
|
|
@@ -48,22 +71,17 @@ const SideBar = memo<SideBarProps>(({ systemRole = true }) => {
|
|
|
48
71
|
}}
|
|
49
72
|
expand={showAgentSettings}
|
|
50
73
|
minWidth={CHAT_SIDEBAR_WIDTH}
|
|
74
|
+
mode={'fixed'}
|
|
51
75
|
onExpandChange={toggleConfig}
|
|
52
76
|
placement={'right'}
|
|
53
77
|
>
|
|
54
78
|
<DraggablePanelContainer
|
|
55
79
|
style={{ flex: 'none', height: '100%', minWidth: CHAT_SIDEBAR_WIDTH }}
|
|
56
80
|
>
|
|
57
|
-
<
|
|
58
|
-
{systemRole && <SystemRole />}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<SearchBar placeholder={t('topic.searchPlaceholder')} spotlight type={'ghost'} />
|
|
62
|
-
</Flexbox>
|
|
63
|
-
<Flexbox gap={16} paddingInline={16} style={{ overflowY: 'auto', position: 'relative' }}>
|
|
64
|
-
<Topic />
|
|
65
|
-
</Flexbox>
|
|
66
|
-
</Flexbox>
|
|
81
|
+
<SafeSpacing />
|
|
82
|
+
{systemRole && <SystemRole mobile={mobile} />}
|
|
83
|
+
|
|
84
|
+
{topic}
|
|
67
85
|
</DraggablePanelContainer>
|
|
68
86
|
</DraggablePanel>
|
|
69
87
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useResponsive } from 'antd-style';
|
|
1
2
|
import Head from 'next/head';
|
|
2
3
|
import { memo } from 'react';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
@@ -11,10 +12,11 @@ import Conversation from './features/Conversation';
|
|
|
11
12
|
import Header from './features/Header';
|
|
12
13
|
import SideBar from './features/Sidebar';
|
|
13
14
|
import Layout from './layout';
|
|
15
|
+
import Mobile from './mobile';
|
|
14
16
|
|
|
15
17
|
const Chat = memo(() => {
|
|
16
18
|
const { t } = useTranslation('common');
|
|
17
|
-
|
|
19
|
+
const { mobile } = useResponsive();
|
|
18
20
|
const pageTitle = genSiteHeadTitle(t('inbox.title'));
|
|
19
21
|
|
|
20
22
|
useOnFinishHydrationSession(() => {
|
|
@@ -26,13 +28,17 @@ const Chat = memo(() => {
|
|
|
26
28
|
<Head>
|
|
27
29
|
<title>{pageTitle}</title>
|
|
28
30
|
</Head>
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
{mobile ? (
|
|
32
|
+
<Mobile />
|
|
33
|
+
) : (
|
|
34
|
+
<Layout>
|
|
35
|
+
<Header settings={false} />
|
|
36
|
+
<Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
|
|
37
|
+
<Conversation />
|
|
38
|
+
<SideBar systemRole={false} />
|
|
39
|
+
</Flexbox>
|
|
40
|
+
</Layout>
|
|
41
|
+
)}
|
|
36
42
|
</>
|
|
37
43
|
);
|
|
38
44
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useResponsive } from 'antd-style';
|
|
1
2
|
import { PropsWithChildren, memo } from 'react';
|
|
2
3
|
import { Flexbox } from 'react-layout-kit';
|
|
3
4
|
|
|
@@ -7,19 +8,22 @@ import { useSwitchSideBarOnInit } from '@/store/global';
|
|
|
7
8
|
import { Sessions } from './SessionList';
|
|
8
9
|
|
|
9
10
|
const ChatLayout = memo<PropsWithChildren>(({ children }) => {
|
|
11
|
+
const { mobile } = useResponsive();
|
|
10
12
|
useSwitchSideBarOnInit('chat');
|
|
11
13
|
|
|
12
14
|
return (
|
|
13
15
|
<AppLayout>
|
|
14
16
|
<Sessions />
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
{!mobile && (
|
|
18
|
+
<Flexbox
|
|
19
|
+
flex={1}
|
|
20
|
+
height={'100vh'}
|
|
21
|
+
id={'lobe-conversion-container'}
|
|
22
|
+
style={{ position: 'relative' }}
|
|
23
|
+
>
|
|
24
|
+
{children}
|
|
25
|
+
</Flexbox>
|
|
26
|
+
)}
|
|
23
27
|
</AppLayout>
|
|
24
28
|
);
|
|
25
29
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useTheme } from 'antd-style';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
|
|
4
|
+
import AppMobileLayout from '@/layout/AppMobileLayout';
|
|
5
|
+
import Header from '@/pages/chat/SessionList/Header';
|
|
6
|
+
import { useSwitchSideBarOnInit } from '@/store/global';
|
|
7
|
+
|
|
8
|
+
import { Sessions } from './SessionList';
|
|
9
|
+
|
|
10
|
+
const ChatMobileLayout = memo(() => {
|
|
11
|
+
useSwitchSideBarOnInit('chat');
|
|
12
|
+
const theme = useTheme();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<AppMobileLayout
|
|
16
|
+
navBar={<Header mobile={'navbar'} />}
|
|
17
|
+
showTabBar
|
|
18
|
+
style={{ background: theme.colorBgContainer }}
|
|
19
|
+
>
|
|
20
|
+
<Sessions mobile />
|
|
21
|
+
</AppMobileLayout>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default ChatMobileLayout;
|
|
@@ -1,21 +1,53 @@
|
|
|
1
|
+
import { useResponsive } from 'antd-style';
|
|
2
|
+
import Head from 'next/head';
|
|
1
3
|
import { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
2
5
|
import { Flexbox } from 'react-layout-kit';
|
|
3
6
|
|
|
4
|
-
import
|
|
7
|
+
import SafeSpacing from '@/components/SafeSpacing';
|
|
8
|
+
import { createI18nNext } from '@/locales/create';
|
|
9
|
+
import { useOnFinishHydrationGlobal, useSwitchSideBarOnInit } from '@/store/global';
|
|
10
|
+
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
5
11
|
|
|
6
12
|
import Header from './Header';
|
|
7
13
|
import Settings from './Settings';
|
|
8
14
|
import SettingLayout from './layout';
|
|
15
|
+
import Mobile from './mobile';
|
|
16
|
+
|
|
17
|
+
const initI18n = createI18nNext({ namespace: 'setting' });
|
|
9
18
|
|
|
10
19
|
const Setting = memo(() => {
|
|
20
|
+
const { mobile } = useResponsive();
|
|
21
|
+
const { t } = useTranslation('setting');
|
|
22
|
+
const pageTitle = genSiteHeadTitle(t('header.global'));
|
|
23
|
+
|
|
24
|
+
useSwitchSideBarOnInit('settings');
|
|
25
|
+
|
|
26
|
+
useOnFinishHydrationGlobal(() => {
|
|
27
|
+
initI18n.then(() => {});
|
|
28
|
+
});
|
|
29
|
+
|
|
11
30
|
return (
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
31
|
+
<>
|
|
32
|
+
<Head>
|
|
33
|
+
<title>{pageTitle}</title>
|
|
34
|
+
</Head>
|
|
35
|
+
{mobile ? (
|
|
36
|
+
<Mobile>
|
|
37
|
+
<Flexbox align={'center'} padding={16} style={{ overflow: 'auto' }}>
|
|
38
|
+
<Settings />
|
|
39
|
+
</Flexbox>
|
|
40
|
+
</Mobile>
|
|
41
|
+
) : (
|
|
42
|
+
<SettingLayout>
|
|
43
|
+
<Header />
|
|
44
|
+
<Flexbox align={'center'} flex={1} padding={24} style={{ overflow: 'auto' }}>
|
|
45
|
+
<SafeSpacing />
|
|
46
|
+
<Settings />
|
|
47
|
+
</Flexbox>
|
|
48
|
+
</SettingLayout>
|
|
49
|
+
)}
|
|
50
|
+
</>
|
|
19
51
|
);
|
|
20
52
|
});
|
|
21
53
|
|
|
@@ -1,37 +1,15 @@
|
|
|
1
|
-
import Head from 'next/head';
|
|
2
1
|
import { ReactNode, memo } from 'react';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
4
2
|
import { Flexbox } from 'react-layout-kit';
|
|
5
3
|
|
|
6
|
-
import
|
|
7
|
-
import { createI18nNext } from '@/locales/create';
|
|
8
|
-
import { useOnFinishHydrationGlobal, useSwitchSideBarOnInit } from '@/store/global';
|
|
9
|
-
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
10
|
-
|
|
11
|
-
const initI18n = createI18nNext({ namespace: 'setting' });
|
|
4
|
+
import AppLayout from '@/layout/AppLayout';
|
|
12
5
|
|
|
13
6
|
const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
|
|
14
|
-
const { t } = useTranslation('setting');
|
|
15
|
-
const pageTitle = genSiteHeadTitle(t('header.global'));
|
|
16
|
-
|
|
17
|
-
useSwitchSideBarOnInit('settings');
|
|
18
|
-
|
|
19
|
-
useOnFinishHydrationGlobal(() => {
|
|
20
|
-
initI18n.then(() => {});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
7
|
return (
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
</Head>
|
|
28
|
-
<Flexbox horizontal width={'100%'}>
|
|
29
|
-
<SideBar />
|
|
30
|
-
<Flexbox flex={1} height={'100vh'} style={{ position: 'relative' }}>
|
|
31
|
-
{children}
|
|
32
|
-
</Flexbox>
|
|
8
|
+
<AppLayout>
|
|
9
|
+
<Flexbox flex={1} height={'100vh'} style={{ position: 'relative' }}>
|
|
10
|
+
{children}
|
|
33
11
|
</Flexbox>
|
|
34
|
-
|
|
12
|
+
</AppLayout>
|
|
35
13
|
);
|
|
36
14
|
});
|
|
37
15
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MobileNavBar, MobileNavBarTitle } from '@lobehub/ui';
|
|
2
|
+
import { ReactNode, memo } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
import AppMobileLayout from '@/layout/AppMobileLayout';
|
|
6
|
+
|
|
7
|
+
const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
|
|
8
|
+
const { t } = useTranslation('setting');
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<AppMobileLayout
|
|
12
|
+
navBar={<MobileNavBar center={<MobileNavBarTitle title={t('header.global')} />} />}
|
|
13
|
+
showTabBar
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</AppMobileLayout>
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default SettingLayout;
|
|
@@ -21,12 +21,10 @@ const Hero = memo<{ width: number }>(({ width }) => {
|
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<>
|
|
24
|
-
<LogoThree
|
|
25
|
-
size={size.logo}
|
|
26
|
-
style={{ marginBottom: -size.logo / 40, marginTop: -size.logo / 5 }}
|
|
27
|
-
/>
|
|
24
|
+
<LogoThree size={size.logo} style={{ marginTop: -size.logo / 5 }} />
|
|
28
25
|
<div className={styles.title} style={{ fontSize: size.title }}>
|
|
29
|
-
|
|
26
|
+
<span style={mobile ? { fontSize: '1.2em' } : {}}>LobeChat</span>
|
|
27
|
+
{mobile ? <br /> : ' '}
|
|
30
28
|
{t('slogan.title')}
|
|
31
29
|
</div>
|
|
32
30
|
<div className={styles.desc} style={{ fontSize: size.desc }}>
|
|
@@ -13,7 +13,7 @@ import { useImportConfig } from '@/hooks/useImportConfig';
|
|
|
13
13
|
import { useStyles } from '../style';
|
|
14
14
|
import Hero from './Hero';
|
|
15
15
|
|
|
16
|
-
const Banner = memo(() => {
|
|
16
|
+
const Banner = memo<{ mobile?: boolean }>(() => {
|
|
17
17
|
const { importConfig } = useImportConfig();
|
|
18
18
|
const ref = useRef(null);
|
|
19
19
|
const domSize = useSize(ref);
|
|
@@ -28,12 +28,15 @@ const Banner = memo(() => {
|
|
|
28
28
|
}, []);
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
|
-
<Flexbox height={'80vh'} style={{
|
|
31
|
+
<Flexbox height={'80vh'} style={{ paddingTop: '10vh' }}>
|
|
32
32
|
<GridShowcase>
|
|
33
33
|
<div className={styles.container} ref={ref}>
|
|
34
34
|
<Hero width={width} />
|
|
35
35
|
</div>
|
|
36
36
|
<Flexbox gap={16} horizontal style={{ marginTop: 16 }}>
|
|
37
|
+
<Upload maxCount={1} onChange={handleImport} showUploadList={false}>
|
|
38
|
+
<Button size={'large'}>{t('button.import')}</Button>
|
|
39
|
+
</Upload>
|
|
37
40
|
<Link href={'/chat'}>
|
|
38
41
|
<Button size={'large'} type={'primary'}>
|
|
39
42
|
<Flexbox align={'center'} gap={4} horizontal>
|
|
@@ -42,9 +45,6 @@ const Banner = memo(() => {
|
|
|
42
45
|
</Flexbox>
|
|
43
46
|
</Button>
|
|
44
47
|
</Link>
|
|
45
|
-
<Upload maxCount={1} onChange={handleImport} showUploadList={false}>
|
|
46
|
-
<Button size={'large'}>{t('button.import')}</Button>
|
|
47
|
-
</Upload>
|
|
48
48
|
</Flexbox>
|
|
49
49
|
</GridShowcase>
|
|
50
50
|
{/*TODO:暂时隐藏,待模板完成后再补回*/}
|