-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[go_router]: add optional completer for replaced routes #6787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d3a7cc2
bb6880b
e8160c1
6fb4b62
426b705
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ class RouteInformationState<T> { | |
RouteInformationState({ | ||
this.extra, | ||
this.completer, | ||
this.onReplaceCompleter, | ||
this.baseRouteMatchList, | ||
required this.type, | ||
}) : assert((type == NavigatingType.go || type == NavigatingType.restore) == | ||
|
@@ -62,6 +63,10 @@ class RouteInformationState<T> { | |
/// [NavigatingType.restore]. | ||
final Completer<T?>? completer; | ||
|
||
/// The completer that needs to be completed when route is replaced. | ||
/// [completer] is ignored when replacing routes. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add only only used when type is NavigatingType.push or NavigatingType.pushReplacement |
||
final Completer<T?>? onReplaceCompleter; | ||
|
||
/// The base route match list to push on top to. | ||
/// | ||
/// This is only null if [type] is [NavigatingType.go]. | ||
|
@@ -146,8 +151,12 @@ class GoRouteInformationProvider extends RouteInformationProvider | |
} | ||
|
||
/// Pushes the `location` as a new route on top of `base`. | ||
Future<T?> push<T>(String location, | ||
{required RouteMatchList base, Object? extra}) { | ||
Future<T?> push<T>( | ||
String location, { | ||
required RouteMatchList base, | ||
Object? extra, | ||
Completer<T?>? onReplaceCompleter, | ||
}) { | ||
final Completer<T?> completer = Completer<T?>(); | ||
_setValue( | ||
location, | ||
|
@@ -156,6 +165,7 @@ class GoRouteInformationProvider extends RouteInformationProvider | |
baseRouteMatchList: base, | ||
completer: completer, | ||
type: NavigatingType.push, | ||
onReplaceCompleter: onReplaceCompleter, | ||
), | ||
); | ||
return completer.future; | ||
|
@@ -186,8 +196,12 @@ class GoRouteInformationProvider extends RouteInformationProvider | |
|
||
/// Removes the top-most route match from `base` and pushes the `location` as a | ||
/// new route on top. | ||
Future<T?> pushReplacement<T>(String location, | ||
{required RouteMatchList base, Object? extra}) { | ||
Future<T?> pushReplacement<T>( | ||
String location, { | ||
required RouteMatchList base, | ||
Object? extra, | ||
Completer<T?>? onReplaceCompleter, | ||
}) { | ||
final Completer<T?> completer = Completer<T?>(); | ||
_setValue( | ||
location, | ||
|
@@ -196,14 +210,19 @@ class GoRouteInformationProvider extends RouteInformationProvider | |
baseRouteMatchList: base, | ||
completer: completer, | ||
type: NavigatingType.pushReplacement, | ||
onReplaceCompleter: onReplaceCompleter, | ||
), | ||
); | ||
return completer.future; | ||
} | ||
|
||
/// Replaces the top-most route match from `base` with the `location`. | ||
Future<T?> replace<T>(String location, | ||
{required RouteMatchList base, Object? extra}) { | ||
Future<T?> replace<T>( | ||
String location, { | ||
required RouteMatchList base, | ||
Object? extra, | ||
Completer<T?>? onReplaceCompleter, | ||
}) { | ||
final Completer<T?> completer = Completer<T?>(); | ||
_setValue( | ||
location, | ||
|
@@ -212,6 +231,7 @@ class GoRouteInformationProvider extends RouteInformationProvider | |
baseRouteMatchList: base, | ||
completer: completer, | ||
type: NavigatingType.replace, | ||
onReplaceCompleter: onReplaceCompleter, | ||
), | ||
); | ||
return completer.future; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'dart:async'; | ||
|
||
import 'package:flutter/widgets.dart'; | ||
|
||
import '../router.dart'; | ||
|
@@ -46,21 +48,31 @@ extension GoRouterHelper on BuildContext { | |
/// * [replace] which replaces the top-most page of the page stack but treats | ||
/// it as the same page. The page key will be reused. This will preserve the | ||
/// state and not run any page animation. | ||
Future<T?> push<T extends Object?>(String location, {Object? extra}) => | ||
GoRouter.of(this).push<T>(location, extra: extra); | ||
Future<T?> push<T extends Object?>( | ||
String location, { | ||
Object? extra, | ||
Completer<T?>? onReplaceCompleter, | ||
}) => | ||
GoRouter.of(this).push<T>( | ||
location, | ||
extra: extra, | ||
onReplaceCompleter: onReplaceCompleter, | ||
); | ||
|
||
/// Navigate to a named route onto the page stack. | ||
Future<T?> pushNamed<T extends Object?>( | ||
String name, { | ||
Map<String, String> pathParameters = const <String, String>{}, | ||
Map<String, dynamic> queryParameters = const <String, dynamic>{}, | ||
Object? extra, | ||
Completer<T?>? onReplaceCompleter, | ||
}) => | ||
GoRouter.of(this).pushNamed<T>( | ||
name, | ||
pathParameters: pathParameters, | ||
queryParameters: queryParameters, | ||
extra: extra, | ||
onReplaceCompleter: onReplaceCompleter, | ||
); | ||
|
||
/// Returns `true` if there is more than 1 page on the stack. | ||
|
@@ -79,8 +91,16 @@ extension GoRouterHelper on BuildContext { | |
/// * [replace] which replaces the top-most page of the page stack but treats | ||
/// it as the same page. The page key will be reused. This will preserve the | ||
/// state and not run any page animation. | ||
void pushReplacement(String location, {Object? extra}) => | ||
GoRouter.of(this).pushReplacement(location, extra: extra); | ||
void pushReplacement( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just took a quick glance, should we make this return future instead of passing in a completer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have page A -> push -> page B -> pushReplacement -> page C, this still won't solve the problem because although we can track when the completer from pushReplacement finishes on page B by returning a Future, the Future on page A will never complete. In the _updateRouteMatchList function, in the case of NavigatingType.pushReplacement, the completer responsible for the future in the push method is simply removed and never completed. Passing a completer through the push method allows us to detect when such a page has been replaced. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the this is intended? the first push will never complete since it was replaced by another page regardless whether you pass in the completer or not |
||
String location, { | ||
Object? extra, | ||
Completer<Object?>? onReplaceCompleter, | ||
}) => | ||
GoRouter.of(this).pushReplacement( | ||
location, | ||
extra: extra, | ||
onReplaceCompleter: onReplaceCompleter, | ||
); | ||
|
||
/// Replaces the top-most page of the page stack with the named route w/ | ||
/// optional parameters, e.g. `name='person', pathParameters={'fid': 'f2', 'pid': | ||
|
@@ -94,12 +114,14 @@ extension GoRouterHelper on BuildContext { | |
Map<String, String> pathParameters = const <String, String>{}, | ||
Map<String, dynamic> queryParameters = const <String, dynamic>{}, | ||
Object? extra, | ||
Completer<Object?>? onReplaceCompleter, | ||
}) => | ||
GoRouter.of(this).pushReplacementNamed( | ||
name, | ||
pathParameters: pathParameters, | ||
queryParameters: queryParameters, | ||
extra: extra, | ||
onReplaceCompleter: onReplaceCompleter, | ||
); | ||
|
||
/// Replaces the top-most page of the page stack with the given one but treats | ||
|
@@ -112,8 +134,16 @@ extension GoRouterHelper on BuildContext { | |
/// * [push] which pushes the given location onto the page stack. | ||
/// * [pushReplacement] which replaces the top-most page of the page stack but | ||
/// always uses a new page key. | ||
void replace(String location, {Object? extra}) => | ||
GoRouter.of(this).replace<Object?>(location, extra: extra); | ||
void replace( | ||
String location, { | ||
Object? extra, | ||
Completer<Object?>? onReplaceCompleter, | ||
}) => | ||
GoRouter.of(this).replace<Object?>( | ||
location, | ||
extra: extra, | ||
onReplaceCompleter: onReplaceCompleter, | ||
); | ||
|
||
/// Replaces the top-most page with the named route and optional parameters, | ||
/// preserving the page key. | ||
|
@@ -131,9 +161,13 @@ extension GoRouterHelper on BuildContext { | |
Map<String, String> pathParameters = const <String, String>{}, | ||
Map<String, dynamic> queryParameters = const <String, dynamic>{}, | ||
Object? extra, | ||
Completer<Object?>? onReplaceCompleter, | ||
}) => | ||
GoRouter.of(this).replaceNamed<Object?>(name, | ||
pathParameters: pathParameters, | ||
queryParameters: queryParameters, | ||
extra: extra); | ||
GoRouter.of(this).replaceNamed<Object?>( | ||
name, | ||
pathParameters: pathParameters, | ||
queryParameters: queryParameters, | ||
extra: extra, | ||
onReplaceCompleter: onReplaceCompleter, | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.