@lobehub/lobehub 2.0.0-next.90 → 2.0.0-next.92
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 +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/src/app/[variants]/DesktopClientRouter.tsx +20 -0
- package/src/app/[variants]/DesktopRouter.tsx +1 -21
- package/src/app/[variants]/MobileClientRouter.tsx +20 -0
- package/src/app/[variants]/MobileRouter.tsx +1 -22
- package/src/app/[variants]/desktopRouter.config.tsx +280 -152
- package/src/app/[variants]/loading.tsx +3 -0
- package/src/app/[variants]/mobileRouter.config.tsx +302 -162
- package/src/app/[variants]/page.tsx +1 -0
- package/src/layout/GlobalProvider/StoreInitialization.tsx +0 -9
- package/src/store/global/initialState.ts +0 -7
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import dynamic from 'next/dynamic';
|
|
3
4
|
import { useEffect } from 'react';
|
|
4
|
-
import {
|
|
5
|
+
import { createBrowserRouter, redirect, useNavigate, useRouteError } from 'react-router-dom';
|
|
5
6
|
|
|
7
|
+
import ErrorCapture from '@/components/Error';
|
|
6
8
|
import Loading from '@/components/Loading/BrandTextLoading';
|
|
7
9
|
import { useGlobalStore } from '@/store/global';
|
|
8
10
|
import type { Locales } from '@/types/locale';
|
|
@@ -10,6 +12,233 @@ import type { Locales } from '@/types/locale';
|
|
|
10
12
|
import { MobileMainLayout } from './(main)/layouts/mobile';
|
|
11
13
|
import { idLoader, slugLoader } from './loaders/routeParams';
|
|
12
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Mobile Router Configuration - Pure CSR Mode
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT: This router runs ONLY in the browser (client-side).
|
|
19
|
+
*
|
|
20
|
+
* Key characteristics:
|
|
21
|
+
* - createBrowserRouter uses window.history API (client-only)
|
|
22
|
+
* - All loaders execute in the browser during navigation
|
|
23
|
+
* - No server-side rendering or hydration involved
|
|
24
|
+
* - Route data fetching happens on-demand during client navigation
|
|
25
|
+
*
|
|
26
|
+
* The entire router tree is wrapped with Next.js dynamic import (ssr: false),
|
|
27
|
+
* ensuring this code never executes on the server.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// Chat components
|
|
31
|
+
const MobileChatPage = dynamic(() => import('./(main)/chat/index').then((m) => m.MobileChatPage), {
|
|
32
|
+
loading: () => <Loading />,
|
|
33
|
+
ssr: false,
|
|
34
|
+
});
|
|
35
|
+
const ChatSettings = dynamic(() => import('./(main)/chat/settings'), {
|
|
36
|
+
loading: () => <Loading />,
|
|
37
|
+
ssr: false,
|
|
38
|
+
});
|
|
39
|
+
const ChatLayout = dynamic(() => import('./(main)/chat/_layout/Mobile'), {
|
|
40
|
+
loading: () => <Loading />,
|
|
41
|
+
ssr: false,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Discover List components
|
|
45
|
+
const MobileHomePage = dynamic(
|
|
46
|
+
() => import('./(main)/discover/(list)/(home)/index').then((m) => m.MobileHomePage),
|
|
47
|
+
{
|
|
48
|
+
loading: () => <Loading />,
|
|
49
|
+
ssr: false,
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
const MobileAssistantPage = dynamic(
|
|
53
|
+
() => import('./(main)/discover/(list)/assistant/index').then((m) => m.MobileAssistantPage),
|
|
54
|
+
{
|
|
55
|
+
loading: () => <Loading />,
|
|
56
|
+
ssr: false,
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
const DiscoverAssistantLayout = dynamic(
|
|
60
|
+
() => import('./(main)/discover/(list)/assistant/_layout/Mobile'),
|
|
61
|
+
{
|
|
62
|
+
loading: () => <Loading />,
|
|
63
|
+
ssr: false,
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
const DiscoverListMobileModelPage = dynamic(
|
|
67
|
+
() => import('./(main)/discover/(list)/model/index').then((m) => m.MobileModelPage),
|
|
68
|
+
{
|
|
69
|
+
loading: () => <Loading />,
|
|
70
|
+
ssr: false,
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
const DiscoverModelLayout = dynamic(() => import('./(main)/discover/(list)/model/_layout/Mobile'), {
|
|
74
|
+
loading: () => <Loading />,
|
|
75
|
+
ssr: false,
|
|
76
|
+
});
|
|
77
|
+
const DiscoverListMobileProviderPage = dynamic(
|
|
78
|
+
() => import('./(main)/discover/(list)/provider/index').then((m) => m.MobileProviderPage),
|
|
79
|
+
{
|
|
80
|
+
loading: () => <Loading />,
|
|
81
|
+
ssr: false,
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
const DiscoverListMobileMcpPage = dynamic(
|
|
85
|
+
() => import('./(main)/discover/(list)/mcp/index').then((m) => m.MobileMcpPage),
|
|
86
|
+
{
|
|
87
|
+
loading: () => <Loading />,
|
|
88
|
+
ssr: false,
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
const DiscoverMcpLayout = dynamic(() => import('./(main)/discover/(list)/mcp/_layout/Mobile'), {
|
|
92
|
+
loading: () => <Loading />,
|
|
93
|
+
ssr: false,
|
|
94
|
+
});
|
|
95
|
+
const DiscoverListLayout = dynamic(() => import('./(main)/discover/(list)/_layout/Mobile/index'), {
|
|
96
|
+
loading: () => <Loading />,
|
|
97
|
+
ssr: false,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Discover Detail components
|
|
101
|
+
const MobileDiscoverAssistantDetailPage = dynamic(
|
|
102
|
+
() =>
|
|
103
|
+
import('./(main)/discover/(detail)/assistant/index').then(
|
|
104
|
+
(m) => m.MobileDiscoverAssistantDetailPage,
|
|
105
|
+
),
|
|
106
|
+
{
|
|
107
|
+
loading: () => <Loading />,
|
|
108
|
+
ssr: false,
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
const DiscoverDetailMobileModelPage = dynamic(
|
|
112
|
+
() => import('./(main)/discover/(detail)/model/index').then((m) => m.MobileModelPage),
|
|
113
|
+
{
|
|
114
|
+
loading: () => <Loading />,
|
|
115
|
+
ssr: false,
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
const DiscoverDetailMobileProviderPage = dynamic(
|
|
119
|
+
() => import('./(main)/discover/(detail)/provider/index').then((m) => m.MobileProviderPage),
|
|
120
|
+
{
|
|
121
|
+
loading: () => <Loading />,
|
|
122
|
+
ssr: false,
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
const DiscoverDetailMobileMcpPage = dynamic(
|
|
126
|
+
() => import('./(main)/discover/(detail)/mcp/index').then((m) => m.MobileMcpPage),
|
|
127
|
+
{
|
|
128
|
+
loading: () => <Loading />,
|
|
129
|
+
ssr: false,
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
const DiscoverDetailLayout = dynamic(
|
|
133
|
+
() => import('./(main)/discover/(detail)/_layout/Mobile/index'),
|
|
134
|
+
{
|
|
135
|
+
loading: () => <Loading />,
|
|
136
|
+
ssr: false,
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
const DiscoverLayout = dynamic(() => import('./(main)/discover/_layout/Mobile/index'), {
|
|
140
|
+
loading: () => <Loading />,
|
|
141
|
+
ssr: false,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Knowledge components
|
|
145
|
+
const KnowledgeHome = dynamic(() => import('./(main)/knowledge/routes/KnowledgeHome'), {
|
|
146
|
+
loading: () => <Loading />,
|
|
147
|
+
ssr: false,
|
|
148
|
+
});
|
|
149
|
+
const KnowledgeBasesList = dynamic(() => import('./(main)/knowledge/routes/KnowledgeBasesList'), {
|
|
150
|
+
loading: () => <Loading />,
|
|
151
|
+
ssr: false,
|
|
152
|
+
});
|
|
153
|
+
const KnowledgeBaseDetail = dynamic(() => import('./(main)/knowledge/routes/KnowledgeBaseDetail'), {
|
|
154
|
+
loading: () => <Loading />,
|
|
155
|
+
ssr: false,
|
|
156
|
+
});
|
|
157
|
+
const KnowledgeLayout = dynamic(() => import('./(main)/knowledge/_layout/Mobile'), {
|
|
158
|
+
loading: () => <Loading />,
|
|
159
|
+
ssr: false,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Settings components
|
|
163
|
+
const SettingsLayout = dynamic(() => import('./(main)/settings/_layout/Mobile'), {
|
|
164
|
+
loading: () => <Loading />,
|
|
165
|
+
ssr: false,
|
|
166
|
+
});
|
|
167
|
+
const SettingsLayoutWrapper = dynamic(() => import('./(main)/settings/_layout/MobileWrapper'), {
|
|
168
|
+
loading: () => <Loading />,
|
|
169
|
+
ssr: false,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Image components
|
|
173
|
+
const ImageComingSoon = dynamic(() => import('./(main)/image/ComingSoon'), {
|
|
174
|
+
loading: () => <Loading />,
|
|
175
|
+
ssr: false,
|
|
176
|
+
});
|
|
177
|
+
const ImageLayoutMobile = dynamic(() => import('./(main)/image/_layout/Mobile'), {
|
|
178
|
+
loading: () => <Loading />,
|
|
179
|
+
ssr: false,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Labs components
|
|
183
|
+
const LabsPage = dynamic(() => import('./(main)/labs'), {
|
|
184
|
+
loading: () => <Loading />,
|
|
185
|
+
ssr: false,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Profile components
|
|
189
|
+
const ProfileHomePage = dynamic(() => import('./(main)/profile/(home)'), {
|
|
190
|
+
loading: () => <Loading />,
|
|
191
|
+
ssr: false,
|
|
192
|
+
});
|
|
193
|
+
const ProfileApikeyPage = dynamic(() => import('./(main)/profile/apikey/index'), {
|
|
194
|
+
loading: () => <Loading />,
|
|
195
|
+
ssr: false,
|
|
196
|
+
});
|
|
197
|
+
const MobileProfileSecurityPage = dynamic(
|
|
198
|
+
() => import('./(main)/profile/security').then((m) => m.MobileProfileSecurityPage),
|
|
199
|
+
{
|
|
200
|
+
loading: () => <Loading />,
|
|
201
|
+
ssr: false,
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
const MobileProfileStatsPage = dynamic(
|
|
205
|
+
() => import('./(main)/profile/stats').then((m) => m.MobileProfileStatsPage),
|
|
206
|
+
{
|
|
207
|
+
loading: () => <Loading />,
|
|
208
|
+
ssr: false,
|
|
209
|
+
},
|
|
210
|
+
);
|
|
211
|
+
const ProfileLayoutMobile = dynamic(() => import('./(main)/profile/_layout/Mobile'), {
|
|
212
|
+
loading: () => <Loading />,
|
|
213
|
+
ssr: false,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Me (mobile personal center) components
|
|
217
|
+
const MeHomePage = dynamic(() => import('./(main)/(mobile)/me/(home)'), {
|
|
218
|
+
loading: () => <Loading />,
|
|
219
|
+
ssr: false,
|
|
220
|
+
});
|
|
221
|
+
const MeHomeLayout = dynamic(() => import('./(main)/(mobile)/me/(home)/layout'), {
|
|
222
|
+
loading: () => <Loading />,
|
|
223
|
+
ssr: false,
|
|
224
|
+
});
|
|
225
|
+
const MeProfilePage = dynamic(() => import('./(main)/(mobile)/me/profile'), {
|
|
226
|
+
loading: () => <Loading />,
|
|
227
|
+
ssr: false,
|
|
228
|
+
});
|
|
229
|
+
const MeProfileLayout = dynamic(() => import('./(main)/(mobile)/me/profile/layout'), {
|
|
230
|
+
loading: () => <Loading />,
|
|
231
|
+
ssr: false,
|
|
232
|
+
});
|
|
233
|
+
const MeSettingsPage = dynamic(() => import('./(main)/(mobile)/me/settings'), {
|
|
234
|
+
loading: () => <Loading />,
|
|
235
|
+
ssr: false,
|
|
236
|
+
});
|
|
237
|
+
const MeSettingsLayout = dynamic(() => import('./(main)/(mobile)/me/settings/layout'), {
|
|
238
|
+
loading: () => <Loading />,
|
|
239
|
+
ssr: false,
|
|
240
|
+
});
|
|
241
|
+
|
|
13
242
|
// Component to register navigate function in global store
|
|
14
243
|
const NavigatorRegistrar = () => {
|
|
15
244
|
const navigate = useNavigate();
|
|
@@ -25,8 +254,32 @@ const NavigatorRegistrar = () => {
|
|
|
25
254
|
return null;
|
|
26
255
|
};
|
|
27
256
|
|
|
28
|
-
//
|
|
29
|
-
|
|
257
|
+
// Error boundary factory for React Router errorElement
|
|
258
|
+
const createErrorBoundary = (resetPath: string) => {
|
|
259
|
+
const ErrorBoundary = () => {
|
|
260
|
+
const error = useRouteError() as Error;
|
|
261
|
+
const navigate = useNavigate();
|
|
262
|
+
|
|
263
|
+
const reset = () => {
|
|
264
|
+
navigate(resetPath);
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
return <ErrorCapture error={error} reset={reset} />;
|
|
268
|
+
};
|
|
269
|
+
return ErrorBoundary;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// Create error boundaries for each route
|
|
273
|
+
const ChatErrorBoundary = createErrorBoundary('/chat');
|
|
274
|
+
const DiscoverErrorBoundary = createErrorBoundary('/discover');
|
|
275
|
+
const KnowledgeErrorBoundary = createErrorBoundary('/knowledge');
|
|
276
|
+
const SettingsErrorBoundary = createErrorBoundary('/settings');
|
|
277
|
+
const ImageErrorBoundary = createErrorBoundary('/image');
|
|
278
|
+
const ProfileErrorBoundary = createErrorBoundary('/profile');
|
|
279
|
+
const MeErrorBoundary = createErrorBoundary('/me'); // Mobile only
|
|
280
|
+
const RootErrorBoundary = createErrorBoundary('/chat'); // Root level falls back to chat
|
|
281
|
+
|
|
282
|
+
// Root layout wrapper component
|
|
30
283
|
const RootLayout = (props: { locale: Locales }) => (
|
|
31
284
|
<>
|
|
32
285
|
<NavigatorRegistrar />
|
|
@@ -34,39 +287,25 @@ const RootLayout = (props: { locale: Locales }) => (
|
|
|
34
287
|
</>
|
|
35
288
|
);
|
|
36
289
|
|
|
37
|
-
// Hydration gate loader -always return true to bypass hydration gate
|
|
38
|
-
const hydrationGateLoader: LoaderFunction = () => {
|
|
39
|
-
return true
|
|
40
|
-
};
|
|
41
|
-
|
|
42
290
|
// Create mobile router configuration
|
|
43
291
|
export const createMobileRouter = (locale: Locales) =>
|
|
44
292
|
createBrowserRouter([
|
|
45
293
|
{
|
|
46
|
-
HydrateFallback: () => <Loading />,
|
|
47
294
|
children: [
|
|
48
295
|
// Chat routes
|
|
49
296
|
{
|
|
50
297
|
children: [
|
|
51
298
|
{
|
|
299
|
+
element: <MobileChatPage />,
|
|
52
300
|
index: true,
|
|
53
|
-
lazy: () =>
|
|
54
|
-
import('./(main)/chat/index').then((m) => ({
|
|
55
|
-
Component: m.MobileChatPage,
|
|
56
|
-
})),
|
|
57
301
|
},
|
|
58
302
|
{
|
|
59
|
-
|
|
60
|
-
import('./(main)/chat/settings').then((m) => ({
|
|
61
|
-
Component: m.default,
|
|
62
|
-
})),
|
|
303
|
+
element: <ChatSettings />,
|
|
63
304
|
path: 'settings',
|
|
64
305
|
},
|
|
65
306
|
],
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Component: m.default,
|
|
69
|
-
})),
|
|
307
|
+
element: <ChatLayout />,
|
|
308
|
+
errorElement: <ChatErrorBoundary />,
|
|
70
309
|
path: 'chat',
|
|
71
310
|
},
|
|
72
311
|
|
|
@@ -77,116 +316,72 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
77
316
|
{
|
|
78
317
|
children: [
|
|
79
318
|
{
|
|
319
|
+
element: <MobileHomePage />,
|
|
80
320
|
index: true,
|
|
81
|
-
lazy: () =>
|
|
82
|
-
import('./(main)/discover/(list)/(home)/index').then((m) => ({
|
|
83
|
-
Component: m.MobileHomePage,
|
|
84
|
-
})),
|
|
85
321
|
},
|
|
86
322
|
{
|
|
87
323
|
children: [
|
|
88
324
|
{
|
|
89
|
-
|
|
90
|
-
import('./(main)/discover/(list)/assistant/index').then((m) => ({
|
|
91
|
-
Component: m.MobileAssistantPage,
|
|
92
|
-
})),
|
|
325
|
+
element: <MobileAssistantPage />,
|
|
93
326
|
path: 'assistant',
|
|
94
327
|
},
|
|
95
328
|
],
|
|
96
|
-
|
|
97
|
-
import('./(main)/discover/(list)/assistant/_layout/Mobile').then((m) => ({
|
|
98
|
-
Component: m.default,
|
|
99
|
-
})),
|
|
329
|
+
element: <DiscoverAssistantLayout />,
|
|
100
330
|
},
|
|
101
331
|
{
|
|
102
332
|
children: [
|
|
103
333
|
{
|
|
104
|
-
|
|
105
|
-
import('./(main)/discover/(list)/model/index').then((m) => ({
|
|
106
|
-
Component: m.MobileModelPage,
|
|
107
|
-
})),
|
|
334
|
+
element: <DiscoverListMobileModelPage />,
|
|
108
335
|
path: 'model',
|
|
109
336
|
},
|
|
110
337
|
],
|
|
111
|
-
|
|
112
|
-
import('./(main)/discover/(list)/model/_layout/Mobile').then((m) => ({
|
|
113
|
-
Component: m.default,
|
|
114
|
-
})),
|
|
338
|
+
element: <DiscoverModelLayout />,
|
|
115
339
|
},
|
|
116
340
|
{
|
|
117
|
-
|
|
118
|
-
import('./(main)/discover/(list)/provider/index').then((m) => ({
|
|
119
|
-
Component: m.MobileProviderPage,
|
|
120
|
-
})),
|
|
341
|
+
element: <DiscoverListMobileProviderPage />,
|
|
121
342
|
path: 'provider',
|
|
122
343
|
},
|
|
123
344
|
{
|
|
124
345
|
children: [
|
|
125
346
|
{
|
|
126
|
-
|
|
127
|
-
import('./(main)/discover/(list)/mcp/index').then((m) => ({
|
|
128
|
-
Component: m.MobileMcpPage,
|
|
129
|
-
})),
|
|
347
|
+
element: <DiscoverListMobileMcpPage />,
|
|
130
348
|
path: 'mcp',
|
|
131
349
|
},
|
|
132
350
|
],
|
|
133
|
-
|
|
134
|
-
import('./(main)/discover/(list)/mcp/_layout/Mobile').then((m) => ({
|
|
135
|
-
Component: m.default,
|
|
136
|
-
})),
|
|
351
|
+
element: <DiscoverMcpLayout />,
|
|
137
352
|
},
|
|
138
353
|
],
|
|
139
|
-
|
|
140
|
-
import('./(main)/discover/(list)/_layout/Mobile/index').then((m) => ({
|
|
141
|
-
Component: m.default,
|
|
142
|
-
})),
|
|
354
|
+
element: <DiscoverListLayout />,
|
|
143
355
|
},
|
|
144
356
|
// Detail routes (with DetailLayout)
|
|
145
357
|
{
|
|
146
358
|
children: [
|
|
147
359
|
{
|
|
148
|
-
|
|
149
|
-
import('./(main)/discover/(detail)/assistant/index').then((m) => ({
|
|
150
|
-
Component: m.MobileDiscoverAssistantDetailPage,
|
|
151
|
-
})),
|
|
360
|
+
element: <MobileDiscoverAssistantDetailPage />,
|
|
152
361
|
loader: slugLoader,
|
|
153
362
|
path: 'assistant/:slug',
|
|
154
363
|
},
|
|
155
364
|
{
|
|
156
|
-
|
|
157
|
-
import('./(main)/discover/(detail)/model/index').then((m) => ({
|
|
158
|
-
Component: m.MobileModelPage,
|
|
159
|
-
})),
|
|
365
|
+
element: <DiscoverDetailMobileModelPage />,
|
|
160
366
|
loader: slugLoader,
|
|
161
367
|
path: 'model/:slug',
|
|
162
368
|
},
|
|
163
369
|
{
|
|
164
|
-
|
|
165
|
-
import('./(main)/discover/(detail)/provider/index').then((m) => ({
|
|
166
|
-
Component: m.MobileProviderPage,
|
|
167
|
-
})),
|
|
370
|
+
element: <DiscoverDetailMobileProviderPage />,
|
|
168
371
|
loader: slugLoader,
|
|
169
372
|
path: 'provider/:slug',
|
|
170
373
|
},
|
|
171
374
|
{
|
|
172
|
-
|
|
173
|
-
import('./(main)/discover/(detail)/mcp/index').then((m) => ({
|
|
174
|
-
Component: m.MobileMcpPage,
|
|
175
|
-
})),
|
|
375
|
+
element: <DiscoverDetailMobileMcpPage />,
|
|
176
376
|
loader: slugLoader,
|
|
177
377
|
path: 'mcp/:slug',
|
|
178
378
|
},
|
|
179
379
|
],
|
|
180
|
-
|
|
181
|
-
import('./(main)/discover/(detail)/_layout/Mobile/index').then((m) => ({
|
|
182
|
-
Component: m.default,
|
|
183
|
-
})),
|
|
380
|
+
element: <DiscoverDetailLayout />,
|
|
184
381
|
},
|
|
185
382
|
],
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Component: m.default,
|
|
189
|
-
})),
|
|
383
|
+
element: <DiscoverLayout />,
|
|
384
|
+
errorElement: <DiscoverErrorBoundary />,
|
|
190
385
|
path: 'discover',
|
|
191
386
|
},
|
|
192
387
|
|
|
@@ -194,32 +389,21 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
194
389
|
{
|
|
195
390
|
children: [
|
|
196
391
|
{
|
|
392
|
+
element: <KnowledgeHome />,
|
|
197
393
|
index: true,
|
|
198
|
-
lazy: () =>
|
|
199
|
-
import('./(main)/knowledge/routes/KnowledgeHome').then((m) => ({
|
|
200
|
-
Component: m.default,
|
|
201
|
-
})),
|
|
202
394
|
},
|
|
203
395
|
{
|
|
204
|
-
|
|
205
|
-
import('./(main)/knowledge/routes/KnowledgeBasesList').then((m) => ({
|
|
206
|
-
Component: m.default,
|
|
207
|
-
})),
|
|
396
|
+
element: <KnowledgeBasesList />,
|
|
208
397
|
path: 'bases',
|
|
209
398
|
},
|
|
210
399
|
{
|
|
211
|
-
|
|
212
|
-
import('./(main)/knowledge/routes/KnowledgeBaseDetail').then((m) => ({
|
|
213
|
-
Component: m.default,
|
|
214
|
-
})),
|
|
400
|
+
element: <KnowledgeBaseDetail />,
|
|
215
401
|
loader: idLoader,
|
|
216
402
|
path: 'bases/:id',
|
|
217
403
|
},
|
|
218
404
|
],
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
Component: m.default,
|
|
222
|
-
})),
|
|
405
|
+
element: <KnowledgeLayout />,
|
|
406
|
+
errorElement: <KnowledgeErrorBoundary />,
|
|
223
407
|
path: 'knowledge',
|
|
224
408
|
},
|
|
225
409
|
|
|
@@ -227,17 +411,12 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
227
411
|
{
|
|
228
412
|
children: [
|
|
229
413
|
{
|
|
414
|
+
element: <SettingsLayout />,
|
|
230
415
|
index: true,
|
|
231
|
-
lazy: () =>
|
|
232
|
-
import('./(main)/settings/_layout/Mobile').then((m) => ({
|
|
233
|
-
Component: m.default,
|
|
234
|
-
})),
|
|
235
416
|
},
|
|
236
417
|
],
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
Component: m.default,
|
|
240
|
-
})),
|
|
418
|
+
element: <SettingsLayoutWrapper />,
|
|
419
|
+
errorElement: <SettingsErrorBoundary />,
|
|
241
420
|
path: 'settings',
|
|
242
421
|
},
|
|
243
422
|
|
|
@@ -245,26 +424,18 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
245
424
|
{
|
|
246
425
|
children: [
|
|
247
426
|
{
|
|
427
|
+
element: <ImageComingSoon />,
|
|
248
428
|
index: true,
|
|
249
|
-
lazy: () =>
|
|
250
|
-
import('./(main)/image/ComingSoon').then((m) => ({
|
|
251
|
-
Component: m.default,
|
|
252
|
-
})),
|
|
253
429
|
},
|
|
254
430
|
],
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
Component: m.default,
|
|
258
|
-
})),
|
|
431
|
+
element: <ImageLayoutMobile />,
|
|
432
|
+
errorElement: <ImageErrorBoundary />,
|
|
259
433
|
path: 'image',
|
|
260
434
|
},
|
|
261
435
|
|
|
262
436
|
// Labs routes
|
|
263
437
|
{
|
|
264
|
-
|
|
265
|
-
import('./(main)/labs').then((m) => ({
|
|
266
|
-
Component: m.default,
|
|
267
|
-
})),
|
|
438
|
+
element: <LabsPage />,
|
|
268
439
|
path: 'labs',
|
|
269
440
|
},
|
|
270
441
|
|
|
@@ -272,38 +443,24 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
272
443
|
{
|
|
273
444
|
children: [
|
|
274
445
|
{
|
|
446
|
+
element: <ProfileHomePage />,
|
|
275
447
|
index: true,
|
|
276
|
-
lazy: () =>
|
|
277
|
-
import('./(main)/profile/(home)').then((m) => ({
|
|
278
|
-
Component: m.default,
|
|
279
|
-
})),
|
|
280
448
|
},
|
|
281
449
|
{
|
|
282
|
-
|
|
283
|
-
import('./(main)/profile/apikey/index').then((m) => ({
|
|
284
|
-
Component: m.default,
|
|
285
|
-
})),
|
|
450
|
+
element: <ProfileApikeyPage />,
|
|
286
451
|
path: 'apikey',
|
|
287
452
|
},
|
|
288
453
|
{
|
|
289
|
-
|
|
290
|
-
import('./(main)/profile/security').then((m) => ({
|
|
291
|
-
Component: m.MobileProfileSecurityPage,
|
|
292
|
-
})),
|
|
454
|
+
element: <MobileProfileSecurityPage />,
|
|
293
455
|
path: 'security',
|
|
294
456
|
},
|
|
295
457
|
{
|
|
296
|
-
|
|
297
|
-
import('./(main)/profile/stats').then((m) => ({
|
|
298
|
-
Component: m.MobileProfileStatsPage,
|
|
299
|
-
})),
|
|
458
|
+
element: <MobileProfileStatsPage />,
|
|
300
459
|
path: 'stats',
|
|
301
460
|
},
|
|
302
461
|
],
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
Component: m.default,
|
|
306
|
-
})),
|
|
462
|
+
element: <ProfileLayoutMobile />,
|
|
463
|
+
errorElement: <ProfileErrorBoundary />,
|
|
307
464
|
path: 'profile',
|
|
308
465
|
},
|
|
309
466
|
|
|
@@ -313,49 +470,32 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
313
470
|
{
|
|
314
471
|
children: [
|
|
315
472
|
{
|
|
473
|
+
element: <MeHomePage />,
|
|
316
474
|
index: true,
|
|
317
|
-
lazy: () =>
|
|
318
|
-
import('./(main)/(mobile)/me/(home)').then((m) => ({
|
|
319
|
-
Component: m.default,
|
|
320
|
-
})),
|
|
321
475
|
},
|
|
322
476
|
],
|
|
323
|
-
|
|
324
|
-
import('./(main)/(mobile)/me/(home)/layout').then((m) => ({
|
|
325
|
-
Component: m.default,
|
|
326
|
-
})),
|
|
477
|
+
element: <MeHomeLayout />,
|
|
327
478
|
},
|
|
328
479
|
{
|
|
329
480
|
children: [
|
|
330
481
|
{
|
|
331
|
-
|
|
332
|
-
import('./(main)/(mobile)/me/profile').then((m) => ({
|
|
333
|
-
Component: m.default,
|
|
334
|
-
})),
|
|
482
|
+
element: <MeProfilePage />,
|
|
335
483
|
path: 'profile',
|
|
336
484
|
},
|
|
337
485
|
],
|
|
338
|
-
|
|
339
|
-
import('./(main)/(mobile)/me/profile/layout').then((m) => ({
|
|
340
|
-
Component: m.default,
|
|
341
|
-
})),
|
|
486
|
+
element: <MeProfileLayout />,
|
|
342
487
|
},
|
|
343
488
|
{
|
|
344
489
|
children: [
|
|
345
490
|
{
|
|
346
|
-
|
|
347
|
-
import('./(main)/(mobile)/me/settings').then((m) => ({
|
|
348
|
-
Component: m.default,
|
|
349
|
-
})),
|
|
491
|
+
element: <MeSettingsPage />,
|
|
350
492
|
path: 'settings',
|
|
351
493
|
},
|
|
352
494
|
],
|
|
353
|
-
|
|
354
|
-
import('./(main)/(mobile)/me/settings/layout').then((m) => ({
|
|
355
|
-
Component: m.default,
|
|
356
|
-
})),
|
|
495
|
+
element: <MeSettingsLayout />,
|
|
357
496
|
},
|
|
358
497
|
],
|
|
498
|
+
errorElement: <MeErrorBoundary />,
|
|
359
499
|
path: 'me',
|
|
360
500
|
},
|
|
361
501
|
|
|
@@ -372,7 +512,7 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
372
512
|
},
|
|
373
513
|
],
|
|
374
514
|
element: <RootLayout locale={locale} />,
|
|
375
|
-
|
|
515
|
+
errorElement: <RootErrorBoundary />,
|
|
376
516
|
path: '/',
|
|
377
517
|
},
|
|
378
518
|
]);
|
|
@@ -12,6 +12,7 @@ export default async (props: DynamicLayoutProps) => {
|
|
|
12
12
|
// Conditionally load and render based on device type
|
|
13
13
|
// Using native dynamic import ensures complete code splitting
|
|
14
14
|
// Mobile and Desktop bundles will be completely separate
|
|
15
|
+
|
|
15
16
|
if (isMobile) {
|
|
16
17
|
return <MobileRouter locale={locale} />;
|
|
17
18
|
}
|
|
@@ -63,16 +63,7 @@ const StoreInitialization = memo(() => {
|
|
|
63
63
|
|
|
64
64
|
// init user state
|
|
65
65
|
useInitUserState(isLoginOnInit, serverConfig, {
|
|
66
|
-
onError: () => {
|
|
67
|
-
// 即使失败也要设置标志,避免应用卡住
|
|
68
|
-
useGlobalStore.setState({ isAppHydrated: true });
|
|
69
|
-
console.warn('[Hydration] Client state initialization failed.');
|
|
70
|
-
},
|
|
71
66
|
onSuccess: (state) => {
|
|
72
|
-
// 设置水合完成标志
|
|
73
|
-
useGlobalStore.setState({ isAppHydrated: true });
|
|
74
|
-
console.log('[Hydration] Client state initialized successfully.');
|
|
75
|
-
|
|
76
67
|
if (state.isOnboard === false) {
|
|
77
68
|
router.push('/onboard');
|
|
78
69
|
}
|