Skip to content
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

go_router should allow setting requestFocus #4636

Merged
merged 17 commits into from
Aug 9, 2023
4 changes: 4 additions & 0 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 10.1.0

- Supports setting `requestFocus`.

## 10.0.0

- **BREAKING CHANGE**:
Expand Down
18 changes: 17 additions & 1 deletion packages/go_router/lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class RouteBuilder {
required this.restorationScopeId,
required this.observers,
required this.onPopPageWithRouteMatch,
this.requestFocus = true,
});

/// Builder function for a go router with Navigator.
Expand All @@ -63,6 +64,14 @@ class RouteBuilder {
/// its history.
final String? restorationScopeId;

/// Whether or not the navigator created by this builder and it's new topmost route should request focus
/// when the new route is pushed onto the navigator.
///
/// Defaults to true.
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe add a link to navigator.requestfocus

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

///
/// {@macro flutter.widgets.navigator.requestFocus}
hangyujin marked this conversation as resolved.
Show resolved Hide resolved
final bool requestFocus;

/// NavigatorObserver used to receive notifications when navigating in between routes.
/// changes.
final List<NavigatorObserver> observers;
Expand Down Expand Up @@ -137,6 +146,7 @@ class RouteBuilder {
navigatorKey,
observers: observers,
restorationScopeId: restorationScopeId,
requestFocus: requestFocus,
),
);
}
Expand Down Expand Up @@ -258,14 +268,18 @@ class RouteBuilder {

// Build the Navigator for this shell route
Widget buildShellNavigator(
List<NavigatorObserver>? observers, String? restorationScopeId) {
List<NavigatorObserver>? observers,
String? restorationScopeId, {
bool requestFocus = true,
}) {
return _buildNavigator(
pagePopContext.onPopPage,
keyToPages[shellNavigatorKey]!,
shellNavigatorKey,
observers: observers ?? const <NavigatorObserver>[],
restorationScopeId: restorationScopeId,
heroController: heroController,
requestFocus: requestFocus,
);
}

Expand Down Expand Up @@ -298,13 +312,15 @@ class RouteBuilder {
List<NavigatorObserver> observers = const <NavigatorObserver>[],
String? restorationScopeId,
HeroController? heroController,
bool requestFocus = true,
}) {
final Widget navigator = Navigator(
key: navigatorKey,
restorationScopeId: restorationScopeId,
pages: pages,
observers: observers,
onPopPage: onPopPage,
requestFocus: requestFocus,
);
if (heroController != null) {
return HeroControllerScope(
Expand Down
2 changes: 2 additions & 0 deletions packages/go_router/lib/src/delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
required List<NavigatorObserver> observers,
required this.routerNeglect,
String? restorationScopeId,
bool requestFocus = true,
}) : _configuration = configuration {
builder = RouteBuilder(
configuration: configuration,
Expand All @@ -35,6 +36,7 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
restorationScopeId: restorationScopeId,
observers: observers,
onPopPageWithRouteMatch: _handlePopPageWithRouteMatch,
requestFocus: requestFocus,
);
}

Expand Down
4 changes: 4 additions & 0 deletions packages/go_router/lib/src/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ typedef GoExceptionHandler = void Function(
/// See [Error handling](https://pub.dev/documentation/go_router/latest/topics/Error%20handling-topic.html)
/// for more details.
///
/// To disable automatically requesting focus when new routes are pushed to the navigator, set `requestFocus` to false.
///
/// See also:
/// * [Configuration](https://pub.dev/documentation/go_router/latest/topics/Configuration-topic.html)
/// * [GoRoute], which provides APIs to define the routing table.
Expand Down Expand Up @@ -83,6 +85,7 @@ class GoRouter implements RouterConfig<RouteMatchList> {
bool debugLogDiagnostics = false,
GlobalKey<NavigatorState>? navigatorKey,
String? restorationScopeId,
bool requestFocus = true,
}) : backButtonDispatcher = RootBackButtonDispatcher(),
assert(
initialExtra == null || initialLocation != null,
Expand Down Expand Up @@ -147,6 +150,7 @@ class GoRouter implements RouterConfig<RouteMatchList> {
...observers ?? <NavigatorObserver>[],
],
restorationScopeId: restorationScopeId,
requestFocus: requestFocus,
// wrap the returned Navigator to enable GoRouter.of(context).go() et al,
// allowing the caller to wrap the navigator themselves
builderWithNav: (BuildContext context, Widget child) =>
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: 10.0.0
version: 10.1.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
61 changes: 61 additions & 0 deletions packages/go_router/test/request_focus.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';

void main() {
testWidgets('GoRouter does not request focus if requestFocus is false',
(WidgetTester tester) async {
final GlobalKey innerKey = GlobalKey();
final FocusScopeNode focusNode = FocusScopeNode();
final GoRouter router = GoRouter(
initialLocation: '/',
routes: <GoRoute>[
GoRoute(
path: '/',
name: 'home',
builder: (_, __) => const Text('A'),
),
GoRoute(
path: '/second',
name: 'second',
builder: (_, __) => Text('B', key: innerKey),
),
],
requestFocus: false,
);

await tester.pumpWidget(Column(
children: <Widget>[
FocusScope(node: focusNode, child: Container()),
Expanded(
child: MaterialApp.router(
routerConfig: router,
),
),
],
));

expect(find.text('A'), findsOneWidget);
expect(find.text('B', skipOffstage: false), findsNothing);
expect(focusNode.hasFocus, false);
focusNode.requestFocus();
await tester.pumpAndSettle();
expect(focusNode.hasFocus, true);

router.pushNamed('second');
await tester.pumpAndSettle();
expect(find.text('A', skipOffstage: false), findsOneWidget);
expect(find.text('B'), findsOneWidget);
expect(focusNode.hasFocus, true);

router.pop();
await tester.pumpAndSettle();
expect(find.text('A'), findsOneWidget);
expect(find.text('B', skipOffstage: false), findsNothing);
expect(focusNode.hasFocus, true);
});
}
2 changes: 2 additions & 0 deletions packages/go_router/test/test_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Future<GoRouter> createRouter(
GoRouterWidgetBuilder? errorBuilder,
String? restorationScopeId,
GoExceptionHandler? onException,
bool requestFocus = true,
}) async {
final GoRouter goRouter = GoRouter(
routes: routes,
Expand All @@ -160,6 +161,7 @@ Future<GoRouter> createRouter(
errorBuilder: errorBuilder,
navigatorKey: navigatorKey,
restorationScopeId: restorationScopeId,
requestFocus: requestFocus,
);
await tester.pumpWidget(
MaterialApp.router(
Expand Down