@lobehub/chat 1.116.1 → 1.116.2
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 +17 -0
- package/changelog/v1.json +5 -0
- package/package.json +1 -1
- package/src/app/[variants]/(main)/_layout/Desktop/DesktopLayoutContainer.tsx +30 -0
- package/src/app/[variants]/(main)/_layout/Desktop/index.tsx +6 -19
- package/src/app/[variants]/(main)/chat/_layout/Desktop/SessionPanel.tsx +25 -21
- package/src/app/[variants]/(main)/settings/_layout/Desktop/Header.tsx +28 -3
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +17 -24
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.116.2](https://github.com/lobehub/lobe-chat/compare/v1.116.1...v1.116.2)
|
6
|
+
|
7
|
+
<sup>Released on **2025-08-28**</sup>
|
8
|
+
|
9
|
+
<br/>
|
10
|
+
|
11
|
+
<details>
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
13
|
+
|
14
|
+
</details>
|
15
|
+
|
16
|
+
<div align="right">
|
17
|
+
|
18
|
+
[](#readme-top)
|
19
|
+
|
20
|
+
</div>
|
21
|
+
|
5
22
|
### [Version 1.116.1](https://github.com/lobehub/lobe-chat/compare/v1.116.0...v1.116.1)
|
6
23
|
|
7
24
|
<sup>Released on **2025-08-27**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.116.
|
3
|
+
"version": "1.116.2",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { useTheme } from 'antd-style';
|
2
|
+
import { usePathname } from 'next/navigation';
|
3
|
+
import { PropsWithChildren, memo } from 'react';
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
5
|
+
|
6
|
+
import SideBar from './SideBar';
|
7
|
+
|
8
|
+
const DesktopLayoutContainer = memo<PropsWithChildren>(({ children }) => {
|
9
|
+
const theme = useTheme();
|
10
|
+
const pathname = usePathname();
|
11
|
+
const hideSideBar = pathname.startsWith('/settings');
|
12
|
+
return (
|
13
|
+
<>
|
14
|
+
{!hideSideBar && <SideBar />}
|
15
|
+
<Flexbox
|
16
|
+
style={{
|
17
|
+
background: theme.colorBgLayout,
|
18
|
+
borderInlineStart: `1px solid ${theme.colorBorderSecondary}`,
|
19
|
+
borderStartStartRadius: !hideSideBar ? 12 : undefined,
|
20
|
+
borderTop: `1px solid ${theme.colorBorderSecondary}`,
|
21
|
+
overflow: 'hidden',
|
22
|
+
}}
|
23
|
+
width={'100%'}
|
24
|
+
>
|
25
|
+
{children}
|
26
|
+
</Flexbox>
|
27
|
+
</>
|
28
|
+
);
|
29
|
+
});
|
30
|
+
export default DesktopLayoutContainer;
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
import { useTheme } from 'antd-style';
|
4
4
|
import dynamic from 'next/dynamic';
|
5
|
-
import { usePathname } from 'next/navigation';
|
6
5
|
import { PropsWithChildren, Suspense, memo } from 'react';
|
7
6
|
import { HotkeysProvider } from 'react-hotkeys-hook';
|
8
7
|
import { Flexbox } from 'react-layout-kit';
|
@@ -15,6 +14,7 @@ import { usePlatform } from '@/hooks/usePlatform';
|
|
15
14
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
16
15
|
import { HotkeyScopeEnum } from '@/types/hotkey';
|
17
16
|
|
17
|
+
import DesktopLayoutContainer from './DesktopLayoutContainer';
|
18
18
|
import RegisterHotkeys from './RegisterHotkeys';
|
19
19
|
import SideBar from './SideBar';
|
20
20
|
|
@@ -24,11 +24,7 @@ const Layout = memo<PropsWithChildren>(({ children }) => {
|
|
24
24
|
const { isPWA } = usePlatform();
|
25
25
|
const theme = useTheme();
|
26
26
|
|
27
|
-
const pathname = usePathname();
|
28
27
|
const { showCloudPromotion } = useServerConfigStore(featureFlagsSelectors);
|
29
|
-
|
30
|
-
// setting page not show sidebar
|
31
|
-
const hideSideBar = isDesktop && pathname.startsWith('/settings');
|
32
28
|
return (
|
33
29
|
<HotkeysProvider initiallyActiveScopes={[HotkeyScopeEnum.Global]}>
|
34
30
|
{isDesktop && <TitleBar />}
|
@@ -48,22 +44,13 @@ const Layout = memo<PropsWithChildren>(({ children }) => {
|
|
48
44
|
}}
|
49
45
|
width={'100%'}
|
50
46
|
>
|
51
|
-
{!hideSideBar && <SideBar />}
|
52
47
|
{isDesktop ? (
|
53
|
-
<
|
54
|
-
style={{
|
55
|
-
background: theme.colorBgLayout,
|
56
|
-
borderInlineStart: `1px solid ${theme.colorBorderSecondary}`,
|
57
|
-
borderStartStartRadius: !hideSideBar ? 12 : undefined,
|
58
|
-
borderTop: `1px solid ${theme.colorBorderSecondary}`,
|
59
|
-
overflow: 'hidden',
|
60
|
-
}}
|
61
|
-
width={'100%'}
|
62
|
-
>
|
63
|
-
{children}
|
64
|
-
</Flexbox>
|
48
|
+
<DesktopLayoutContainer>{children}</DesktopLayoutContainer>
|
65
49
|
) : (
|
66
|
-
|
50
|
+
<>
|
51
|
+
<SideBar />
|
52
|
+
{children}
|
53
|
+
</>
|
67
54
|
)}
|
68
55
|
</Flexbox>
|
69
56
|
<HotkeyHelperPanel />
|
@@ -3,7 +3,7 @@
|
|
3
3
|
import { DraggablePanel, DraggablePanelContainer, type DraggablePanelProps } from '@lobehub/ui';
|
4
4
|
import { createStyles, useResponsive } from 'antd-style';
|
5
5
|
import isEqual from 'fast-deep-equal';
|
6
|
-
import { PropsWithChildren, memo, useEffect, useState } from 'react';
|
6
|
+
import { PropsWithChildren, memo, useEffect, useMemo, useState } from 'react';
|
7
7
|
|
8
8
|
import { withSuspense } from '@/components/withSuspense';
|
9
9
|
import { FOLDER_WIDTH } from '@/const/layoutTokens';
|
@@ -69,26 +69,30 @@ const SessionPanel = memo<PropsWithChildren>(({ children }) => {
|
|
69
69
|
if (!md) updatePreference({ showSessionPanel: false });
|
70
70
|
}, [md, cacheExpand]);
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
{
|
89
|
-
|
90
|
-
|
91
|
-
|
72
|
+
const SessionPanel = useMemo(() => {
|
73
|
+
return (
|
74
|
+
<DraggablePanel
|
75
|
+
className={styles.panel}
|
76
|
+
defaultSize={{ width: tmpWidth }}
|
77
|
+
// 当进入 pin 模式下,不可展开
|
78
|
+
expand={!isPinned && sessionExpandable}
|
79
|
+
expandable={!isPinned}
|
80
|
+
maxWidth={400}
|
81
|
+
minWidth={FOLDER_WIDTH}
|
82
|
+
mode={md ? 'fixed' : 'float'}
|
83
|
+
onExpandChange={handleExpand}
|
84
|
+
onSizeChange={handleSizeChange}
|
85
|
+
placement="left"
|
86
|
+
size={{ height: '100%', width: sessionsWidth }}
|
87
|
+
>
|
88
|
+
<DraggablePanelContainer style={{ flex: 'none', height: '100%', minWidth: FOLDER_WIDTH }}>
|
89
|
+
{children}
|
90
|
+
</DraggablePanelContainer>
|
91
|
+
</DraggablePanel>
|
92
|
+
);
|
93
|
+
}, [sessionsWidth, md, isPinned, sessionExpandable, tmpWidth]);
|
94
|
+
|
95
|
+
return SessionPanel;
|
92
96
|
});
|
93
97
|
|
94
98
|
export default withSuspense(SessionPanel);
|
@@ -1,14 +1,20 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
|
-
import { ActionIcon } from '@lobehub/ui';
|
3
|
+
import { ActionIcon, Tag } from '@lobehub/ui';
|
4
4
|
import { ChatHeader } from '@lobehub/ui/chat';
|
5
5
|
import { Drawer, type DrawerProps } from 'antd';
|
6
6
|
import { createStyles } from 'antd-style';
|
7
7
|
import { Menu } from 'lucide-react';
|
8
|
+
import { usePathname } from 'next/navigation';
|
8
9
|
import { ReactNode, memo, useState } from 'react';
|
10
|
+
import { useTranslation } from 'react-i18next';
|
9
11
|
import { Flexbox } from 'react-layout-kit';
|
10
12
|
|
11
13
|
import BrandWatermark from '@/components/BrandWatermark';
|
14
|
+
// 新增:引入 SettingsTabs
|
15
|
+
import { useActiveSettingsKey } from '@/hooks/useActiveTabKey';
|
16
|
+
import { useProviderName } from '@/hooks/useProviderName';
|
17
|
+
import { SettingsTabs } from '@/store/global/initialState';
|
12
18
|
|
13
19
|
const useStyles = createStyles(({ token, css }) => ({
|
14
20
|
container: css`
|
@@ -26,12 +32,31 @@ const useStyles = createStyles(({ token, css }) => ({
|
|
26
32
|
|
27
33
|
interface HeaderProps extends Pick<DrawerProps, 'getContainer'> {
|
28
34
|
children: ReactNode;
|
29
|
-
title
|
35
|
+
title?: ReactNode;
|
30
36
|
}
|
31
37
|
|
32
38
|
const Header = memo<HeaderProps>(({ children, getContainer, title }) => {
|
33
39
|
const [open, setOpen] = useState(false);
|
34
40
|
const { styles, theme } = useStyles();
|
41
|
+
const activeKey = useActiveSettingsKey();
|
42
|
+
const providerName = useProviderName(activeKey);
|
43
|
+
|
44
|
+
const pathname = usePathname();
|
45
|
+
const { t } = useTranslation('setting');
|
46
|
+
|
47
|
+
const isProvider = pathname.includes('/settings/provider/');
|
48
|
+
const dynamicTitle = title ? (
|
49
|
+
title
|
50
|
+
) : (
|
51
|
+
<>
|
52
|
+
{isProvider ? providerName : t(`tab.${activeKey}`)}
|
53
|
+
{activeKey === SettingsTabs.Sync && (
|
54
|
+
<Tag bordered={false} color={'gold'}>
|
55
|
+
{t('tab.experiment')}
|
56
|
+
</Tag>
|
57
|
+
)}
|
58
|
+
</>
|
59
|
+
);
|
35
60
|
|
36
61
|
return (
|
37
62
|
<>
|
@@ -47,7 +72,7 @@ const Header = memo<HeaderProps>(({ children, getContainer, title }) => {
|
|
47
72
|
onClick={() => setOpen(true)}
|
48
73
|
size={{ blockSize: 32, size: 18 }}
|
49
74
|
/>
|
50
|
-
{
|
75
|
+
{dynamicTitle}
|
51
76
|
</Flexbox>
|
52
77
|
}
|
53
78
|
/>
|
@@ -1,18 +1,13 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
|
-
import { Tag } from '@lobehub/ui';
|
4
3
|
import { useResponsive, useTheme } from 'antd-style';
|
5
4
|
import { usePathname } from 'next/navigation';
|
6
|
-
import { memo, useRef } from 'react';
|
7
|
-
import { useTranslation } from 'react-i18next';
|
5
|
+
import { PropsWithChildren, memo, useEffect, useRef } from 'react';
|
8
6
|
import { Flexbox } from 'react-layout-kit';
|
9
7
|
|
10
8
|
import InitClientDB from '@/features/InitClientDB';
|
11
9
|
import Footer from '@/features/Setting/Footer';
|
12
10
|
import SettingContainer from '@/features/Setting/SettingContainer';
|
13
|
-
import { useActiveSettingsKey } from '@/hooks/useActiveTabKey';
|
14
|
-
import { useProviderName } from '@/hooks/useProviderName';
|
15
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
16
11
|
|
17
12
|
import { LayoutProps } from '../type';
|
18
13
|
import Header from './Header';
|
@@ -20,17 +15,25 @@ import SideBar from './SideBar';
|
|
20
15
|
|
21
16
|
const SKIP_PATHS = ['/settings/provider', '/settings/agent'];
|
22
17
|
|
18
|
+
const ContentContainer = memo<PropsWithChildren>(({ children }) => {
|
19
|
+
const pathname = usePathname();
|
20
|
+
const isSkip = SKIP_PATHS.some((path) => pathname.includes(path));
|
21
|
+
|
22
|
+
return isSkip ? (
|
23
|
+
children
|
24
|
+
) : (
|
25
|
+
<SettingContainer addonAfter={<Footer />}>{children}</SettingContainer>
|
26
|
+
);
|
27
|
+
});
|
28
|
+
|
23
29
|
const Layout = memo<LayoutProps>(({ children, category }) => {
|
24
30
|
const ref = useRef<any>(null);
|
25
31
|
const { md = true } = useResponsive();
|
26
|
-
const { t } = useTranslation('setting');
|
27
|
-
const activeKey = useActiveSettingsKey();
|
28
32
|
const theme = useTheme();
|
29
|
-
const pathname = usePathname();
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
useEffect(() => {
|
35
|
+
console.log('settings render');
|
36
|
+
});
|
34
37
|
|
35
38
|
return (
|
36
39
|
<Flexbox
|
@@ -42,19 +45,9 @@ const Layout = memo<LayoutProps>(({ children, category }) => {
|
|
42
45
|
{md ? (
|
43
46
|
<SideBar>{category}</SideBar>
|
44
47
|
) : (
|
45
|
-
<Header
|
46
|
-
getContainer={() => ref.current}
|
47
|
-
title={
|
48
|
-
<>
|
49
|
-
{isProvider ? providerName : t(`tab.${activeKey}`)}
|
50
|
-
{activeKey === SettingsTabs.Sync && <Tag color={'gold'}>{t('tab.experiment')}</Tag>}
|
51
|
-
</>
|
52
|
-
}
|
53
|
-
>
|
54
|
-
{category}
|
55
|
-
</Header>
|
48
|
+
<Header getContainer={() => ref.current!}>{category}</Header>
|
56
49
|
)}
|
57
|
-
|
50
|
+
<ContentContainer>{children}</ContentContainer>
|
58
51
|
<InitClientDB />
|
59
52
|
</Flexbox>
|
60
53
|
);
|