@@ -36,6 +36,13 @@ enum NavigatingType {
36
36
restore,
37
37
}
38
38
39
+ /// Maps the replacement route result to the correct generic type.
40
+ typedef MapRouteResultCallback <T extends Object ?> = T Function (Object ? result);
41
+
42
+ /// Pipe completer to the last route match completer.
43
+ typedef PipeRouteCompleterCallback = Completer <Next ?>
44
+ Function <Next extends Object ?>(Completer <Next ?> next);
45
+
39
46
/// The data class to be stored in [RouteInformation.state] to be used by
40
47
/// [GoRouteInformationParser] .
41
48
///
@@ -49,9 +56,16 @@ class RouteInformationState<T> {
49
56
this .completer,
50
57
this .baseRouteMatchList,
51
58
required this .type,
59
+ MapRouteResultCallback <T ?>? mapReplacementResult,
52
60
}) : assert ((type == NavigatingType .go || type == NavigatingType .restore) ==
53
61
(completer == null )),
54
- assert ((type != NavigatingType .go) == (baseRouteMatchList != null ));
62
+ assert ((type != NavigatingType .go) == (baseRouteMatchList != null )),
63
+ mapReplacementResult =
64
+ mapReplacementResult ?? _defaultMapReplacementResult;
65
+
66
+ static T ? _defaultMapReplacementResult <T >(Object ? result) {
67
+ return null ;
68
+ }
55
69
56
70
/// The extra object used when navigating with [GoRouter] .
57
71
final Object ? extra;
@@ -63,13 +77,30 @@ class RouteInformationState<T> {
63
77
/// [NavigatingType.restore] .
64
78
final Completer <T ?>? completer;
65
79
80
+ /// Maps the replacement result to the appropriate type, to resolve the
81
+ /// [completer] .
82
+ final MapRouteResultCallback <T ?> mapReplacementResult;
83
+
66
84
/// The base route match list to push on top to.
67
85
///
68
86
/// This is only null if [type] is [NavigatingType.go] .
69
87
final RouteMatchList ? baseRouteMatchList;
70
88
71
89
/// The type of navigation.
72
90
final NavigatingType type;
91
+
92
+ /// Pipes the completer to the next completer in the chain.
93
+ Completer <Next ?> pipeCompleter <Next extends Object ?>(Completer <Next ?> next) {
94
+ if (completer == null ) {
95
+ return next;
96
+ }
97
+
98
+ return _PipeCompleter <T ?, Next ?>(
99
+ next: next,
100
+ current: completer! ,
101
+ mapReplacementResult: mapReplacementResult,
102
+ );
103
+ }
73
104
}
74
105
75
106
/// The [RouteInformationProvider] created by go_router.
@@ -156,8 +187,12 @@ class GoRouteInformationProvider extends RouteInformationProvider
156
187
}
157
188
158
189
/// Pushes the `location` as a new route on top of `base` .
159
- Future <T ?> push <T >(String location,
160
- {required RouteMatchList base , Object ? extra}) {
190
+ Future <T ?> push <T >(
191
+ String location, {
192
+ required RouteMatchList base ,
193
+ Object ? extra,
194
+ MapRouteResultCallback <T ?>? mapReplacementResult,
195
+ }) {
161
196
final Completer <T ?> completer = Completer <T ?>();
162
197
_setValue (
163
198
location,
@@ -166,6 +201,7 @@ class GoRouteInformationProvider extends RouteInformationProvider
166
201
baseRouteMatchList: base ,
167
202
completer: completer,
168
203
type: NavigatingType .push,
204
+ mapReplacementResult: mapReplacementResult,
169
205
),
170
206
);
171
207
return completer.future;
@@ -196,8 +232,12 @@ class GoRouteInformationProvider extends RouteInformationProvider
196
232
197
233
/// Removes the top-most route match from `base` and pushes the `location` as a
198
234
/// new route on top.
199
- Future <T ?> pushReplacement <T >(String location,
200
- {required RouteMatchList base , Object ? extra}) {
235
+ Future <T ?> pushReplacement <T >(
236
+ String location, {
237
+ required RouteMatchList base ,
238
+ Object ? extra,
239
+ MapRouteResultCallback <T ?>? mapReplacementResult,
240
+ }) {
201
241
final Completer <T ?> completer = Completer <T ?>();
202
242
_setValue (
203
243
location,
@@ -206,14 +246,19 @@ class GoRouteInformationProvider extends RouteInformationProvider
206
246
baseRouteMatchList: base ,
207
247
completer: completer,
208
248
type: NavigatingType .pushReplacement,
249
+ mapReplacementResult: mapReplacementResult,
209
250
),
210
251
);
211
252
return completer.future;
212
253
}
213
254
214
255
/// Replaces the top-most route match from `base` with the `location` .
215
- Future <T ?> replace <T >(String location,
216
- {required RouteMatchList base , Object ? extra}) {
256
+ Future <T ?> replace <T >(
257
+ String location, {
258
+ required RouteMatchList base ,
259
+ Object ? extra,
260
+ MapRouteResultCallback <T ?>? mapReplacementResult,
261
+ }) {
217
262
final Completer <T ?> completer = Completer <T ?>();
218
263
_setValue (
219
264
location,
@@ -290,3 +335,42 @@ class GoRouteInformationProvider extends RouteInformationProvider
290
335
return SynchronousFuture <bool >(true );
291
336
}
292
337
}
338
+
339
+ /// Ensures the replacement routes can resolve the originating route completer.
340
+ /// Mainly used by [RouteInformationState.pipeCompleter]
341
+ class _PipeCompleter <Current extends Object ?, Next extends Object ?>
342
+ implements Completer <Next > {
343
+ _PipeCompleter ({
344
+ required Completer <Next > next,
345
+ required Completer <Current > current,
346
+ required MapRouteResultCallback <Current > mapReplacementResult,
347
+ }) : _next = next,
348
+ _current = current,
349
+ _mapReplacementResult = mapReplacementResult;
350
+
351
+ final Completer <Next > _next;
352
+ final Completer <Current > _current;
353
+ final MapRouteResultCallback <Current > _mapReplacementResult;
354
+
355
+ @override
356
+ void complete ([FutureOr <Next >? value]) {
357
+ _next.complete (value);
358
+ if (! _current.isCompleted) {
359
+ _current.complete (_mapReplacementResult (value));
360
+ }
361
+ }
362
+
363
+ @override
364
+ void completeError (Object error, [StackTrace ? stackTrace]) {
365
+ _next.completeError (error, stackTrace);
366
+ if (! _current.isCompleted) {
367
+ _current.completeError (error, stackTrace);
368
+ }
369
+ }
370
+
371
+ @override
372
+ Future <Next > get future => _next.future;
373
+
374
+ @override
375
+ bool get isCompleted => _next.isCompleted;
376
+ }
0 commit comments