@react-navigation/routers 8.0.0-alpha.0 → 8.0.0-alpha.10
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 +3 -2
- package/lib/module/BaseRouter.js.map +1 -1
- package/lib/module/CommonActions.js.map +1 -1
- package/lib/module/StackRouter.js +256 -136
- package/lib/module/StackRouter.js.map +1 -1
- package/lib/typescript/src/BaseRouter.d.ts +6 -6
- package/lib/typescript/src/BaseRouter.d.ts.map +1 -1
- package/lib/typescript/src/CommonActions.d.ts +34 -34
- package/lib/typescript/src/CommonActions.d.ts.map +1 -1
- package/lib/typescript/src/DrawerRouter.d.ts +3 -3
- package/lib/typescript/src/DrawerRouter.d.ts.map +1 -1
- package/lib/typescript/src/StackRouter.d.ts +40 -17
- package/lib/typescript/src/StackRouter.d.ts.map +1 -1
- package/lib/typescript/src/TabRouter.d.ts +4 -4
- package/lib/typescript/src/TabRouter.d.ts.map +1 -1
- package/lib/typescript/src/createParamsFromAction.d.ts +1 -1
- package/lib/typescript/src/createParamsFromAction.d.ts.map +1 -1
- package/lib/typescript/src/createRouteFromAction.d.ts +1 -1
- package/lib/typescript/src/createRouteFromAction.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +14 -14
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/BaseRouter.tsx +4 -4
- package/src/CommonActions.tsx +36 -34
- package/src/DrawerRouter.tsx +3 -3
- package/src/StackRouter.tsx +433 -182
- package/src/TabRouter.tsx +4 -4
- package/src/createParamsFromAction.tsx +1 -1
- package/src/createRouteFromAction.tsx +1 -1
- package/src/types.tsx +18 -14
package/lib/module/BaseRouter.js
CHANGED
|
@@ -47,11 +47,12 @@ export const BaseRouter = {
|
|
|
47
47
|
case 'RESET':
|
|
48
48
|
{
|
|
49
49
|
const nextState = action.payload;
|
|
50
|
-
|
|
50
|
+
const routeNamesSet = new Set(state.routeNames);
|
|
51
|
+
if (nextState.routes.length === 0 || nextState.routes.some(route => !routeNamesSet.has(route.name))) {
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
54
|
if (nextState.stale === false) {
|
|
54
|
-
if (state.routeNames.length !== nextState.routeNames.length || nextState.routeNames.some(name => !
|
|
55
|
+
if (state.routeNames.length !== nextState.routeNames.length || nextState.routeNames.some(name => !routeNamesSet.has(name))) {
|
|
55
56
|
return null;
|
|
56
57
|
}
|
|
57
58
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["nanoid","BaseRouter","getStateForAction","state","action","type","index","source","routes","findIndex","r","key","map","i","params","payload","history","nextState","length","some","route","
|
|
1
|
+
{"version":3,"names":["nanoid","BaseRouter","getStateForAction","state","action","type","index","source","routes","findIndex","r","key","map","i","params","payload","history","nextState","routeNamesSet","Set","routeNames","length","some","route","has","name","stale","shouldActionChangeFocus"],"sourceRoot":"../../src","sources":["BaseRouter.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["goBack","type","navigate","args","name","params","options","payload","merge","pop","Error","reset","state","setParams","replaceParams","pushParams","preload"],"sourceRoot":"../../src","sources":["CommonActions.tsx"],"mappings":";;AA2EA,OAAO,SAASA,MAAMA,CAAA,EAAW;EAC/B,OAAO;IAAEC,IAAI,EAAE;EAAU,CAAC;AAC5B;
|
|
1
|
+
{"version":3,"names":["goBack","type","navigate","args","name","params","options","payload","merge","pop","Error","reset","state","setParams","replaceParams","pushParams","preload"],"sourceRoot":"../../src","sources":["CommonActions.tsx"],"mappings":";;AA2EA,OAAO,SAASA,MAAMA,CAAA,EAAW;EAC/B,OAAO;IAAEC,IAAI,EAAE;EAAU,CAAC;AAC5B;AAqBA,OAAO,SAASC,QAAQA,CAAC,GAAGC,IAAS,EAAU;EAC7C,IAAI,OAAOA,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;IAC/B,MAAM,CAACC,IAAI,EAAEC,MAAM,EAAEC,OAAO,CAAC,GAAGH,IAAI;IAEpC,OAAO;MACLF,IAAI,EAAE,UAAU;MAChBM,OAAO,EAAE;QACPH,IAAI;QACJC,MAAM;QACNG,KAAK,EAAEF,OAAO,EAAEE,KAAK;QACrBC,GAAG,EAAEH,OAAO,EAAEG;MAChB;IACF,CAAC;EACH,CAAC,MAAM;IACL,MAAMF,OAAO,GAAGJ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE7B,IAAI,EAAE,MAAM,IAAII,OAAO,CAAC,EAAE;MACxB,MAAM,IAAIG,KAAK,CACb,8JACF,CAAC;IACH;IAEA,OAAO;MAAET,IAAI,EAAE,UAAU;MAAEM;IAAQ,CAAC;EACtC;AACF;AAEA,OAAO,SAASI,KAAKA,CAACC,KAAiB,EAAE;EACvC,OAAO;IAAEX,IAAI,EAAE,OAAO;IAAEM,OAAO,EAAEK;EAAM,CAAC;AAC1C;AAEA,OAAO,SAASC,SAASA,CAACR,MAAc,EAAE;EACxC,OAAO;IACLJ,IAAI,EAAE,YAAY;IAClBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASS,aAAaA,CAACT,MAAc,EAAE;EAC5C,OAAO;IACLJ,IAAI,EAAE,gBAAgB;IACtBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASU,UAAUA,CAACV,MAAc,EAAE;EACzC,OAAO;IACLJ,IAAI,EAAE,aAAa;IACnBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASW,OAAOA,CAACZ,IAAY,EAAEC,MAA2B,EAAE;EACjE,OAAO;IACLJ,IAAI,EAAE,SAAS;IACfM,OAAO,EAAE;MAAEH,IAAI;MAAEC;IAAO;EAC1B,CAAC;AACH","ignoreList":[]}
|
|
@@ -45,8 +45,50 @@ export const StackActions = {
|
|
|
45
45
|
merge: options?.merge
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
+
},
|
|
49
|
+
retain(enable) {
|
|
50
|
+
return {
|
|
51
|
+
type: 'RETAIN',
|
|
52
|
+
payload: {
|
|
53
|
+
enable
|
|
54
|
+
}
|
|
55
|
+
};
|
|
48
56
|
}
|
|
49
57
|
};
|
|
58
|
+
function retainRoutes(previousState, nextState) {
|
|
59
|
+
if (!nextState.retainedRouteKeys.length) {
|
|
60
|
+
return nextState;
|
|
61
|
+
}
|
|
62
|
+
const retainedRouteKeySet = new Set(nextState.retainedRouteKeys);
|
|
63
|
+
const nextRouteKeySet = new Set(nextState.routes.map(route => route.key));
|
|
64
|
+
const retainedRoutes = getActiveRoutes(previousState).filter(route => retainedRouteKeySet.has(route.key) && !nextRouteKeySet.has(route.key));
|
|
65
|
+
if (!retainedRoutes.length) {
|
|
66
|
+
return nextState;
|
|
67
|
+
}
|
|
68
|
+
const removedRetainedRouteKeys = new Set(retainedRoutes.map(route => route.key));
|
|
69
|
+
return getStateWithRoutes(nextState, getActiveRoutes(nextState), getPreloadedRoutes(nextState), retainedRoutes.concat(getRetainedRoutes(nextState).filter(route => !removedRetainedRouteKeys.has(route.key))));
|
|
70
|
+
}
|
|
71
|
+
const getActiveRoutes = state => state.routes.slice(0, state.index + 1);
|
|
72
|
+
const getInactiveRoutes = state => state.routes.slice(state.index + 1);
|
|
73
|
+
const getPreloadedRoutes = state => {
|
|
74
|
+
const retainedRouteKeySet = new Set(state.retainedRouteKeys);
|
|
75
|
+
return getInactiveRoutes(state).filter(route => !retainedRouteKeySet.has(route.key));
|
|
76
|
+
};
|
|
77
|
+
const getRetainedRoutes = state => {
|
|
78
|
+
const retainedRouteKeySet = new Set(state.retainedRouteKeys);
|
|
79
|
+
return getInactiveRoutes(state).filter(route => retainedRouteKeySet.has(route.key));
|
|
80
|
+
};
|
|
81
|
+
const getStateWithRoutes = (state, activeRoutes, preloadedRoutes = getPreloadedRoutes(state), retainedRoutes = getRetainedRoutes(state)) => {
|
|
82
|
+
const routeKeySet = new Set(activeRoutes.map(route => route.key));
|
|
83
|
+
const retainedRouteKeySet = new Set(state.retainedRouteKeys);
|
|
84
|
+
const filteredRetainedRoutes = retainedRoutes.filter(route => !routeKeySet.has(route.key));
|
|
85
|
+
const filteredPreloadedRoutes = preloadedRoutes.filter(route => !retainedRouteKeySet.has(route.key) && !routeKeySet.has(route.key));
|
|
86
|
+
return {
|
|
87
|
+
...state,
|
|
88
|
+
index: activeRoutes.length - 1,
|
|
89
|
+
routes: activeRoutes.concat(filteredRetainedRoutes, filteredPreloadedRoutes)
|
|
90
|
+
};
|
|
91
|
+
};
|
|
50
92
|
export function StackRouter(options) {
|
|
51
93
|
const router = {
|
|
52
94
|
...BaseRouter,
|
|
@@ -62,7 +104,7 @@ export function StackRouter(options) {
|
|
|
62
104
|
key: `stack-${nanoid()}`,
|
|
63
105
|
index: 0,
|
|
64
106
|
routeNames,
|
|
65
|
-
|
|
107
|
+
retainedRouteKeys: [],
|
|
66
108
|
routes: [{
|
|
67
109
|
key: `${initialRouteName}-${nanoid()}`,
|
|
68
110
|
name: initialRouteName,
|
|
@@ -86,14 +128,6 @@ export function StackRouter(options) {
|
|
|
86
128
|
...route.params
|
|
87
129
|
} : route.params
|
|
88
130
|
}));
|
|
89
|
-
const preloadedRoutes = state.preloadedRoutes?.filter(route => routeNames.includes(route.name)).map(route => ({
|
|
90
|
-
...route,
|
|
91
|
-
key: route.key || `${route.name}-${nanoid()}`,
|
|
92
|
-
params: routeParamList[route.name] !== undefined ? {
|
|
93
|
-
...routeParamList[route.name],
|
|
94
|
-
...route.params
|
|
95
|
-
} : route.params
|
|
96
|
-
})) ?? [];
|
|
97
131
|
if (routes.length === 0) {
|
|
98
132
|
const initialRouteName = options.initialRouteName !== undefined ? options.initialRouteName : routeNames[0];
|
|
99
133
|
routes.push({
|
|
@@ -102,14 +136,17 @@ export function StackRouter(options) {
|
|
|
102
136
|
params: routeParamList[initialRouteName]
|
|
103
137
|
});
|
|
104
138
|
}
|
|
139
|
+
const index = Math.min(Math.max(state.index ?? routes.length - 1, 0), routes.length - 1);
|
|
140
|
+
const routeKeys = new Set(routes.map(route => route.key));
|
|
141
|
+
const retainedRouteKeys = state.retainedRouteKeys?.filter(key => routeKeys.has(key)) ?? [];
|
|
105
142
|
return {
|
|
106
143
|
stale: false,
|
|
107
144
|
type: 'stack',
|
|
108
145
|
key: `stack-${nanoid()}`,
|
|
109
|
-
index
|
|
146
|
+
index,
|
|
110
147
|
routeNames,
|
|
111
148
|
routes,
|
|
112
|
-
|
|
149
|
+
retainedRouteKeys
|
|
113
150
|
};
|
|
114
151
|
},
|
|
115
152
|
getStateForRouteNamesChange(state, {
|
|
@@ -117,7 +154,9 @@ export function StackRouter(options) {
|
|
|
117
154
|
routeParamList,
|
|
118
155
|
routeKeyChanges
|
|
119
156
|
}) {
|
|
120
|
-
const routes = state.
|
|
157
|
+
const routes = getActiveRoutes(state).filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
|
|
158
|
+
const preloadedRoutes = getPreloadedRoutes(state).filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
|
|
159
|
+
const retainedRoutes = getRetainedRoutes(state).filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
|
|
121
160
|
if (routes.length === 0) {
|
|
122
161
|
const initialRouteName = options.initialRouteName !== undefined && routeNames.includes(options.initialRouteName) ? options.initialRouteName : routeNames[0];
|
|
123
162
|
routes.push({
|
|
@@ -126,32 +165,33 @@ export function StackRouter(options) {
|
|
|
126
165
|
params: routeParamList[initialRouteName]
|
|
127
166
|
});
|
|
128
167
|
}
|
|
129
|
-
|
|
168
|
+
const routeKeys = new Set([...routes, ...preloadedRoutes, ...retainedRoutes].map(route => route.key));
|
|
169
|
+
const retainedRouteKeys = state.retainedRouteKeys.filter(key => routeKeys.has(key));
|
|
170
|
+
return getStateWithRoutes({
|
|
130
171
|
...state,
|
|
131
172
|
routeNames,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
};
|
|
173
|
+
retainedRouteKeys
|
|
174
|
+
}, routes, preloadedRoutes, retainedRoutes);
|
|
135
175
|
},
|
|
136
176
|
getStateForRouteFocus(state, key) {
|
|
137
|
-
const
|
|
177
|
+
const routes = getActiveRoutes(state);
|
|
178
|
+
const index = routes.findIndex(r => r.key === key);
|
|
138
179
|
if (index === -1 || index === state.index) {
|
|
139
180
|
return state;
|
|
140
181
|
}
|
|
141
|
-
return
|
|
142
|
-
...state,
|
|
143
|
-
index,
|
|
144
|
-
routes: state.routes.slice(0, index + 1)
|
|
145
|
-
};
|
|
182
|
+
return retainRoutes(state, getStateWithRoutes(state, routes.slice(0, index + 1)));
|
|
146
183
|
},
|
|
147
184
|
getStateForAction(state, action, options) {
|
|
148
185
|
const {
|
|
149
186
|
routeParamList
|
|
150
187
|
} = options;
|
|
188
|
+
const routes = getActiveRoutes(state);
|
|
189
|
+
const preloadedRoutes = getPreloadedRoutes(state);
|
|
190
|
+
const inactiveRoutes = getInactiveRoutes(state);
|
|
151
191
|
switch (action.type) {
|
|
152
192
|
case 'REPLACE':
|
|
153
193
|
{
|
|
154
|
-
const currentIndex = action.target === state.key && action.source ?
|
|
194
|
+
const currentIndex = action.target === state.key && action.source ? routes.findIndex(r => r.key === action.source) : state.index;
|
|
155
195
|
if (currentIndex === -1) {
|
|
156
196
|
return null;
|
|
157
197
|
}
|
|
@@ -163,8 +203,8 @@ export function StackRouter(options) {
|
|
|
163
203
|
params: action.payload.params
|
|
164
204
|
});
|
|
165
205
|
|
|
166
|
-
// Re-use
|
|
167
|
-
let route =
|
|
206
|
+
// Re-use inactive route if available
|
|
207
|
+
let route = inactiveRoutes.find(route => route.name === action.payload.name && id === getId?.({
|
|
168
208
|
params: route.params
|
|
169
209
|
}));
|
|
170
210
|
if (!route) {
|
|
@@ -172,12 +212,19 @@ export function StackRouter(options) {
|
|
|
172
212
|
action,
|
|
173
213
|
routeParamList
|
|
174
214
|
});
|
|
215
|
+
} else {
|
|
216
|
+
const params = createParamsFromAction({
|
|
217
|
+
action,
|
|
218
|
+
routeParamList
|
|
219
|
+
});
|
|
220
|
+
if (route.params !== params) {
|
|
221
|
+
route = {
|
|
222
|
+
...route,
|
|
223
|
+
params
|
|
224
|
+
};
|
|
225
|
+
}
|
|
175
226
|
}
|
|
176
|
-
return
|
|
177
|
-
...state,
|
|
178
|
-
routes: state.routes.map((r, i) => i === currentIndex ? route : r),
|
|
179
|
-
preloadedRoutes: state.preloadedRoutes.filter(r => r.key !== route.key)
|
|
180
|
-
};
|
|
227
|
+
return retainRoutes(state, getStateWithRoutes(state, routes.map((r, i) => i === currentIndex ? route : r), preloadedRoutes.filter(r => r.key !== route.key)));
|
|
181
228
|
}
|
|
182
229
|
case 'PUSH':
|
|
183
230
|
case 'NAVIGATE':
|
|
@@ -190,22 +237,55 @@ export function StackRouter(options) {
|
|
|
190
237
|
params: action.payload.params
|
|
191
238
|
});
|
|
192
239
|
let route;
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
240
|
+
if (action.type === 'NAVIGATE') {
|
|
241
|
+
const currentRoute = routes[state.index];
|
|
242
|
+
if (id !== undefined) {
|
|
243
|
+
if (currentRoute.name === action.payload.name && id === getId?.({
|
|
244
|
+
params: currentRoute.params
|
|
245
|
+
})) {
|
|
246
|
+
route = currentRoute;
|
|
247
|
+
} else if (action.payload.pop) {
|
|
248
|
+
for (let i = routes.length - 1; i >= 0; i--) {
|
|
249
|
+
const r = routes[i];
|
|
250
|
+
if (r.name !== action.payload.name) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (id === getId?.({
|
|
254
|
+
params: r.params
|
|
255
|
+
})) {
|
|
256
|
+
route = r;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
if (r.history?.length) {
|
|
260
|
+
for (let j = r.history.length - 1; j >= 0; j--) {
|
|
261
|
+
if (r.history[j].type === 'params' && id === getId?.({
|
|
262
|
+
params: r.history[j].params
|
|
263
|
+
})) {
|
|
264
|
+
route = {
|
|
265
|
+
...r,
|
|
266
|
+
params: r.history[j].params,
|
|
267
|
+
history: r.history.slice(0, j)
|
|
268
|
+
};
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (route) {
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
// If the route matches the current one, then navigate to it
|
|
280
|
+
if (action.payload.name === currentRoute.name) {
|
|
281
|
+
route = currentRoute;
|
|
282
|
+
} else if (action.payload.pop) {
|
|
283
|
+
route = routes.findLast(route => route.name === action.payload.name);
|
|
284
|
+
}
|
|
205
285
|
}
|
|
206
286
|
}
|
|
207
287
|
if (!route) {
|
|
208
|
-
route =
|
|
288
|
+
route = inactiveRoutes.find(route => route.name === action.payload.name && id === getId?.({
|
|
209
289
|
params: route.params
|
|
210
290
|
}));
|
|
211
291
|
}
|
|
@@ -222,50 +302,55 @@ export function StackRouter(options) {
|
|
|
222
302
|
routeParamList
|
|
223
303
|
});
|
|
224
304
|
}
|
|
225
|
-
let
|
|
305
|
+
let nextRoutes;
|
|
226
306
|
if (route) {
|
|
227
307
|
if (action.type === 'NAVIGATE' && action.payload.pop) {
|
|
228
|
-
|
|
308
|
+
nextRoutes = [];
|
|
229
309
|
|
|
230
310
|
// Get all routes until the matching one
|
|
231
|
-
for (const r of
|
|
311
|
+
for (const r of routes) {
|
|
232
312
|
if (r.key === route.key) {
|
|
233
|
-
|
|
313
|
+
nextRoutes.push({
|
|
234
314
|
...route,
|
|
235
315
|
path: action.payload.path !== undefined ? action.payload.path : route.path,
|
|
236
316
|
params
|
|
237
317
|
});
|
|
238
318
|
break;
|
|
239
319
|
}
|
|
240
|
-
|
|
320
|
+
nextRoutes.push(r);
|
|
321
|
+
}
|
|
322
|
+
if (!nextRoutes.some(r => r.key === route.key)) {
|
|
323
|
+
nextRoutes.push({
|
|
324
|
+
...route,
|
|
325
|
+
path: action.payload.path !== undefined ? action.payload.path : route.path,
|
|
326
|
+
params
|
|
327
|
+
});
|
|
241
328
|
}
|
|
242
329
|
} else {
|
|
243
|
-
|
|
244
|
-
|
|
330
|
+
nextRoutes = routes.filter(r => r.key !== route.key);
|
|
331
|
+
nextRoutes.push({
|
|
245
332
|
...route,
|
|
246
333
|
path: action.type === 'NAVIGATE' && action.payload.path !== undefined ? action.payload.path : route.path,
|
|
247
334
|
params
|
|
248
335
|
});
|
|
249
336
|
}
|
|
250
337
|
} else {
|
|
251
|
-
|
|
338
|
+
nextRoutes = [...routes, {
|
|
252
339
|
key: `${action.payload.name}-${nanoid()}`,
|
|
253
340
|
name: action.payload.name,
|
|
254
341
|
path: action.type === 'NAVIGATE' ? action.payload.path : undefined,
|
|
255
342
|
params
|
|
256
343
|
}];
|
|
257
344
|
}
|
|
258
|
-
return
|
|
259
|
-
...state,
|
|
260
|
-
index: routes.length - 1,
|
|
261
|
-
preloadedRoutes: state.preloadedRoutes.filter(route => routes[routes.length - 1].key !== route.key),
|
|
262
|
-
routes
|
|
263
|
-
};
|
|
345
|
+
return retainRoutes(state, getStateWithRoutes(state, nextRoutes, preloadedRoutes.filter(route => nextRoutes[nextRoutes.length - 1].key !== route.key)));
|
|
264
346
|
}
|
|
265
347
|
case 'POP':
|
|
266
348
|
{
|
|
267
|
-
let currentIndex = action.target === state.key && action.source ?
|
|
268
|
-
|
|
349
|
+
let currentIndex = action.target === state.key && action.source ? routes.findIndex(r => r.key === action.source) : state.index;
|
|
350
|
+
if (currentIndex === -1) {
|
|
351
|
+
return null;
|
|
352
|
+
}
|
|
353
|
+
let route = routes[currentIndex];
|
|
269
354
|
|
|
270
355
|
/**
|
|
271
356
|
* When popping entries,
|
|
@@ -278,42 +363,38 @@ export function StackRouter(options) {
|
|
|
278
363
|
*/
|
|
279
364
|
if (route.history?.length || currentIndex > 0) {
|
|
280
365
|
let count = action.payload.count;
|
|
281
|
-
let
|
|
366
|
+
let nextRoutes = routes;
|
|
282
367
|
while (count > 0 && (route.history?.length || currentIndex > 0)) {
|
|
283
368
|
if (route.history?.length) {
|
|
284
|
-
|
|
369
|
+
nextRoutes = [...nextRoutes];
|
|
285
370
|
const end = Math.min(count, route.history.length);
|
|
286
371
|
const last = route.history.at(-end);
|
|
287
372
|
const history = route.history.slice(0, -end);
|
|
288
373
|
const removed = route.history.length - history.length;
|
|
289
374
|
count = count - removed;
|
|
290
|
-
|
|
375
|
+
nextRoutes[currentIndex] = {
|
|
291
376
|
...route,
|
|
292
377
|
params: last?.type === 'params' ? last.params : route.params,
|
|
293
378
|
history
|
|
294
379
|
};
|
|
295
380
|
}
|
|
296
381
|
if (currentIndex > 0 && count > 0) {
|
|
297
|
-
const length =
|
|
382
|
+
const length = nextRoutes.length;
|
|
298
383
|
const end = Math.max(currentIndex - count + 1, 1);
|
|
299
|
-
|
|
300
|
-
const removed = length -
|
|
384
|
+
nextRoutes = nextRoutes.slice(0, end).concat(nextRoutes.slice(currentIndex + 1));
|
|
385
|
+
const removed = length - nextRoutes.length;
|
|
301
386
|
count = count - removed;
|
|
302
|
-
currentIndex =
|
|
303
|
-
route =
|
|
387
|
+
currentIndex = nextRoutes.length - 1;
|
|
388
|
+
route = nextRoutes[currentIndex];
|
|
304
389
|
}
|
|
305
390
|
}
|
|
306
|
-
return
|
|
307
|
-
...state,
|
|
308
|
-
index: routes.length - 1,
|
|
309
|
-
routes
|
|
310
|
-
};
|
|
391
|
+
return retainRoutes(state, getStateWithRoutes(state, nextRoutes));
|
|
311
392
|
}
|
|
312
393
|
return null;
|
|
313
394
|
}
|
|
314
395
|
case 'POP_TO_TOP':
|
|
315
396
|
{
|
|
316
|
-
let route =
|
|
397
|
+
let route = routes[0];
|
|
317
398
|
if (state.index > 0 || route.history?.length) {
|
|
318
399
|
if (route.history?.length) {
|
|
319
400
|
route = {
|
|
@@ -321,17 +402,13 @@ export function StackRouter(options) {
|
|
|
321
402
|
history: undefined
|
|
322
403
|
};
|
|
323
404
|
}
|
|
324
|
-
return
|
|
325
|
-
...state,
|
|
326
|
-
index: 0,
|
|
327
|
-
routes: [route]
|
|
328
|
-
};
|
|
405
|
+
return retainRoutes(state, getStateWithRoutes(state, [route]));
|
|
329
406
|
}
|
|
330
407
|
return null;
|
|
331
408
|
}
|
|
332
409
|
case 'POP_TO':
|
|
333
410
|
{
|
|
334
|
-
const currentIndex = action.target === state.key && action.source ?
|
|
411
|
+
const currentIndex = action.target === state.key && action.source ? routes.findLastIndex(r => r.key === action.source) : state.index;
|
|
335
412
|
if (currentIndex === -1) {
|
|
336
413
|
return null;
|
|
337
414
|
}
|
|
@@ -341,19 +418,43 @@ export function StackRouter(options) {
|
|
|
341
418
|
|
|
342
419
|
// If the route already exists, navigate to it
|
|
343
420
|
let index = -1;
|
|
421
|
+
let historyIndex;
|
|
344
422
|
const getId = options.routeGetIdList[action.payload.name];
|
|
345
423
|
const id = getId?.({
|
|
346
424
|
params: action.payload.params
|
|
347
425
|
});
|
|
348
426
|
if (id !== undefined) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
427
|
+
for (let i = currentIndex; i >= 0; i--) {
|
|
428
|
+
const r = routes[i];
|
|
429
|
+
if (r.name !== action.payload.name) {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (id === getId?.({
|
|
433
|
+
params: r.params
|
|
434
|
+
})) {
|
|
435
|
+
index = i;
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
if (r.history?.length) {
|
|
439
|
+
for (let j = r.history.length - 1; j >= 0; j--) {
|
|
440
|
+
if (r.history[j].type === 'params' && id === getId?.({
|
|
441
|
+
params: r.history[j].params
|
|
442
|
+
})) {
|
|
443
|
+
index = i;
|
|
444
|
+
historyIndex = j;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
if (index !== -1) {
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
} else if (routes[currentIndex].name === action.payload.name) {
|
|
353
454
|
index = currentIndex;
|
|
354
455
|
} else {
|
|
355
456
|
for (let i = currentIndex; i >= 0; i--) {
|
|
356
|
-
if (
|
|
457
|
+
if (routes[i].name === action.payload.name) {
|
|
357
458
|
index = i;
|
|
358
459
|
break;
|
|
359
460
|
}
|
|
@@ -362,8 +463,8 @@ export function StackRouter(options) {
|
|
|
362
463
|
|
|
363
464
|
// If the route doesn't exist, remove the current route and add the new one
|
|
364
465
|
if (index === -1) {
|
|
365
|
-
// Re-use
|
|
366
|
-
let route =
|
|
466
|
+
// Re-use inactive route if available
|
|
467
|
+
let route = inactiveRoutes.find(route => route.name === action.payload.name && id === getId?.({
|
|
367
468
|
params: route.params
|
|
368
469
|
}));
|
|
369
470
|
if (!route) {
|
|
@@ -371,40 +472,49 @@ export function StackRouter(options) {
|
|
|
371
472
|
action,
|
|
372
473
|
routeParamList
|
|
373
474
|
});
|
|
475
|
+
} else {
|
|
476
|
+
const params = createParamsFromAction({
|
|
477
|
+
action,
|
|
478
|
+
routeParamList
|
|
479
|
+
});
|
|
480
|
+
if (route.params !== params) {
|
|
481
|
+
route = {
|
|
482
|
+
...route,
|
|
483
|
+
params
|
|
484
|
+
};
|
|
485
|
+
}
|
|
374
486
|
}
|
|
375
|
-
const
|
|
376
|
-
return
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
487
|
+
const nextRoutes = routes.slice(0, currentIndex).concat(route);
|
|
488
|
+
return retainRoutes(state, getStateWithRoutes(state, nextRoutes, preloadedRoutes.filter(r => r.key !== route.key)));
|
|
489
|
+
}
|
|
490
|
+
const route = routes[index];
|
|
491
|
+
let baseParams = route.params;
|
|
492
|
+
let history = route.history;
|
|
493
|
+
if (historyIndex !== undefined && route.history) {
|
|
494
|
+
baseParams = route.history[historyIndex].params;
|
|
495
|
+
history = route.history.slice(0, historyIndex);
|
|
382
496
|
}
|
|
383
|
-
const route = state.routes[index];
|
|
384
497
|
let params;
|
|
385
498
|
if (action.payload.merge) {
|
|
386
499
|
params = action.payload.params !== undefined || routeParamList[route.name] !== undefined ? {
|
|
387
500
|
...routeParamList[route.name],
|
|
388
|
-
...
|
|
501
|
+
...baseParams,
|
|
389
502
|
...action.payload.params
|
|
390
|
-
} :
|
|
503
|
+
} : baseParams;
|
|
391
504
|
} else {
|
|
392
505
|
params = createParamsFromAction({
|
|
393
506
|
action,
|
|
394
507
|
routeParamList
|
|
395
508
|
});
|
|
396
509
|
}
|
|
397
|
-
return {
|
|
398
|
-
...
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
params
|
|
403
|
-
} : state.routes[index]]
|
|
404
|
-
};
|
|
510
|
+
return retainRoutes(state, getStateWithRoutes(state, [...routes.slice(0, index), params !== baseParams || historyIndex !== undefined ? {
|
|
511
|
+
...route,
|
|
512
|
+
params,
|
|
513
|
+
history
|
|
514
|
+
} : routes[index]]));
|
|
405
515
|
}
|
|
406
516
|
case 'GO_BACK':
|
|
407
|
-
if (state.index > 0 ||
|
|
517
|
+
if (state.index > 0 || routes[state.index].history?.length) {
|
|
408
518
|
return router.getStateForAction(state, {
|
|
409
519
|
type: 'POP',
|
|
410
520
|
payload: {
|
|
@@ -415,45 +525,55 @@ export function StackRouter(options) {
|
|
|
415
525
|
}, options);
|
|
416
526
|
}
|
|
417
527
|
return null;
|
|
528
|
+
case 'RETAIN':
|
|
529
|
+
{
|
|
530
|
+
const routeKey = action.source ?? routes[state.index].key;
|
|
531
|
+
if (!state.routes.some(route => route.key === routeKey)) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
if (action.payload.enable) {
|
|
535
|
+
if (state.retainedRouteKeys.includes(routeKey)) {
|
|
536
|
+
return state;
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
...state,
|
|
540
|
+
retainedRouteKeys: [...state.retainedRouteKeys, routeKey]
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
if (!state.retainedRouteKeys.includes(routeKey)) {
|
|
544
|
+
return state;
|
|
545
|
+
}
|
|
546
|
+
return getStateWithRoutes({
|
|
547
|
+
...state,
|
|
548
|
+
retainedRouteKeys: state.retainedRouteKeys.filter(key => key !== routeKey)
|
|
549
|
+
}, routes, preloadedRoutes.filter(route => route.key !== routeKey));
|
|
550
|
+
}
|
|
418
551
|
case 'PRELOAD':
|
|
419
552
|
{
|
|
553
|
+
if (!state.routeNames.includes(action.payload.name)) {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
420
556
|
const getId = options.routeGetIdList[action.payload.name];
|
|
421
557
|
const id = getId?.({
|
|
422
558
|
params: action.payload.params
|
|
423
559
|
});
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
560
|
+
const params = createParamsFromAction({
|
|
561
|
+
action,
|
|
562
|
+
routeParamList
|
|
563
|
+
});
|
|
564
|
+
const route = preloadedRoutes.findLast(route => route.name === action.payload.name && (id === undefined || id === getId?.({
|
|
565
|
+
params: route.params
|
|
566
|
+
})));
|
|
430
567
|
if (route) {
|
|
431
|
-
return {
|
|
432
|
-
...
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
return r;
|
|
436
|
-
}
|
|
437
|
-
return {
|
|
438
|
-
...r,
|
|
439
|
-
params: createParamsFromAction({
|
|
440
|
-
action,
|
|
441
|
-
routeParamList
|
|
442
|
-
})
|
|
443
|
-
};
|
|
444
|
-
})
|
|
445
|
-
};
|
|
446
|
-
} else {
|
|
447
|
-
return {
|
|
448
|
-
...state,
|
|
449
|
-
preloadedRoutes: state.preloadedRoutes.filter(r => r.name !== action.payload.name || id !== getId?.({
|
|
450
|
-
params: r.params
|
|
451
|
-
})).concat(createRouteFromAction({
|
|
452
|
-
action,
|
|
453
|
-
routeParamList
|
|
454
|
-
}))
|
|
455
|
-
};
|
|
568
|
+
return getStateWithRoutes(state, routes, preloadedRoutes.map(r => r.key === route.key && r.params !== params ? {
|
|
569
|
+
...r,
|
|
570
|
+
params
|
|
571
|
+
} : r));
|
|
456
572
|
}
|
|
573
|
+
return getStateWithRoutes(state, routes, preloadedRoutes.concat(createRouteFromAction({
|
|
574
|
+
action,
|
|
575
|
+
routeParamList
|
|
576
|
+
})));
|
|
457
577
|
}
|
|
458
578
|
default:
|
|
459
579
|
return BaseRouter.getStateForAction(state, action);
|