@lobehub/lobehub 2.0.0-next.240 → 2.0.0-next.241
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/apps/desktop/resources/locales/ar/menu.json +5 -1
- package/apps/desktop/resources/locales/bg-BG/menu.json +5 -1
- package/apps/desktop/resources/locales/de-DE/menu.json +5 -1
- package/apps/desktop/resources/locales/es-ES/menu.json +5 -1
- package/apps/desktop/resources/locales/fa-IR/menu.json +5 -1
- package/apps/desktop/resources/locales/fr-FR/menu.json +5 -1
- package/apps/desktop/resources/locales/it-IT/menu.json +5 -1
- package/apps/desktop/resources/locales/ja-JP/menu.json +5 -1
- package/apps/desktop/resources/locales/ko-KR/menu.json +5 -1
- package/apps/desktop/resources/locales/nl-NL/menu.json +5 -1
- package/apps/desktop/resources/locales/pl-PL/menu.json +5 -1
- package/apps/desktop/resources/locales/pt-BR/menu.json +5 -1
- package/apps/desktop/resources/locales/ru-RU/menu.json +5 -1
- package/apps/desktop/resources/locales/tr-TR/menu.json +5 -1
- package/apps/desktop/resources/locales/vi-VN/menu.json +5 -1
- package/apps/desktop/resources/locales/zh-CN/menu.json +5 -1
- package/apps/desktop/resources/locales/zh-TW/menu.json +5 -1
- package/apps/desktop/src/main/locales/default/menu.ts +5 -1
- package/apps/desktop/src/main/menus/impls/linux.ts +30 -0
- package/apps/desktop/src/main/menus/impls/macOS.test.ts +17 -0
- package/apps/desktop/src/main/menus/impls/macOS.ts +33 -0
- package/apps/desktop/src/main/menus/impls/windows.ts +30 -0
- package/changelog/v1.json +5 -0
- package/locales/ar/electron.json +24 -0
- package/locales/bg-BG/electron.json +24 -0
- package/locales/de-DE/electron.json +24 -0
- package/locales/en-US/electron.json +24 -0
- package/locales/es-ES/electron.json +24 -0
- package/locales/fa-IR/electron.json +24 -0
- package/locales/fr-FR/electron.json +24 -0
- package/locales/it-IT/electron.json +24 -0
- package/locales/ja-JP/electron.json +24 -0
- package/locales/ko-KR/electron.json +24 -0
- package/locales/nl-NL/electron.json +24 -0
- package/locales/pl-PL/electron.json +24 -0
- package/locales/pt-BR/electron.json +24 -0
- package/locales/ru-RU/electron.json +24 -0
- package/locales/tr-TR/electron.json +24 -0
- package/locales/vi-VN/electron.json +24 -0
- package/locales/zh-CN/electron.json +24 -0
- package/locales/zh-TW/electron.json +24 -0
- package/package.json +1 -1
- package/packages/electron-client-ipc/src/events/navigation.ts +12 -0
- package/src/components/PageTitle/index.tsx +11 -1
- package/src/features/ElectronTitlebar/NavigationBar/RecentlyViewed.tsx +137 -0
- package/src/features/ElectronTitlebar/NavigationBar/index.tsx +86 -0
- package/src/features/ElectronTitlebar/helpers/routeMetadata.ts +214 -0
- package/src/features/ElectronTitlebar/hooks/useNavigationHistory.ts +152 -0
- package/src/features/ElectronTitlebar/index.tsx +13 -5
- package/src/features/NavHeader/index.tsx +4 -2
- package/src/features/NavPanel/components/NavPanelDraggable.tsx +174 -0
- package/src/features/NavPanel/hooks/useNavPanel.ts +11 -35
- package/src/features/NavPanel/index.tsx +2 -126
- package/src/hooks/useTypeScriptHappyCallback.ts +7 -0
- package/src/locales/default/electron.ts +24 -0
- package/src/store/electron/actions/navigationHistory.ts +247 -0
- package/src/store/electron/initialState.ts +7 -1
- package/src/store/electron/store.ts +9 -2
- package/src/store/global/selectors/systemStatus.ts +4 -1
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { DraggablePanel } from '@lobehub/ui';
|
|
4
|
-
import { createStaticStyles, cssVar } from 'antd-style';
|
|
5
|
-
import { AnimatePresence, motion } from 'motion/react';
|
|
6
3
|
import {
|
|
7
4
|
type PropsWithChildren,
|
|
8
5
|
type ReactNode,
|
|
@@ -11,14 +8,8 @@ import {
|
|
|
11
8
|
useSyncExternalStore,
|
|
12
9
|
} from 'react';
|
|
13
10
|
|
|
14
|
-
import { USER_DROPDOWN_ICON_ID } from '@/app/[variants]/(main)/home/_layout/Header/components/User';
|
|
15
|
-
import { isDesktop } from '@/const/version';
|
|
16
|
-
import { TOGGLE_BUTTON_ID } from '@/features/NavPanel/ToggleLeftPanelButton';
|
|
17
|
-
import { isMacOS } from '@/utils/platform';
|
|
18
|
-
|
|
19
11
|
import Sidebar from '../../app/[variants]/(main)/home/_layout/Sidebar';
|
|
20
|
-
import {
|
|
21
|
-
import { useNavPanel } from './hooks/useNavPanel';
|
|
12
|
+
import { NavPanelDraggable } from './components/NavPanelDraggable';
|
|
22
13
|
|
|
23
14
|
export const NAV_PANEL_RIGHT_DRAWER_ID = 'nav-panel-drawer';
|
|
24
15
|
|
|
@@ -41,82 +32,7 @@ const setNavPanelSnapshot = (snapshot: NavPanelSnapshot) => {
|
|
|
41
32
|
listeners.forEach((listener) => listener());
|
|
42
33
|
};
|
|
43
34
|
|
|
44
|
-
export const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
45
|
-
content: css`
|
|
46
|
-
position: relative;
|
|
47
|
-
|
|
48
|
-
overflow: hidden;
|
|
49
|
-
display: flex;
|
|
50
|
-
|
|
51
|
-
height: 100%;
|
|
52
|
-
min-height: 100%;
|
|
53
|
-
max-height: 100%;
|
|
54
|
-
`,
|
|
55
|
-
inner: css`
|
|
56
|
-
position: relative;
|
|
57
|
-
inset: 0;
|
|
58
|
-
|
|
59
|
-
overflow: hidden;
|
|
60
|
-
flex: 1;
|
|
61
|
-
flex-direction: column;
|
|
62
|
-
|
|
63
|
-
min-width: 240px;
|
|
64
|
-
`,
|
|
65
|
-
panel: css`
|
|
66
|
-
user-select: none;
|
|
67
|
-
height: 100%;
|
|
68
|
-
color: ${cssVar.colorTextSecondary};
|
|
69
|
-
background: ${isDesktop && isMacOS() ? 'transparent' : cssVar.colorBgLayout};
|
|
70
|
-
|
|
71
|
-
* {
|
|
72
|
-
user-select: none;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
#${TOGGLE_BUTTON_ID} {
|
|
76
|
-
width: 0 !important;
|
|
77
|
-
opacity: 0;
|
|
78
|
-
transition:
|
|
79
|
-
opacity,
|
|
80
|
-
width 0.2s ${cssVar.motionEaseOut};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
#${USER_DROPDOWN_ICON_ID} {
|
|
84
|
-
width: 0 !important;
|
|
85
|
-
opacity: 0;
|
|
86
|
-
transition:
|
|
87
|
-
opacity,
|
|
88
|
-
width 0.2s ${cssVar.motionEaseOut};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
#${BACK_BUTTON_ID} {
|
|
92
|
-
width: 0 !important;
|
|
93
|
-
opacity: 0;
|
|
94
|
-
transition: all 0.2s ${cssVar.motionEaseOut};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
&:hover {
|
|
98
|
-
#${TOGGLE_BUTTON_ID} {
|
|
99
|
-
width: 32px !important;
|
|
100
|
-
opacity: 1;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
#${USER_DROPDOWN_ICON_ID} {
|
|
104
|
-
width: 14px !important;
|
|
105
|
-
opacity: 1;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
&:hover {
|
|
109
|
-
#${BACK_BUTTON_ID} {
|
|
110
|
-
width: 24px !important;
|
|
111
|
-
opacity: 1;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
`,
|
|
116
|
-
}));
|
|
117
|
-
|
|
118
35
|
const NavPanel = memo(() => {
|
|
119
|
-
const { expand, handleSizeChange, width, togglePanel } = useNavPanel();
|
|
120
36
|
const panelContent = useSyncExternalStore(
|
|
121
37
|
subscribeNavPanel,
|
|
122
38
|
getNavPanelSnapshot,
|
|
@@ -128,47 +44,7 @@ const NavPanel = memo(() => {
|
|
|
128
44
|
|
|
129
45
|
return (
|
|
130
46
|
<>
|
|
131
|
-
<
|
|
132
|
-
className={styles.panel}
|
|
133
|
-
classNames={{
|
|
134
|
-
content: styles.content,
|
|
135
|
-
}}
|
|
136
|
-
defaultSize={{ height: '100%', width }}
|
|
137
|
-
expand={expand}
|
|
138
|
-
expandable={false}
|
|
139
|
-
maxWidth={400}
|
|
140
|
-
minWidth={240}
|
|
141
|
-
onExpandChange={(expand) => togglePanel(expand)}
|
|
142
|
-
onSizeChange={handleSizeChange}
|
|
143
|
-
placement="left"
|
|
144
|
-
showBorder={false}
|
|
145
|
-
style={{
|
|
146
|
-
background: isDesktop && isMacOS() ? 'transparent' : cssVar.colorBgLayout,
|
|
147
|
-
zIndex: 11,
|
|
148
|
-
}}
|
|
149
|
-
>
|
|
150
|
-
<AnimatePresence initial={false} mode="popLayout">
|
|
151
|
-
<motion.div
|
|
152
|
-
animate={{ opacity: 1, x: 0 }}
|
|
153
|
-
className={styles.inner}
|
|
154
|
-
exit={{
|
|
155
|
-
opacity: 0,
|
|
156
|
-
x: '-20%',
|
|
157
|
-
}}
|
|
158
|
-
initial={{
|
|
159
|
-
opacity: 0,
|
|
160
|
-
x: 0,
|
|
161
|
-
}}
|
|
162
|
-
key={activeContent.key}
|
|
163
|
-
transition={{
|
|
164
|
-
duration: 0.4,
|
|
165
|
-
ease: [0.4, 0, 0.2, 1],
|
|
166
|
-
}}
|
|
167
|
-
>
|
|
168
|
-
{activeContent.node}
|
|
169
|
-
</motion.div>
|
|
170
|
-
</AnimatePresence>
|
|
171
|
-
</DraggablePanel>
|
|
47
|
+
<NavPanelDraggable activeContent={activeContent} />
|
|
172
48
|
<div
|
|
173
49
|
id={NAV_PANEL_RIGHT_DRAWER_ID}
|
|
174
50
|
style={{
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
'navigation.chat': 'Chat',
|
|
3
|
+
'navigation.discover': 'Discover',
|
|
4
|
+
'navigation.discoverAssistants': 'Discover Assistants',
|
|
5
|
+
'navigation.discoverMcp': 'Discover MCP',
|
|
6
|
+
'navigation.discoverModels': 'Discover Models',
|
|
7
|
+
'navigation.discoverProviders': 'Discover Providers',
|
|
8
|
+
'navigation.group': 'Group',
|
|
9
|
+
'navigation.groupChat': 'Group Chat',
|
|
10
|
+
'navigation.home': 'Home',
|
|
11
|
+
'navigation.image': 'Image',
|
|
12
|
+
'navigation.knowledgeBase': 'Knowledge Base',
|
|
13
|
+
'navigation.lobehub': 'LobeHub',
|
|
14
|
+
'navigation.memory': 'Memory',
|
|
15
|
+
'navigation.memoryContexts': 'Memory - Contexts',
|
|
16
|
+
'navigation.memoryExperiences': 'Memory - Experiences',
|
|
17
|
+
'navigation.memoryIdentities': 'Memory - Identities',
|
|
18
|
+
'navigation.memoryPreferences': 'Memory - Preferences',
|
|
19
|
+
'navigation.onboarding': 'Onboarding',
|
|
20
|
+
'navigation.page': 'Page',
|
|
21
|
+
'navigation.pages': 'Pages',
|
|
22
|
+
'navigation.provider': 'Provider',
|
|
23
|
+
'navigation.recentView': 'Recent pages',
|
|
24
|
+
'navigation.resources': 'Resources',
|
|
25
|
+
'navigation.settings': 'Settings',
|
|
2
26
|
'notification.finishChatGeneration': 'AI message generation completed',
|
|
3
27
|
'proxy.auth': 'Authentication Required',
|
|
4
28
|
'proxy.authDesc': 'If the proxy server requires a username and password',
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { type StateCreator } from 'zustand/vanilla';
|
|
2
|
+
|
|
3
|
+
import type { ElectronStore } from '../store';
|
|
4
|
+
|
|
5
|
+
// ======== Types ======== //
|
|
6
|
+
|
|
7
|
+
export interface HistoryEntry {
|
|
8
|
+
icon?: string;
|
|
9
|
+
metadata?: {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
sessionId?: string;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
};
|
|
14
|
+
title: string;
|
|
15
|
+
url: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface NavigationHistoryState {
|
|
19
|
+
/**
|
|
20
|
+
* Current page title from PageTitle component
|
|
21
|
+
* Used to get dynamic titles without setTimeout hack
|
|
22
|
+
*/
|
|
23
|
+
currentPageTitle: string;
|
|
24
|
+
/**
|
|
25
|
+
* Current position in history (-1 means empty)
|
|
26
|
+
*/
|
|
27
|
+
historyCurrentIndex: number;
|
|
28
|
+
/**
|
|
29
|
+
* History entries list
|
|
30
|
+
*/
|
|
31
|
+
historyEntries: HistoryEntry[];
|
|
32
|
+
/**
|
|
33
|
+
* Flag to indicate if currently navigating via back/forward
|
|
34
|
+
* Used to prevent adding duplicate history entries
|
|
35
|
+
*/
|
|
36
|
+
isNavigatingHistory: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ======== Action Interface ======== //
|
|
40
|
+
|
|
41
|
+
export interface NavigationHistoryAction {
|
|
42
|
+
/**
|
|
43
|
+
* Check if can go back in history
|
|
44
|
+
*/
|
|
45
|
+
canGoBack: () => boolean;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if can go forward in history
|
|
49
|
+
*/
|
|
50
|
+
canGoForward: () => boolean;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get current history entry
|
|
54
|
+
*/
|
|
55
|
+
getCurrentEntry: () => HistoryEntry | null;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Navigate back in history
|
|
59
|
+
* @returns The target entry or null if cannot go back
|
|
60
|
+
*/
|
|
61
|
+
goBack: () => HistoryEntry | null;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Navigate forward in history
|
|
65
|
+
* @returns The target entry or null if cannot go forward
|
|
66
|
+
*/
|
|
67
|
+
goForward: () => HistoryEntry | null;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Push a new entry to history (for normal navigation)
|
|
71
|
+
* Truncates any forward history if not at the end
|
|
72
|
+
*/
|
|
73
|
+
pushHistory: (
|
|
74
|
+
entry: Omit<HistoryEntry, 'metadata'> & { metadata?: Partial<HistoryEntry['metadata']> },
|
|
75
|
+
) => void;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Replace current entry in history (for replace navigation)
|
|
79
|
+
*/
|
|
80
|
+
replaceHistory: (
|
|
81
|
+
entry: Omit<HistoryEntry, 'metadata'> & { metadata?: Partial<HistoryEntry['metadata']> },
|
|
82
|
+
) => void;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Set current page title (called by PageTitle component)
|
|
86
|
+
*/
|
|
87
|
+
setCurrentPageTitle: (title: string) => void;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Set the navigating history flag
|
|
91
|
+
*/
|
|
92
|
+
setIsNavigatingHistory: (value: boolean) => void;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ======== Initial State ======== //
|
|
96
|
+
|
|
97
|
+
export const navigationHistoryInitialState: NavigationHistoryState = {
|
|
98
|
+
currentPageTitle: '',
|
|
99
|
+
historyCurrentIndex: -1,
|
|
100
|
+
historyEntries: [],
|
|
101
|
+
isNavigatingHistory: false,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// ======== Action Implementation ======== //
|
|
105
|
+
|
|
106
|
+
export const createNavigationHistorySlice: StateCreator<
|
|
107
|
+
ElectronStore,
|
|
108
|
+
[['zustand/devtools', never]],
|
|
109
|
+
[],
|
|
110
|
+
NavigationHistoryAction
|
|
111
|
+
> = (set, get) => ({
|
|
112
|
+
canGoBack: () => {
|
|
113
|
+
const { historyCurrentIndex } = get();
|
|
114
|
+
return historyCurrentIndex > 0;
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
canGoForward: () => {
|
|
118
|
+
const { historyCurrentIndex, historyEntries } = get();
|
|
119
|
+
return historyCurrentIndex < historyEntries.length - 1;
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
getCurrentEntry: () => {
|
|
123
|
+
const { historyCurrentIndex, historyEntries } = get();
|
|
124
|
+
if (historyCurrentIndex < 0 || historyCurrentIndex >= historyEntries.length) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return historyEntries[historyCurrentIndex];
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
goBack: () => {
|
|
131
|
+
const { historyCurrentIndex, historyEntries } = get();
|
|
132
|
+
|
|
133
|
+
if (historyCurrentIndex <= 0) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const newIndex = historyCurrentIndex - 1;
|
|
138
|
+
const targetEntry = historyEntries[newIndex];
|
|
139
|
+
|
|
140
|
+
set(
|
|
141
|
+
{
|
|
142
|
+
historyCurrentIndex: newIndex,
|
|
143
|
+
isNavigatingHistory: true,
|
|
144
|
+
},
|
|
145
|
+
false,
|
|
146
|
+
'goBack',
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return targetEntry;
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
goForward: () => {
|
|
153
|
+
const { historyCurrentIndex, historyEntries } = get();
|
|
154
|
+
|
|
155
|
+
if (historyCurrentIndex >= historyEntries.length - 1) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const newIndex = historyCurrentIndex + 1;
|
|
160
|
+
const targetEntry = historyEntries[newIndex];
|
|
161
|
+
|
|
162
|
+
set(
|
|
163
|
+
{
|
|
164
|
+
historyCurrentIndex: newIndex,
|
|
165
|
+
isNavigatingHistory: true,
|
|
166
|
+
},
|
|
167
|
+
false,
|
|
168
|
+
'goForward',
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return targetEntry;
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
pushHistory: (entry) => {
|
|
175
|
+
const { historyCurrentIndex, historyEntries } = get();
|
|
176
|
+
|
|
177
|
+
// Create full entry with metadata
|
|
178
|
+
const fullEntry: HistoryEntry = {
|
|
179
|
+
icon: entry.icon,
|
|
180
|
+
metadata: {
|
|
181
|
+
timestamp: Date.now(),
|
|
182
|
+
...entry.metadata,
|
|
183
|
+
},
|
|
184
|
+
title: entry.title,
|
|
185
|
+
url: entry.url,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// If not at the end, truncate forward history
|
|
189
|
+
const newEntries =
|
|
190
|
+
historyCurrentIndex < historyEntries.length - 1
|
|
191
|
+
? historyEntries.slice(0, historyCurrentIndex + 1)
|
|
192
|
+
: [...historyEntries];
|
|
193
|
+
|
|
194
|
+
// Add new entry
|
|
195
|
+
newEntries.push(fullEntry);
|
|
196
|
+
|
|
197
|
+
set(
|
|
198
|
+
{
|
|
199
|
+
historyCurrentIndex: newEntries.length - 1,
|
|
200
|
+
historyEntries: newEntries,
|
|
201
|
+
},
|
|
202
|
+
false,
|
|
203
|
+
'pushHistory',
|
|
204
|
+
);
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
replaceHistory: (entry) => {
|
|
208
|
+
const { historyCurrentIndex, historyEntries } = get();
|
|
209
|
+
|
|
210
|
+
// If history is empty, just push
|
|
211
|
+
if (historyCurrentIndex < 0 || historyEntries.length === 0) {
|
|
212
|
+
get().pushHistory(entry);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Create full entry with metadata
|
|
217
|
+
const fullEntry: HistoryEntry = {
|
|
218
|
+
icon: entry.icon,
|
|
219
|
+
metadata: {
|
|
220
|
+
timestamp: Date.now(),
|
|
221
|
+
...entry.metadata,
|
|
222
|
+
},
|
|
223
|
+
title: entry.title,
|
|
224
|
+
url: entry.url,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// Replace current entry
|
|
228
|
+
const newEntries = [...historyEntries];
|
|
229
|
+
newEntries[historyCurrentIndex] = fullEntry;
|
|
230
|
+
|
|
231
|
+
set(
|
|
232
|
+
{
|
|
233
|
+
historyEntries: newEntries,
|
|
234
|
+
},
|
|
235
|
+
false,
|
|
236
|
+
'replaceHistory',
|
|
237
|
+
);
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
setCurrentPageTitle: (title) => {
|
|
241
|
+
set({ currentPageTitle: title }, false, 'setCurrentPageTitle');
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
setIsNavigatingHistory: (value) => {
|
|
245
|
+
set({ isNavigatingHistory: value }, false, 'setIsNavigatingHistory');
|
|
246
|
+
},
|
|
247
|
+
});
|
|
@@ -4,6 +4,11 @@ import {
|
|
|
4
4
|
type NetworkProxySettings,
|
|
5
5
|
} from '@lobechat/electron-client-ipc';
|
|
6
6
|
|
|
7
|
+
import {
|
|
8
|
+
type NavigationHistoryState,
|
|
9
|
+
navigationHistoryInitialState,
|
|
10
|
+
} from './actions/navigationHistory';
|
|
11
|
+
|
|
7
12
|
export type RemoteServerError = 'CONFIG_ERROR' | 'AUTH_ERROR' | 'DISCONNECT_ERROR';
|
|
8
13
|
|
|
9
14
|
export const defaultProxySettings: NetworkProxySettings = {
|
|
@@ -15,7 +20,7 @@ export const defaultProxySettings: NetworkProxySettings = {
|
|
|
15
20
|
proxyType: 'http',
|
|
16
21
|
};
|
|
17
22
|
|
|
18
|
-
export interface ElectronState {
|
|
23
|
+
export interface ElectronState extends NavigationHistoryState {
|
|
19
24
|
appState: ElectronAppState;
|
|
20
25
|
dataSyncConfig: DataSyncConfig;
|
|
21
26
|
desktopHotkeys: Record<string, string>;
|
|
@@ -29,6 +34,7 @@ export interface ElectronState {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
export const initialState: ElectronState = {
|
|
37
|
+
...navigationHistoryInitialState,
|
|
32
38
|
appState: {},
|
|
33
39
|
dataSyncConfig: { storageMode: 'cloud' },
|
|
34
40
|
desktopHotkeys: {},
|
|
@@ -4,6 +4,10 @@ import { type StateCreator } from 'zustand/vanilla';
|
|
|
4
4
|
|
|
5
5
|
import { createDevtools } from '../middleware/createDevtools';
|
|
6
6
|
import { type ElectronAppAction, createElectronAppSlice } from './actions/app';
|
|
7
|
+
import {
|
|
8
|
+
type NavigationHistoryAction,
|
|
9
|
+
createNavigationHistorySlice,
|
|
10
|
+
} from './actions/navigationHistory';
|
|
7
11
|
import { type ElectronSettingsAction, settingsSlice } from './actions/settings';
|
|
8
12
|
import { type ElectronRemoteServerAction, remoteSyncSlice } from './actions/sync';
|
|
9
13
|
import { type ElectronState, initialState } from './initialState';
|
|
@@ -11,10 +15,12 @@ import { type ElectronState, initialState } from './initialState';
|
|
|
11
15
|
// =============== Aggregate createStoreFn ============ //
|
|
12
16
|
|
|
13
17
|
export interface ElectronStore
|
|
14
|
-
extends
|
|
18
|
+
extends
|
|
19
|
+
ElectronState,
|
|
15
20
|
ElectronRemoteServerAction,
|
|
16
21
|
ElectronAppAction,
|
|
17
|
-
ElectronSettingsAction
|
|
22
|
+
ElectronSettingsAction,
|
|
23
|
+
NavigationHistoryAction {
|
|
18
24
|
/* empty */
|
|
19
25
|
}
|
|
20
26
|
|
|
@@ -25,6 +31,7 @@ const createStore: StateCreator<ElectronStore, [['zustand/devtools', never]]> =
|
|
|
25
31
|
...remoteSyncSlice(...parameters),
|
|
26
32
|
...createElectronAppSlice(...parameters),
|
|
27
33
|
...settingsSlice(...parameters),
|
|
34
|
+
...createNavigationHistorySlice(...parameters),
|
|
28
35
|
});
|
|
29
36
|
|
|
30
37
|
// =============== Implement useStore ============ //
|
|
@@ -30,7 +30,10 @@ const modelSwitchPanelWidth = (s: GlobalState) => s.status.modelSwitchPanelWidth
|
|
|
30
30
|
|
|
31
31
|
const showChatHeader = (s: GlobalState) => !s.status.zenMode;
|
|
32
32
|
const inZenMode = (s: GlobalState) => s.status.zenMode;
|
|
33
|
-
const leftPanelWidth = (s: GlobalState) =>
|
|
33
|
+
const leftPanelWidth = (s: GlobalState): number => {
|
|
34
|
+
const width = s.status.leftPanelWidth;
|
|
35
|
+
return typeof width === 'string' ? Number.parseInt(width) : width;
|
|
36
|
+
};
|
|
34
37
|
const portalWidth = (s: GlobalState) => s.status.portalWidth || 400;
|
|
35
38
|
const filePanelWidth = (s: GlobalState) => s.status.filePanelWidth;
|
|
36
39
|
const imagePanelWidth = (s: GlobalState) => s.status.imagePanelWidth;
|