@react-navigation/routers 8.0.0-alpha.2 → 8.0.0-alpha.20
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/lib/module/BaseRouter.js +64 -61
- package/lib/module/BaseRouter.js.map +1 -1
- package/lib/module/CommonActions.js +9 -21
- package/lib/module/CommonActions.js.map +1 -1
- package/lib/module/DrawerRouter.js +15 -14
- package/lib/module/DrawerRouter.js.map +1 -1
- package/lib/module/StackRouter.js +287 -166
- package/lib/module/StackRouter.js.map +1 -1
- package/lib/module/SwitchRouter.js +426 -0
- package/lib/module/SwitchRouter.js.map +1 -0
- package/lib/module/TabRouter.js +14 -290
- package/lib/module/TabRouter.js.map +1 -1
- package/lib/typescript/src/BaseRouter.d.ts +10 -8
- package/lib/typescript/src/BaseRouter.d.ts.map +1 -1
- package/lib/typescript/src/CommonActions.d.ts +42 -39
- package/lib/typescript/src/CommonActions.d.ts.map +1 -1
- package/lib/typescript/src/DrawerRouter.d.ts +6 -5
- package/lib/typescript/src/DrawerRouter.d.ts.map +1 -1
- package/lib/typescript/src/StackRouter.d.ts +70 -24
- package/lib/typescript/src/StackRouter.d.ts.map +1 -1
- package/lib/typescript/src/SwitchRouter.d.ts +69 -0
- package/lib/typescript/src/SwitchRouter.d.ts.map +1 -0
- package/lib/typescript/src/TabRouter.d.ts +4 -24
- package/lib/typescript/src/TabRouter.d.ts.map +1 -1
- package/lib/typescript/src/createParamsFromAction.d.ts +2 -2
- package/lib/typescript/src/createParamsFromAction.d.ts.map +1 -1
- package/lib/typescript/src/createRouteFromAction.d.ts +2 -2
- package/lib/typescript/src/createRouteFromAction.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +9 -9
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +20 -30
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/BaseRouter.tsx +93 -80
- package/src/CommonActions.tsx +44 -66
- package/src/DrawerRouter.tsx +28 -22
- package/src/StackRouter.tsx +551 -238
- package/src/SwitchRouter.tsx +718 -0
- package/src/TabRouter.tsx +24 -463
- package/src/createParamsFromAction.tsx +1 -1
- package/src/createRouteFromAction.tsx +1 -1
- package/src/types.tsx +39 -41
package/src/StackRouter.tsx
CHANGED
|
@@ -6,7 +6,6 @@ import { createRouteFromAction } from './createRouteFromAction';
|
|
|
6
6
|
import type {
|
|
7
7
|
CommonNavigationAction,
|
|
8
8
|
DefaultRouterOptions,
|
|
9
|
-
NavigationRoute,
|
|
10
9
|
NavigationState,
|
|
11
10
|
ParamListBase,
|
|
12
11
|
Route,
|
|
@@ -16,36 +15,48 @@ import type {
|
|
|
16
15
|
export type StackActionType =
|
|
17
16
|
| {
|
|
18
17
|
type: 'REPLACE';
|
|
19
|
-
payload: { name: string; params?: object };
|
|
20
|
-
source?: string;
|
|
21
|
-
target?: string;
|
|
18
|
+
payload: { name: string; params?: object | undefined };
|
|
19
|
+
source?: string | undefined;
|
|
20
|
+
target?: string | undefined;
|
|
22
21
|
}
|
|
23
22
|
| {
|
|
24
23
|
type: 'PUSH';
|
|
25
|
-
payload: { name: string; params?: object };
|
|
26
|
-
source?: string;
|
|
27
|
-
target?: string;
|
|
24
|
+
payload: { name: string; params?: object | undefined };
|
|
25
|
+
source?: string | undefined;
|
|
26
|
+
target?: string | undefined;
|
|
28
27
|
}
|
|
29
28
|
| {
|
|
30
29
|
type: 'POP';
|
|
31
30
|
payload: { count: number };
|
|
32
|
-
source?: string;
|
|
33
|
-
target?: string;
|
|
31
|
+
source?: string | undefined;
|
|
32
|
+
target?: string | undefined;
|
|
34
33
|
}
|
|
35
34
|
| {
|
|
36
35
|
type: 'POP_TO_TOP';
|
|
37
|
-
source?: string;
|
|
38
|
-
target?: string;
|
|
36
|
+
source?: string | undefined;
|
|
37
|
+
target?: string | undefined;
|
|
39
38
|
}
|
|
40
39
|
| {
|
|
41
40
|
type: 'POP_TO';
|
|
42
41
|
payload: {
|
|
43
42
|
name: string;
|
|
44
|
-
params?: object;
|
|
45
|
-
merge?: boolean;
|
|
43
|
+
params?: object | undefined;
|
|
44
|
+
merge?: boolean | undefined;
|
|
46
45
|
};
|
|
47
|
-
source?: string;
|
|
48
|
-
target?: string;
|
|
46
|
+
source?: string | undefined;
|
|
47
|
+
target?: string | undefined;
|
|
48
|
+
}
|
|
49
|
+
| {
|
|
50
|
+
type: 'RETAIN';
|
|
51
|
+
payload: { enable: boolean };
|
|
52
|
+
source?: string | undefined;
|
|
53
|
+
target?: string | undefined;
|
|
54
|
+
}
|
|
55
|
+
| {
|
|
56
|
+
type: 'DISMISS';
|
|
57
|
+
payload: { count: number };
|
|
58
|
+
source?: string | undefined;
|
|
59
|
+
target?: string | undefined;
|
|
49
60
|
};
|
|
50
61
|
|
|
51
62
|
export type StackRouterOptions = DefaultRouterOptions;
|
|
@@ -57,14 +68,16 @@ export type StackNavigationState<ParamList extends ParamListBase> =
|
|
|
57
68
|
*/
|
|
58
69
|
type: 'stack';
|
|
59
70
|
/**
|
|
60
|
-
* List of
|
|
71
|
+
* List of route keys to retain in the stack.
|
|
72
|
+
* When a retained route gets removed from the stack,
|
|
73
|
+
* it'll be kept in routes and can be navigated to again.
|
|
61
74
|
*/
|
|
62
|
-
|
|
75
|
+
retainedRouteKeys: string[];
|
|
63
76
|
};
|
|
64
77
|
|
|
65
78
|
export type StackActionHelpers<ParamList extends ParamListBase> = {
|
|
66
79
|
/**
|
|
67
|
-
* Replace the current
|
|
80
|
+
* Replace the current screen with a new one.
|
|
68
81
|
*
|
|
69
82
|
* @param screen Name of the new route that will replace the current one.
|
|
70
83
|
* @param [params] Params object for the new route.
|
|
@@ -92,12 +105,15 @@ export type StackActionHelpers<ParamList extends ParamListBase> = {
|
|
|
92
105
|
): void;
|
|
93
106
|
|
|
94
107
|
/**
|
|
95
|
-
* Pop a
|
|
108
|
+
* Pop a history entry from the stack.
|
|
109
|
+
* Also dismisses any screens above the current one.
|
|
110
|
+
*
|
|
111
|
+
* @param [count=1] Number of history entries to pop. Defaults to 1.
|
|
96
112
|
*/
|
|
97
113
|
pop(count?: number): void;
|
|
98
114
|
|
|
99
115
|
/**
|
|
100
|
-
* Pop to the first
|
|
116
|
+
* Pop to the first screen in the stack, dismissing all other screens.
|
|
101
117
|
*/
|
|
102
118
|
popToTop(): void;
|
|
103
119
|
|
|
@@ -115,15 +131,32 @@ export type StackActionHelpers<ParamList extends ParamListBase> = {
|
|
|
115
131
|
? [
|
|
116
132
|
screen: RouteName,
|
|
117
133
|
params?: ParamList[RouteName],
|
|
118
|
-
options?: { merge?: boolean },
|
|
134
|
+
options?: { merge?: boolean | undefined },
|
|
119
135
|
]
|
|
120
136
|
: [
|
|
121
137
|
screen: RouteName,
|
|
122
138
|
params: ParamList[RouteName],
|
|
123
|
-
options?: { merge?: boolean },
|
|
139
|
+
options?: { merge?: boolean | undefined },
|
|
124
140
|
]
|
|
125
141
|
: never
|
|
126
142
|
): void;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Enable or disable retaining the current screen in the stack.
|
|
146
|
+
*
|
|
147
|
+
* When a retained route gets removed from the stack,
|
|
148
|
+
* it'll be kept in routes and can be navigated to again.
|
|
149
|
+
*
|
|
150
|
+
* @param enable Whether to retain the current route in the stack or not.
|
|
151
|
+
*/
|
|
152
|
+
retain(enable: boolean): void;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Dismiss a screen from the stack.
|
|
156
|
+
*
|
|
157
|
+
* @param [count=1] Number of screens to dismiss. Defaults to 1.
|
|
158
|
+
*/
|
|
159
|
+
dismiss(count?: number): void;
|
|
127
160
|
};
|
|
128
161
|
|
|
129
162
|
export const StackActions = {
|
|
@@ -148,7 +181,11 @@ export const StackActions = {
|
|
|
148
181
|
popToTop() {
|
|
149
182
|
return { type: 'POP_TO_TOP' } as const satisfies StackActionType;
|
|
150
183
|
},
|
|
151
|
-
popTo(
|
|
184
|
+
popTo(
|
|
185
|
+
name: string,
|
|
186
|
+
params?: object,
|
|
187
|
+
options?: { merge?: boolean | undefined }
|
|
188
|
+
) {
|
|
152
189
|
return {
|
|
153
190
|
type: 'POP_TO',
|
|
154
191
|
payload: {
|
|
@@ -158,6 +195,109 @@ export const StackActions = {
|
|
|
158
195
|
},
|
|
159
196
|
} as const satisfies StackActionType;
|
|
160
197
|
},
|
|
198
|
+
retain(enable: boolean) {
|
|
199
|
+
return {
|
|
200
|
+
type: 'RETAIN',
|
|
201
|
+
payload: { enable },
|
|
202
|
+
} as const satisfies StackActionType;
|
|
203
|
+
},
|
|
204
|
+
dismiss(count: number = 1) {
|
|
205
|
+
return {
|
|
206
|
+
type: 'DISMISS',
|
|
207
|
+
payload: { count },
|
|
208
|
+
} as const satisfies StackActionType;
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
function retainRoutes<ParamList extends ParamListBase>(
|
|
213
|
+
previousState: StackNavigationState<ParamList>,
|
|
214
|
+
nextState: StackNavigationState<ParamList>
|
|
215
|
+
) {
|
|
216
|
+
if (!nextState.retainedRouteKeys.length) {
|
|
217
|
+
return nextState;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const retainedRouteKeySet = new Set(nextState.retainedRouteKeys);
|
|
221
|
+
const nextRouteKeySet = new Set(nextState.routes.map((route) => route.key));
|
|
222
|
+
const retainedRoutes = getActiveRoutes(previousState).filter(
|
|
223
|
+
(route) =>
|
|
224
|
+
retainedRouteKeySet.has(route.key) && !nextRouteKeySet.has(route.key)
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
if (!retainedRoutes.length) {
|
|
228
|
+
return nextState;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const removedRetainedRouteKeys = new Set(
|
|
232
|
+
retainedRoutes.map((route) => route.key)
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
return getStateWithRoutes(
|
|
236
|
+
nextState,
|
|
237
|
+
getActiveRoutes(nextState),
|
|
238
|
+
getPreloadedRoutes(nextState),
|
|
239
|
+
retainedRoutes.concat(
|
|
240
|
+
getRetainedRoutes(nextState).filter(
|
|
241
|
+
(route) => !removedRetainedRouteKeys.has(route.key)
|
|
242
|
+
)
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const getActiveRoutes = <ParamList extends ParamListBase>(
|
|
248
|
+
state: StackNavigationState<ParamList>
|
|
249
|
+
) => state.routes.slice(0, state.index + 1);
|
|
250
|
+
|
|
251
|
+
const getInactiveRoutes = <ParamList extends ParamListBase>(
|
|
252
|
+
state: StackNavigationState<ParamList>
|
|
253
|
+
) => state.routes.slice(state.index + 1);
|
|
254
|
+
|
|
255
|
+
const getPreloadedRoutes = <ParamList extends ParamListBase>(
|
|
256
|
+
state: StackNavigationState<ParamList>
|
|
257
|
+
) => {
|
|
258
|
+
const retainedRouteKeySet = new Set(state.retainedRouteKeys);
|
|
259
|
+
|
|
260
|
+
return getInactiveRoutes(state).filter(
|
|
261
|
+
(route) => !retainedRouteKeySet.has(route.key)
|
|
262
|
+
);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const getRetainedRoutes = <ParamList extends ParamListBase>(
|
|
266
|
+
state: StackNavigationState<ParamList>
|
|
267
|
+
) => {
|
|
268
|
+
const retainedRouteKeySet = new Set(state.retainedRouteKeys);
|
|
269
|
+
|
|
270
|
+
return getInactiveRoutes(state).filter((route) =>
|
|
271
|
+
retainedRouteKeySet.has(route.key)
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const getStateWithRoutes = <ParamList extends ParamListBase>(
|
|
276
|
+
state: StackNavigationState<ParamList>,
|
|
277
|
+
activeRoutes: Route<string>[],
|
|
278
|
+
preloadedRoutes = getPreloadedRoutes(state),
|
|
279
|
+
retainedRoutes = getRetainedRoutes(state)
|
|
280
|
+
) => {
|
|
281
|
+
const routeKeySet = new Set(activeRoutes.map((route) => route.key));
|
|
282
|
+
const retainedRouteKeySet = new Set(state.retainedRouteKeys);
|
|
283
|
+
|
|
284
|
+
const filteredRetainedRoutes = retainedRoutes.filter(
|
|
285
|
+
(route) => !routeKeySet.has(route.key)
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const filteredPreloadedRoutes = preloadedRoutes.filter(
|
|
289
|
+
(route) =>
|
|
290
|
+
!retainedRouteKeySet.has(route.key) && !routeKeySet.has(route.key)
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
...state,
|
|
295
|
+
index: activeRoutes.length - 1,
|
|
296
|
+
routes: activeRoutes.concat(
|
|
297
|
+
filteredRetainedRoutes,
|
|
298
|
+
filteredPreloadedRoutes
|
|
299
|
+
),
|
|
300
|
+
};
|
|
161
301
|
};
|
|
162
302
|
|
|
163
303
|
export function StackRouter(options: StackRouterOptions) {
|
|
@@ -176,13 +316,19 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
176
316
|
? options.initialRouteName
|
|
177
317
|
: routeNames[0];
|
|
178
318
|
|
|
319
|
+
if (initialRouteName == null) {
|
|
320
|
+
throw new Error(
|
|
321
|
+
"Couldn't initialize the stack navigator. Have you defined any screens?"
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
179
325
|
return {
|
|
180
326
|
stale: false,
|
|
181
327
|
type: 'stack',
|
|
182
328
|
key: `stack-${nanoid()}`,
|
|
183
329
|
index: 0,
|
|
184
330
|
routeNames,
|
|
185
|
-
|
|
331
|
+
retainedRouteKeys: [],
|
|
186
332
|
routes: [
|
|
187
333
|
{
|
|
188
334
|
key: `${initialRouteName}-${nanoid()}`,
|
|
@@ -214,30 +360,19 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
214
360
|
: route.params,
|
|
215
361
|
}));
|
|
216
362
|
|
|
217
|
-
const preloadedRoutes =
|
|
218
|
-
state.preloadedRoutes
|
|
219
|
-
?.filter((route) => routeNames.includes(route.name))
|
|
220
|
-
.map(
|
|
221
|
-
(route) =>
|
|
222
|
-
({
|
|
223
|
-
...route,
|
|
224
|
-
key: route.key || `${route.name}-${nanoid()}`,
|
|
225
|
-
params:
|
|
226
|
-
routeParamList[route.name] !== undefined
|
|
227
|
-
? {
|
|
228
|
-
...routeParamList[route.name],
|
|
229
|
-
...route.params,
|
|
230
|
-
}
|
|
231
|
-
: route.params,
|
|
232
|
-
}) as Route<string>
|
|
233
|
-
) ?? [];
|
|
234
|
-
|
|
235
363
|
if (routes.length === 0) {
|
|
236
364
|
const initialRouteName =
|
|
237
|
-
options.initialRouteName !== undefined
|
|
365
|
+
options.initialRouteName !== undefined &&
|
|
366
|
+
routeNames.includes(options.initialRouteName)
|
|
238
367
|
? options.initialRouteName
|
|
239
368
|
: routeNames[0];
|
|
240
369
|
|
|
370
|
+
if (initialRouteName == null) {
|
|
371
|
+
throw new Error(
|
|
372
|
+
"Couldn't initialize the stack navigator. Have you defined any screens?"
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
241
376
|
routes.push({
|
|
242
377
|
key: `${initialRouteName}-${nanoid()}`,
|
|
243
378
|
name: initialRouteName,
|
|
@@ -245,14 +380,23 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
245
380
|
});
|
|
246
381
|
}
|
|
247
382
|
|
|
383
|
+
const index = Math.min(
|
|
384
|
+
Math.max(state.index ?? routes.length - 1, 0),
|
|
385
|
+
routes.length - 1
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
const routeKeys = new Set(routes.map((route) => route.key));
|
|
389
|
+
const retainedRouteKeys =
|
|
390
|
+
state.retainedRouteKeys?.filter((key) => routeKeys.has(key)) ?? [];
|
|
391
|
+
|
|
248
392
|
return {
|
|
249
393
|
stale: false,
|
|
250
394
|
type: 'stack',
|
|
251
395
|
key: `stack-${nanoid()}`,
|
|
252
|
-
index
|
|
396
|
+
index,
|
|
253
397
|
routeNames,
|
|
254
398
|
routes,
|
|
255
|
-
|
|
399
|
+
retainedRouteKeys,
|
|
256
400
|
};
|
|
257
401
|
},
|
|
258
402
|
|
|
@@ -260,7 +404,19 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
260
404
|
state,
|
|
261
405
|
{ routeNames, routeParamList, routeKeyChanges }
|
|
262
406
|
) {
|
|
263
|
-
const routes = state.
|
|
407
|
+
const routes = getActiveRoutes(state).filter(
|
|
408
|
+
(route) =>
|
|
409
|
+
routeNames.includes(route.name) &&
|
|
410
|
+
!routeKeyChanges.includes(route.name)
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
const preloadedRoutes = getPreloadedRoutes(state).filter(
|
|
414
|
+
(route) =>
|
|
415
|
+
routeNames.includes(route.name) &&
|
|
416
|
+
!routeKeyChanges.includes(route.name)
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
const retainedRoutes = getRetainedRoutes(state).filter(
|
|
264
420
|
(route) =>
|
|
265
421
|
routeNames.includes(route.name) &&
|
|
266
422
|
!routeKeyChanges.includes(route.name)
|
|
@@ -273,6 +429,12 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
273
429
|
? options.initialRouteName
|
|
274
430
|
: routeNames[0];
|
|
275
431
|
|
|
432
|
+
if (initialRouteName == null) {
|
|
433
|
+
throw new Error(
|
|
434
|
+
"Couldn't initialize the stack navigator. Have you defined any screens?"
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
276
438
|
routes.push({
|
|
277
439
|
key: `${initialRouteName}-${nanoid()}`,
|
|
278
440
|
name: initialRouteName,
|
|
@@ -280,51 +442,73 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
280
442
|
});
|
|
281
443
|
}
|
|
282
444
|
|
|
283
|
-
|
|
284
|
-
...
|
|
285
|
-
|
|
445
|
+
const routeKeys = new Set(
|
|
446
|
+
[...routes, ...preloadedRoutes, ...retainedRoutes].map(
|
|
447
|
+
(route) => route.key
|
|
448
|
+
)
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
const retainedRouteKeys = state.retainedRouteKeys.filter((key) =>
|
|
452
|
+
routeKeys.has(key)
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
return getStateWithRoutes(
|
|
456
|
+
{
|
|
457
|
+
...state,
|
|
458
|
+
routeNames,
|
|
459
|
+
retainedRouteKeys,
|
|
460
|
+
},
|
|
286
461
|
routes,
|
|
287
|
-
|
|
288
|
-
|
|
462
|
+
preloadedRoutes,
|
|
463
|
+
retainedRoutes
|
|
464
|
+
);
|
|
289
465
|
},
|
|
290
466
|
|
|
291
467
|
getStateForRouteFocus(state, key) {
|
|
292
|
-
const
|
|
468
|
+
const activeRoutes = getActiveRoutes(state);
|
|
293
469
|
|
|
294
|
-
|
|
470
|
+
const route = state.routes.find((route) => route.key === key);
|
|
471
|
+
|
|
472
|
+
if (route == null || route === activeRoutes.at(-1)) {
|
|
295
473
|
return state;
|
|
296
474
|
}
|
|
297
475
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
index
|
|
301
|
-
|
|
302
|
-
|
|
476
|
+
const index = activeRoutes.indexOf(route);
|
|
477
|
+
const routes =
|
|
478
|
+
index === -1
|
|
479
|
+
? activeRoutes.concat(route)
|
|
480
|
+
: activeRoutes.slice(0, index + 1);
|
|
481
|
+
|
|
482
|
+
return retainRoutes(state, getStateWithRoutes(state, routes));
|
|
303
483
|
},
|
|
304
484
|
|
|
305
485
|
getStateForAction(state, action, options) {
|
|
306
486
|
const { routeParamList } = options;
|
|
307
487
|
|
|
488
|
+
const routes = getActiveRoutes(state);
|
|
489
|
+
const preloadedRoutes = getPreloadedRoutes(state);
|
|
490
|
+
const inactiveRoutes = getInactiveRoutes(state);
|
|
491
|
+
|
|
308
492
|
switch (action.type) {
|
|
309
493
|
case 'REPLACE': {
|
|
494
|
+
if (!state.routeNames.includes(action.payload.name)) {
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
|
|
310
498
|
const currentIndex =
|
|
311
|
-
action.
|
|
312
|
-
?
|
|
499
|
+
action.source !== undefined
|
|
500
|
+
? routes.findIndex((r) => r.key === action.source)
|
|
313
501
|
: state.index;
|
|
314
502
|
|
|
315
503
|
if (currentIndex === -1) {
|
|
316
504
|
return null;
|
|
317
505
|
}
|
|
318
506
|
|
|
319
|
-
if (!state.routeNames.includes(action.payload.name)) {
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
507
|
const getId = options.routeGetIdList[action.payload.name];
|
|
324
508
|
const id = getId?.({ params: action.payload.params });
|
|
325
509
|
|
|
326
|
-
// Re-use
|
|
327
|
-
let route =
|
|
510
|
+
// Re-use inactive route if available
|
|
511
|
+
let route = inactiveRoutes.find(
|
|
328
512
|
(route) =>
|
|
329
513
|
route.name === action.payload.name &&
|
|
330
514
|
id === getId?.({ params: route.params })
|
|
@@ -332,17 +516,22 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
332
516
|
|
|
333
517
|
if (!route) {
|
|
334
518
|
route = createRouteFromAction({ action, routeParamList });
|
|
519
|
+
} else {
|
|
520
|
+
const params = createParamsFromAction({ action, routeParamList });
|
|
521
|
+
|
|
522
|
+
if (route.params !== params) {
|
|
523
|
+
route = { ...route, params };
|
|
524
|
+
}
|
|
335
525
|
}
|
|
336
526
|
|
|
337
|
-
return
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
};
|
|
527
|
+
return retainRoutes(
|
|
528
|
+
state,
|
|
529
|
+
getStateWithRoutes(
|
|
530
|
+
state,
|
|
531
|
+
routes.map((r, i) => (i === currentIndex ? route : r)),
|
|
532
|
+
preloadedRoutes.filter((r) => r.key !== route.key)
|
|
533
|
+
)
|
|
534
|
+
);
|
|
346
535
|
}
|
|
347
536
|
|
|
348
537
|
case 'PUSH':
|
|
@@ -354,20 +543,41 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
354
543
|
const getId = options.routeGetIdList[action.payload.name];
|
|
355
544
|
const id = getId?.({ params: action.payload.params });
|
|
356
545
|
|
|
546
|
+
let remainingRoutes = routes;
|
|
357
547
|
let route: Route<string> | undefined;
|
|
358
548
|
|
|
359
549
|
if (action.type === 'NAVIGATE') {
|
|
360
|
-
const
|
|
550
|
+
const currentIndex =
|
|
551
|
+
action.source !== undefined
|
|
552
|
+
? routes.findIndex((r) => r.key === action.source)
|
|
553
|
+
: state.index;
|
|
361
554
|
|
|
362
|
-
if (
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
555
|
+
if (currentIndex === -1) {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* When navigating,
|
|
561
|
+
* - If the current route matches the destination, reuse it.
|
|
562
|
+
* - Or, if a route matching the destination exists after the current, reuse it.
|
|
563
|
+
* - Remove all non-matching routes after the current.
|
|
564
|
+
*/
|
|
565
|
+
remainingRoutes = routes.slice(0, currentIndex + 1);
|
|
566
|
+
route = routes.find(
|
|
567
|
+
(route, i) =>
|
|
568
|
+
i >= currentIndex &&
|
|
569
|
+
route.name === action.payload.name &&
|
|
570
|
+
(id === undefined || id === getId?.({ params: route.params }))
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
if (!route && action.payload.pop) {
|
|
574
|
+
if (id !== undefined) {
|
|
575
|
+
for (let i = remainingRoutes.length - 1; i >= 0; i--) {
|
|
576
|
+
const r = remainingRoutes[i];
|
|
577
|
+
|
|
578
|
+
if (r == null) {
|
|
579
|
+
throw new Error(`Couldn't find a route at index ${i}.`);
|
|
580
|
+
}
|
|
371
581
|
|
|
372
582
|
if (r.name !== action.payload.name) {
|
|
373
583
|
continue;
|
|
@@ -380,13 +590,21 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
380
590
|
|
|
381
591
|
if (r.history?.length) {
|
|
382
592
|
for (let j = r.history.length - 1; j >= 0; j--) {
|
|
593
|
+
const historyEntry = r.history[j];
|
|
594
|
+
|
|
595
|
+
if (historyEntry == null) {
|
|
596
|
+
throw new Error(
|
|
597
|
+
`Couldn't find a route history entry at index ${j}.`
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
|
|
383
601
|
if (
|
|
384
|
-
|
|
385
|
-
id === getId?.({ params:
|
|
602
|
+
historyEntry.type === 'params' &&
|
|
603
|
+
id === getId?.({ params: historyEntry.params })
|
|
386
604
|
) {
|
|
387
605
|
route = {
|
|
388
606
|
...r,
|
|
389
|
-
params:
|
|
607
|
+
params: historyEntry.params,
|
|
390
608
|
history: r.history.slice(0, j),
|
|
391
609
|
};
|
|
392
610
|
break;
|
|
@@ -398,13 +616,8 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
398
616
|
}
|
|
399
617
|
}
|
|
400
618
|
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// If the route matches the current one, then navigate to it
|
|
404
|
-
if (action.payload.name === currentRoute.name) {
|
|
405
|
-
route = currentRoute;
|
|
406
|
-
} else if (action.payload.pop) {
|
|
407
|
-
route = state.routes.findLast(
|
|
619
|
+
} else {
|
|
620
|
+
route = remainingRoutes.findLast(
|
|
408
621
|
(route) => route.name === action.payload.name
|
|
409
622
|
);
|
|
410
623
|
}
|
|
@@ -412,7 +625,7 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
412
625
|
}
|
|
413
626
|
|
|
414
627
|
if (!route) {
|
|
415
|
-
route =
|
|
628
|
+
route = inactiveRoutes.find(
|
|
416
629
|
(route) =>
|
|
417
630
|
route.name === action.payload.name &&
|
|
418
631
|
id === getId?.({ params: route.params })
|
|
@@ -435,43 +648,35 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
435
648
|
params = createParamsFromAction({ action, routeParamList });
|
|
436
649
|
}
|
|
437
650
|
|
|
438
|
-
let
|
|
651
|
+
let nextRoutes: Route<string>[];
|
|
439
652
|
|
|
440
653
|
if (route) {
|
|
441
654
|
if (action.type === 'NAVIGATE' && action.payload.pop) {
|
|
442
|
-
|
|
655
|
+
nextRoutes = [];
|
|
443
656
|
|
|
444
|
-
// Get all routes
|
|
445
|
-
for (const r of
|
|
657
|
+
// Get all routes before the matching one
|
|
658
|
+
for (const r of remainingRoutes) {
|
|
446
659
|
if (r.key === route.key) {
|
|
447
|
-
routes.push({
|
|
448
|
-
...route,
|
|
449
|
-
path:
|
|
450
|
-
action.payload.path !== undefined
|
|
451
|
-
? action.payload.path
|
|
452
|
-
: route.path,
|
|
453
|
-
params,
|
|
454
|
-
});
|
|
455
660
|
break;
|
|
456
661
|
}
|
|
457
662
|
|
|
458
|
-
|
|
663
|
+
nextRoutes.push(r);
|
|
459
664
|
}
|
|
460
665
|
} else {
|
|
461
|
-
|
|
462
|
-
routes.push({
|
|
463
|
-
...route,
|
|
464
|
-
path:
|
|
465
|
-
action.type === 'NAVIGATE' &&
|
|
466
|
-
action.payload.path !== undefined
|
|
467
|
-
? action.payload.path
|
|
468
|
-
: route.path,
|
|
469
|
-
params,
|
|
470
|
-
});
|
|
666
|
+
nextRoutes = remainingRoutes.filter((r) => r.key !== route.key);
|
|
471
667
|
}
|
|
668
|
+
|
|
669
|
+
nextRoutes.push({
|
|
670
|
+
...route,
|
|
671
|
+
path:
|
|
672
|
+
action.type === 'NAVIGATE' && action.payload.path !== undefined
|
|
673
|
+
? action.payload.path
|
|
674
|
+
: route.path,
|
|
675
|
+
params,
|
|
676
|
+
});
|
|
472
677
|
} else {
|
|
473
|
-
|
|
474
|
-
...
|
|
678
|
+
nextRoutes = [
|
|
679
|
+
...remainingRoutes,
|
|
475
680
|
{
|
|
476
681
|
key: `${action.payload.name}-${nanoid()}`,
|
|
477
682
|
name: action.payload.name,
|
|
@@ -482,41 +687,41 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
482
687
|
];
|
|
483
688
|
}
|
|
484
689
|
|
|
485
|
-
return
|
|
486
|
-
...state,
|
|
487
|
-
index: routes.length - 1,
|
|
488
|
-
preloadedRoutes: state.preloadedRoutes.filter(
|
|
489
|
-
(route) => routes[routes.length - 1].key !== route.key
|
|
490
|
-
),
|
|
491
|
-
routes,
|
|
492
|
-
};
|
|
690
|
+
return retainRoutes(state, getStateWithRoutes(state, nextRoutes));
|
|
493
691
|
}
|
|
494
692
|
|
|
495
693
|
case 'POP': {
|
|
496
694
|
let currentIndex =
|
|
497
|
-
action.
|
|
498
|
-
?
|
|
695
|
+
action.source !== undefined
|
|
696
|
+
? routes.findIndex((r) => r.key === action.source)
|
|
499
697
|
: state.index;
|
|
500
698
|
|
|
501
|
-
|
|
699
|
+
if (currentIndex === -1) {
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
let route = routes[currentIndex];
|
|
704
|
+
|
|
705
|
+
if (route == null) {
|
|
706
|
+
throw new Error(`Couldn't find a route at index ${currentIndex}.`);
|
|
707
|
+
}
|
|
502
708
|
|
|
503
709
|
/**
|
|
504
710
|
* When popping entries,
|
|
505
711
|
* - Pop entries from route.history
|
|
506
|
-
* - Pop
|
|
712
|
+
* - Pop the route itself and continue from the route below it
|
|
507
713
|
*
|
|
508
714
|
* Repeat until:
|
|
509
715
|
* - We have popped the amount of items in count
|
|
510
716
|
* - There are no more items to pop
|
|
717
|
+
*
|
|
718
|
+
* Routes above the current route are removed.
|
|
511
719
|
*/
|
|
512
720
|
if (route.history?.length || currentIndex > 0) {
|
|
513
721
|
let count = action.payload.count;
|
|
514
|
-
let routes = state.routes;
|
|
515
722
|
|
|
516
723
|
while (count > 0 && (route.history?.length || currentIndex > 0)) {
|
|
517
724
|
if (route.history?.length) {
|
|
518
|
-
routes = [...routes];
|
|
519
|
-
|
|
520
725
|
const end = Math.min(count, route.history.length);
|
|
521
726
|
const last = route.history.at(-end);
|
|
522
727
|
const history = route.history.slice(0, -end);
|
|
@@ -524,7 +729,7 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
524
729
|
|
|
525
730
|
count = count - removed;
|
|
526
731
|
|
|
527
|
-
|
|
732
|
+
route = {
|
|
528
733
|
...route,
|
|
529
734
|
params: last?.type === 'params' ? last.params : route.params,
|
|
530
735
|
history,
|
|
@@ -532,33 +737,70 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
532
737
|
}
|
|
533
738
|
|
|
534
739
|
if (currentIndex > 0 && count > 0) {
|
|
535
|
-
|
|
536
|
-
|
|
740
|
+
count = count - 1;
|
|
741
|
+
currentIndex = currentIndex - 1;
|
|
537
742
|
|
|
538
|
-
|
|
539
|
-
.slice(0, end)
|
|
540
|
-
.concat(routes.slice(currentIndex + 1));
|
|
743
|
+
const currentRoute = routes[currentIndex];
|
|
541
744
|
|
|
542
|
-
|
|
745
|
+
if (currentRoute == null) {
|
|
746
|
+
throw new Error(
|
|
747
|
+
`Couldn't find a route at index ${currentIndex}.`
|
|
748
|
+
);
|
|
749
|
+
}
|
|
543
750
|
|
|
544
|
-
|
|
545
|
-
currentIndex = routes.length - 1;
|
|
546
|
-
route = routes[currentIndex];
|
|
751
|
+
route = currentRoute;
|
|
547
752
|
}
|
|
548
753
|
}
|
|
549
754
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
755
|
+
const nextRoutes = routes.slice(0, currentIndex + 1);
|
|
756
|
+
|
|
757
|
+
if (route !== routes[currentIndex]) {
|
|
758
|
+
nextRoutes[currentIndex] = route;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
return retainRoutes(state, getStateWithRoutes(state, nextRoutes));
|
|
555
762
|
}
|
|
556
763
|
|
|
557
764
|
return null;
|
|
558
765
|
}
|
|
559
766
|
|
|
767
|
+
case 'DISMISS': {
|
|
768
|
+
const currentIndex =
|
|
769
|
+
action.source !== undefined
|
|
770
|
+
? routes.findIndex((route) => route.key === action.source)
|
|
771
|
+
: state.index;
|
|
772
|
+
|
|
773
|
+
if (
|
|
774
|
+
currentIndex === -1 ||
|
|
775
|
+
routes.length === 1 ||
|
|
776
|
+
action.payload.count < 1
|
|
777
|
+
) {
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const count = Math.min(
|
|
782
|
+
action.payload.count,
|
|
783
|
+
currentIndex + 1,
|
|
784
|
+
routes.length - 1
|
|
785
|
+
);
|
|
786
|
+
|
|
787
|
+
const firstIndex = currentIndex - count + 1;
|
|
788
|
+
|
|
789
|
+
return retainRoutes(
|
|
790
|
+
state,
|
|
791
|
+
getStateWithRoutes(
|
|
792
|
+
state,
|
|
793
|
+
routes.slice(0, firstIndex).concat(routes.slice(currentIndex + 1))
|
|
794
|
+
)
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
|
|
560
798
|
case 'POP_TO_TOP': {
|
|
561
|
-
let route =
|
|
799
|
+
let route = routes[0];
|
|
800
|
+
|
|
801
|
+
if (route == null) {
|
|
802
|
+
throw new Error("Couldn't find a route at index 0.");
|
|
803
|
+
}
|
|
562
804
|
|
|
563
805
|
if (state.index > 0 || route.history?.length) {
|
|
564
806
|
if (route.history?.length) {
|
|
@@ -568,30 +810,26 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
568
810
|
};
|
|
569
811
|
}
|
|
570
812
|
|
|
571
|
-
return
|
|
572
|
-
...state,
|
|
573
|
-
index: 0,
|
|
574
|
-
routes: [route],
|
|
575
|
-
};
|
|
813
|
+
return retainRoutes(state, getStateWithRoutes(state, [route]));
|
|
576
814
|
}
|
|
577
815
|
|
|
578
816
|
return null;
|
|
579
817
|
}
|
|
580
818
|
|
|
581
819
|
case 'POP_TO': {
|
|
820
|
+
if (!state.routeNames.includes(action.payload.name)) {
|
|
821
|
+
return null;
|
|
822
|
+
}
|
|
823
|
+
|
|
582
824
|
const currentIndex =
|
|
583
|
-
action.
|
|
584
|
-
?
|
|
825
|
+
action.source !== undefined
|
|
826
|
+
? routes.findIndex((r) => r.key === action.source)
|
|
585
827
|
: state.index;
|
|
586
828
|
|
|
587
829
|
if (currentIndex === -1) {
|
|
588
830
|
return null;
|
|
589
831
|
}
|
|
590
832
|
|
|
591
|
-
if (!state.routeNames.includes(action.payload.name)) {
|
|
592
|
-
return null;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
833
|
// If the route already exists, navigate to it
|
|
596
834
|
let index = -1;
|
|
597
835
|
let historyIndex: number | undefined;
|
|
@@ -601,7 +839,11 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
601
839
|
|
|
602
840
|
if (id !== undefined) {
|
|
603
841
|
for (let i = currentIndex; i >= 0; i--) {
|
|
604
|
-
const r =
|
|
842
|
+
const r = routes[i];
|
|
843
|
+
|
|
844
|
+
if (r == null) {
|
|
845
|
+
throw new Error(`Couldn't find a route at index ${i}.`);
|
|
846
|
+
}
|
|
605
847
|
|
|
606
848
|
if (r.name !== action.payload.name) {
|
|
607
849
|
continue;
|
|
@@ -614,9 +856,17 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
614
856
|
|
|
615
857
|
if (r.history?.length) {
|
|
616
858
|
for (let j = r.history.length - 1; j >= 0; j--) {
|
|
859
|
+
const historyEntry = r.history[j];
|
|
860
|
+
|
|
861
|
+
if (historyEntry == null) {
|
|
862
|
+
throw new Error(
|
|
863
|
+
`Couldn't find a route history entry at index ${j}.`
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
|
|
617
867
|
if (
|
|
618
|
-
|
|
619
|
-
id === getId?.({ params:
|
|
868
|
+
historyEntry.type === 'params' &&
|
|
869
|
+
id === getId?.({ params: historyEntry.params })
|
|
620
870
|
) {
|
|
621
871
|
index = i;
|
|
622
872
|
historyIndex = j;
|
|
@@ -629,11 +879,29 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
629
879
|
}
|
|
630
880
|
}
|
|
631
881
|
}
|
|
632
|
-
} else if (state.routes[currentIndex].name === action.payload.name) {
|
|
633
|
-
index = currentIndex;
|
|
634
882
|
} else {
|
|
883
|
+
const currentRoute = routes[currentIndex];
|
|
884
|
+
|
|
885
|
+
if (currentRoute == null) {
|
|
886
|
+
throw new Error(
|
|
887
|
+
`Couldn't find a route at index ${currentIndex}.`
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
if (currentRoute.name === action.payload.name) {
|
|
892
|
+
index = currentIndex;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (id == null && index === -1) {
|
|
635
897
|
for (let i = currentIndex; i >= 0; i--) {
|
|
636
|
-
|
|
898
|
+
const route = routes[i];
|
|
899
|
+
|
|
900
|
+
if (route == null) {
|
|
901
|
+
throw new Error(`Couldn't find a route at index ${i}.`);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (route.name === action.payload.name) {
|
|
637
905
|
index = i;
|
|
638
906
|
break;
|
|
639
907
|
}
|
|
@@ -642,8 +910,8 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
642
910
|
|
|
643
911
|
// If the route doesn't exist, remove the current route and add the new one
|
|
644
912
|
if (index === -1) {
|
|
645
|
-
// Re-use
|
|
646
|
-
let route =
|
|
913
|
+
// Re-use inactive route if available
|
|
914
|
+
let route = inactiveRoutes.find(
|
|
647
915
|
(route) =>
|
|
648
916
|
route.name === action.payload.name &&
|
|
649
917
|
id === getId?.({ params: route.params })
|
|
@@ -651,27 +919,45 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
651
919
|
|
|
652
920
|
if (!route) {
|
|
653
921
|
route = createRouteFromAction({ action, routeParamList });
|
|
922
|
+
} else {
|
|
923
|
+
const params = createParamsFromAction({ action, routeParamList });
|
|
924
|
+
|
|
925
|
+
if (route.params !== params) {
|
|
926
|
+
route = { ...route, params };
|
|
927
|
+
}
|
|
654
928
|
}
|
|
655
929
|
|
|
656
|
-
const
|
|
930
|
+
const nextRoutes = routes.slice(0, currentIndex).concat(route);
|
|
657
931
|
|
|
658
|
-
return
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
(r) => r.key !== route.key
|
|
664
|
-
)
|
|
665
|
-
|
|
932
|
+
return retainRoutes(
|
|
933
|
+
state,
|
|
934
|
+
getStateWithRoutes(
|
|
935
|
+
state,
|
|
936
|
+
nextRoutes,
|
|
937
|
+
preloadedRoutes.filter((r) => r.key !== route.key)
|
|
938
|
+
)
|
|
939
|
+
);
|
|
666
940
|
}
|
|
667
941
|
|
|
668
|
-
const route =
|
|
942
|
+
const route = routes[index];
|
|
943
|
+
|
|
944
|
+
if (route == null) {
|
|
945
|
+
throw new Error(`Couldn't find a route at index ${index}.`);
|
|
946
|
+
}
|
|
669
947
|
|
|
670
948
|
let baseParams = route.params;
|
|
671
949
|
let history = route.history;
|
|
672
950
|
|
|
673
951
|
if (historyIndex !== undefined && route.history) {
|
|
674
|
-
|
|
952
|
+
const historyEntry = route.history[historyIndex];
|
|
953
|
+
|
|
954
|
+
if (historyEntry == null) {
|
|
955
|
+
throw new Error(
|
|
956
|
+
`Couldn't find a route history entry at index ${historyIndex}.`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
baseParams = historyEntry.params;
|
|
675
961
|
history = route.history.slice(0, historyIndex);
|
|
676
962
|
}
|
|
677
963
|
|
|
@@ -691,73 +977,104 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
691
977
|
params = createParamsFromAction({ action, routeParamList });
|
|
692
978
|
}
|
|
693
979
|
|
|
694
|
-
return
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
...state.routes.slice(0, index),
|
|
980
|
+
return retainRoutes(
|
|
981
|
+
state,
|
|
982
|
+
getStateWithRoutes(state, [
|
|
983
|
+
...routes.slice(0, index),
|
|
699
984
|
params !== baseParams || historyIndex !== undefined
|
|
700
985
|
? { ...route, params, history }
|
|
701
|
-
:
|
|
702
|
-
]
|
|
703
|
-
|
|
986
|
+
: route,
|
|
987
|
+
])
|
|
988
|
+
);
|
|
704
989
|
}
|
|
705
990
|
|
|
706
|
-
case 'GO_BACK':
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
}
|
|
991
|
+
case 'GO_BACK': {
|
|
992
|
+
return router.getStateForAction(
|
|
993
|
+
state,
|
|
994
|
+
{
|
|
995
|
+
type: 'POP',
|
|
996
|
+
payload: { count: 1 },
|
|
997
|
+
target: action.target,
|
|
998
|
+
source: action.source,
|
|
999
|
+
},
|
|
1000
|
+
options
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
719
1003
|
|
|
720
|
-
|
|
1004
|
+
case 'RETAIN': {
|
|
1005
|
+
const route = routes[state.index];
|
|
721
1006
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1007
|
+
if (route == null) {
|
|
1008
|
+
throw new Error(`Couldn't find a route at index ${state.index}.`);
|
|
1009
|
+
}
|
|
725
1010
|
|
|
726
|
-
|
|
1011
|
+
const routeKey = action.source ?? route.key;
|
|
727
1012
|
|
|
728
|
-
if (
|
|
729
|
-
|
|
730
|
-
(route) =>
|
|
731
|
-
route.name === action.payload.name &&
|
|
732
|
-
id === getId?.({ params: route.params })
|
|
733
|
-
);
|
|
1013
|
+
if (!state.routes.some((route) => route.key === routeKey)) {
|
|
1014
|
+
return null;
|
|
734
1015
|
}
|
|
735
1016
|
|
|
736
|
-
if (
|
|
1017
|
+
if (action.payload.enable) {
|
|
1018
|
+
if (state.retainedRouteKeys.includes(routeKey)) {
|
|
1019
|
+
return state;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
737
1022
|
return {
|
|
738
1023
|
...state,
|
|
739
|
-
|
|
740
|
-
if (r.key !== route?.key) {
|
|
741
|
-
return r;
|
|
742
|
-
}
|
|
743
|
-
return {
|
|
744
|
-
...r,
|
|
745
|
-
params: createParamsFromAction({ action, routeParamList }),
|
|
746
|
-
};
|
|
747
|
-
}),
|
|
1024
|
+
retainedRouteKeys: [...state.retainedRouteKeys, routeKey],
|
|
748
1025
|
};
|
|
749
|
-
}
|
|
750
|
-
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
if (!state.retainedRouteKeys.includes(routeKey)) {
|
|
1029
|
+
return state;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return getStateWithRoutes(
|
|
1033
|
+
{
|
|
751
1034
|
...state,
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1035
|
+
retainedRouteKeys: state.retainedRouteKeys.filter(
|
|
1036
|
+
(key) => key !== routeKey
|
|
1037
|
+
),
|
|
1038
|
+
},
|
|
1039
|
+
routes,
|
|
1040
|
+
preloadedRoutes.filter((route) => route.key !== routeKey)
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
case 'PRELOAD': {
|
|
1045
|
+
if (!state.routeNames.includes(action.payload.name)) {
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
const getId = options.routeGetIdList[action.payload.name];
|
|
1050
|
+
const id = getId?.({ params: action.payload.params });
|
|
1051
|
+
const params = createParamsFromAction({ action, routeParamList });
|
|
1052
|
+
|
|
1053
|
+
const route = preloadedRoutes.findLast(
|
|
1054
|
+
(route) =>
|
|
1055
|
+
route.name === action.payload.name &&
|
|
1056
|
+
id === getId?.({ params: route.params })
|
|
1057
|
+
);
|
|
1058
|
+
|
|
1059
|
+
if (route) {
|
|
1060
|
+
return getStateWithRoutes(
|
|
1061
|
+
state,
|
|
1062
|
+
routes,
|
|
1063
|
+
preloadedRoutes.map((r) =>
|
|
1064
|
+
r.key === route.key && r.params !== params
|
|
1065
|
+
? { ...r, params }
|
|
1066
|
+
: r
|
|
1067
|
+
)
|
|
1068
|
+
);
|
|
760
1069
|
}
|
|
1070
|
+
|
|
1071
|
+
return getStateWithRoutes(
|
|
1072
|
+
state,
|
|
1073
|
+
routes,
|
|
1074
|
+
preloadedRoutes.concat(
|
|
1075
|
+
createRouteFromAction({ action, routeParamList })
|
|
1076
|
+
)
|
|
1077
|
+
);
|
|
761
1078
|
}
|
|
762
1079
|
|
|
763
1080
|
default:
|
|
@@ -765,10 +1082,6 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
765
1082
|
}
|
|
766
1083
|
},
|
|
767
1084
|
|
|
768
|
-
getRoutesFromState(state) {
|
|
769
|
-
return [...state.routes, ...state.preloadedRoutes];
|
|
770
|
-
},
|
|
771
|
-
|
|
772
1085
|
actionCreators: StackActions,
|
|
773
1086
|
};
|
|
774
1087
|
|