Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f74ad0d
Return value when pop
NazarenoCavazzon Mar 3, 2023
72db2d6
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 3, 2023
ba08b81
Fixes
NazarenoCavazzon Mar 3, 2023
845dfbd
Removed unnecessary completer
NazarenoCavazzon Mar 3, 2023
0105de8
removed addPostFrameCallback from docs
NazarenoCavazzon Mar 3, 2023
4a6352c
Moved implementation to ImperativeRouteMatch
NazarenoCavazzon Mar 3, 2023
ecee639
Documented complete() method
NazarenoCavazzon Mar 3, 2023
98e1216
Changes
NazarenoCavazzon Mar 3, 2023
1b5e37b
Update delegate.dart
NazarenoCavazzon Mar 3, 2023
b734714
Update go_router_test.dart
NazarenoCavazzon Mar 3, 2023
ba99cc5
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 3, 2023
9b556a3
Last fixes
NazarenoCavazzon Mar 3, 2023
8d34c15
Update match.dart
NazarenoCavazzon Mar 3, 2023
0f0eafc
Update packages/go_router/CHANGELOG.md
NazarenoCavazzon Mar 4, 2023
77f6ab9
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 6, 2023
251966a
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 9, 2023
ed87847
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 20, 2023
1661569
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 23, 2023
c3ed204
Update version to 6.5.0
NazarenoCavazzon Mar 23, 2023
02a4f5c
Updated from main
NazarenoCavazzon Mar 23, 2023
a44a5cc
Merge branch 'main' into feat/return-value-when-pop
NazarenoCavazzon Mar 23, 2023
801c7c6
Type annotations
NazarenoCavazzon Mar 23, 2023
5d88336
Update router.dart
NazarenoCavazzon Mar 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
- Updates compileSdkVersion to 33.
- Updates example app to iOS 11.

## 6.3.0

- Support for returning values on pop.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Support for returning values on pop.
- Supports for returning values on pop.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please move the item under ## NEXT to be under 6.3.0 as well


## 6.2.0

- Export supertypes in route_data.dart library
Expand Down
19 changes: 19 additions & 0 deletions packages/go_router/doc/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,23 @@ Navigator.of(context).push(
);
```

## Returning values
Waiting for a value to be returned:

```dart
onTap: () {
final bool? result = await context.push<bool>('/page2');
WidgetsBinding.instance.addPostFrameCallback((_) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a post frame callback?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was before context.mounted was implemented, and using context after the value was returned lead to some dirty context problems, but we can take it out

if(result ?? false)...
});
}
```

Returning a value:

```dart
onTap: () => context.pop(true)
```


[Named routes]: https://pub.dev/documentation/go_router/latest/topics/Named%20routes-topic.html
1 change: 1 addition & 0 deletions packages/go_router/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies:
go_router:
path: ..
logging: ^1.0.0
package_info_plus_web: ^2.0.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be removed?

provider: ^6.0.0
shared_preferences: ^2.0.11
url_launcher: ^6.0.7
Expand Down
7 changes: 6 additions & 1 deletion packages/go_router/lib/src/delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
}

/// Pushes the given location onto the page stack
void push(RouteMatchList matches) {
Future<T?> push<T extends Object?>(RouteMatchList matches) async {
assert(matches.last.route is! ShellRoute);
final Completer<T?> completer = Completer<T?>();

// Remap the pageKey to allow any number of the same page on the stack
final int count = (_pushCounts[matches.fullpath] ?? 0) + 1;
Expand All @@ -91,10 +92,12 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
error: matches.last.error,
pageKey: pageKey,
matches: matches,
completer: completer,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not let ImperativeRouteMatch to create the completer itself.

);

_matchList.push(newPageKeyMatch);
notifyListeners();
return completer.future;
}

/// Returns `true` if the active Navigator can pop.
Expand All @@ -113,6 +116,7 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
final _NavigatorStateIterator iterator = _createNavigatorStateIterator();
while (iterator.moveNext()) {
if (iterator.current.canPop()) {
iterator.matchList.last.completer?.complete(result);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of exposing the completer directly, can you add a method in RouteMatch something like didComplete()? and let ImperativeRouteMatch to override the method to call complete on the completer

iterator.current.pop<T>(result);
return;
}
Expand Down Expand Up @@ -278,6 +282,7 @@ class ImperativeRouteMatch extends RouteMatch {
required super.error,
required super.pageKey,
required this.matches,
super.completer,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhere in the doc should mention about the completer and future and what it meant.

also, please remove the todo for me. Thanks in advance

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

});

/// The matches that produces this route match.
Expand Down
9 changes: 9 additions & 0 deletions packages/go_router/lib/src/match.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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/foundation.dart';
import 'package:flutter/widgets.dart';

Expand All @@ -18,6 +20,7 @@ class RouteMatch {
required this.extra,
required this.error,
required this.pageKey,
this.completer,
});

// ignore: public_member_api_docs
Expand All @@ -27,6 +30,7 @@ class RouteMatch {
required String parentSubloc, // e.g. /family/f2
required Map<String, String> pathParameters,
required Object? extra,
Completer<dynamic>? completer,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use method this property should be in ImerativeRouteMatch, and instead of dynamic, it should use generic type T

}) {
if (route is ShellRoute) {
return RouteMatch(
Expand All @@ -35,6 +39,7 @@ class RouteMatch {
extra: extra,
error: null,
pageKey: ValueKey<String>(route.hashCode.toString()),
completer: completer,
);
} else if (route is GoRoute) {
assert(!route.path.contains('//'));
Expand All @@ -56,6 +61,7 @@ class RouteMatch {
extra: extra,
error: null,
pageKey: ValueKey<String>(route.hashCode.toString()),
completer: completer,
);
}
throw MatcherError('Unexpected route type: $route', restLoc);
Expand All @@ -75,4 +81,7 @@ class RouteMatch {

/// Value key of type string, to hold a unique reference to a page.
final ValueKey<String> pageKey;

/// The completer for the promise returned by [GoRouter.push].
final Completer<dynamic>? completer;
}
6 changes: 3 additions & 3 deletions packages/go_router/lib/src/misc/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ extension GoRouterHelper on BuildContext {
);

/// Push a location onto the page stack.
void push(String location, {Object? extra}) =>
Future<T?> push<T extends Object?>(String location, {Object? extra}) =>
GoRouter.of(this).push(location, extra: extra);

/// Navigate to a named route onto the page stack.
void pushNamed(
Future<T?> pushNamed<T extends Object?>(
String name, {
Map<String, String> params = const <String, String>{},
Map<String, dynamic> queryParams = const <String, dynamic>{},
Object? extra,
}) =>
GoRouter.of(this).pushNamed(
GoRouter.of(this).pushNamed<T>(
name,
params: params,
queryParams: queryParams,
Expand Down
16 changes: 7 additions & 9 deletions packages/go_router/lib/src/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -204,32 +204,30 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {

/// Push a URI location onto the page stack w/ optional query parameters, e.g.
/// `/family/f2/person/p1?color=blue`
void push(String location, {Object? extra}) {
Future<T?> push<T extends Object?>(String location, {Object? extra}) async {
assert(() {
log.info('pushing $location');
return true;
}());
_routeInformationParser
.parseRouteInformationWithDependencies(
final RouteMatchList matches =
await _routeInformationParser.parseRouteInformationWithDependencies(
RouteInformation(location: location, state: extra),
// TODO(chunhtai): avoid accessing the context directly through global key.
// https://github.com/flutter/flutter/issues/99112
_routerDelegate.navigatorKey.currentContext!,
)
.then<void>((RouteMatchList matches) {
_routerDelegate.push(matches);
});
);
return _routerDelegate.push<T>(matches);
}

/// Push a named route onto the page stack w/ optional parameters, e.g.
/// `name='person', params={'fid': 'f2', 'pid': 'p1'}`
void pushNamed(
Future<T?> pushNamed<T extends Object?>(
String name, {
Map<String, String> params = const <String, String>{},
Map<String, dynamic> queryParams = const <String, dynamic>{},
Object? extra,
}) =>
push(
push<T>(
namedLocation(name, params: params, queryParams: queryParams),
extra: extra,
);
Expand Down
2 changes: 1 addition & 1 deletion packages/go_router/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: go_router
description: A declarative router for Flutter based on Navigation 2 supporting
deep linking, data-driven routes and more
version: 6.2.0
version: 6.3.0
repository: https://github.com/flutter/packages/tree/main/packages/go_router
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22

Expand Down
44 changes: 44 additions & 0 deletions packages/go_router/test/go_router_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,26 @@ void main() {
expect(router.extra, extra);
});

testWidgets('calls [push] on closest GoRouter with a promise',
(WidgetTester tester) async {
final GoRouterPushSpy router = GoRouterPushSpy(routes: routes);
await tester.pumpWidget(
MaterialApp.router(
routeInformationProvider: router.routeInformationProvider,
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
title: 'GoRouter Example',
),
);
final String? result = await router.push<String>(
location,
extra: extra,
);
expect(result, extra);
expect(router.myLocation, location);
expect(router.extra, extra);
});

testWidgets('calls [pushNamed] on closest GoRouter',
(WidgetTester tester) async {
final GoRouterPushNamedSpy router = GoRouterPushNamedSpy(routes: routes);
Expand All @@ -2676,6 +2696,30 @@ void main() {
expect(router.extra, extra);
});

testWidgets('calls [pushNamed] on closest GoRouter with a promise',
(WidgetTester tester) async {
final GoRouterPushNamedSpy router = GoRouterPushNamedSpy(routes: routes);
await tester.pumpWidget(
MaterialApp.router(
routeInformationProvider: router.routeInformationProvider,
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
title: 'GoRouter Example',
),
);
final String? result = await router.pushNamed<String>(
name,
params: params,
queryParams: queryParams,
extra: extra,
);
expect(result, extra);
expect(router.extra, extra);
expect(router.name, name);
expect(router.params, params);
expect(router.queryParams, queryParams);
});

testWidgets('calls [pop] on closest GoRouter', (WidgetTester tester) async {
final GoRouterPopSpy router = GoRouterPopSpy(routes: routes);
await tester.pumpWidget(
Expand Down
3 changes: 2 additions & 1 deletion packages/go_router/test/inherited_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ class MockGoRouter extends GoRouter {
late String latestPushedName;

@override
void pushNamed(String name,
Future<T?> pushNamed<T extends Object?>(String name,
{Map<String, String> params = const <String, String>{},
Map<String, dynamic> queryParams = const <String, dynamic>{},
Object? extra}) {
latestPushedName = name;
return Future<T?>.value();
}

@override
Expand Down
6 changes: 4 additions & 2 deletions packages/go_router/test/test_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,10 @@ class GoRouterPushSpy extends GoRouter {
Object? extra;

@override
void push(String location, {Object? extra}) {
Future<T?> push<T extends Object?>(String location, {Object? extra}) {
myLocation = location;
this.extra = extra;
return Future<T?>.value(extra as T?);
}
}

Expand All @@ -110,7 +111,7 @@ class GoRouterPushNamedSpy extends GoRouter {
Object? extra;

@override
void pushNamed(
Future<T?> pushNamed<T extends Object?>(
String name, {
Map<String, String> params = const <String, String>{},
Map<String, dynamic> queryParams = const <String, dynamic>{},
Expand All @@ -120,6 +121,7 @@ class GoRouterPushNamedSpy extends GoRouter {
this.params = params;
this.queryParams = queryParams;
this.extra = extra;
return Future<T?>.value(extra as T?);
}
}

Expand Down