Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
6be9a5d
[go_router] Added top level onEnter callback.
omar-hanafy Dec 22, 2024
171b639
added version 14.7.0
omar-hanafy Dec 22, 2024
f52a269
Merge branch 'main' into main
omar-hanafy Dec 25, 2024
3bbd241
Merge branch 'main' into main
omar-hanafy Dec 27, 2024
6a60006
Merge branch 'main' into main
omar-hanafy Jan 3, 2025
d1e1fc2
[go_router] added nextState, and currentState to OnEnter signature, a…
omar-hanafy Jan 24, 2025
516db13
Merge branch 'main' into main
omar-hanafy Jan 24, 2025
e1f10b1
Merge branch 'main' into main
omar-hanafy Jan 26, 2025
7a847b8
Merge branch 'main' into main
omar-hanafy Jan 28, 2025
b08d804
Merge branch 'main' into main
omar-hanafy Feb 2, 2025
1e25466
Merge branch 'main' into main
omar-hanafy Feb 4, 2025
aec8e47
Add router instance to OnEnter callback
omar-hanafy Feb 4, 2025
2bdc147
Merge branch 'main' into main
omar-hanafy Feb 8, 2025
1bd3c18
[go_router] Async onEnter, improved redirection, and loop prevention.
omar-hanafy Feb 15, 2025
61729b2
Merge branch 'main' into main
omar-hanafy Feb 15, 2025
8334a64
Merge branch 'main' into main
omar-hanafy Feb 17, 2025
f28337e
improved redirection and async handling.
omar-hanafy Feb 18, 2025
4092405
extracting the onEnter logic into its own helper class.
omar-hanafy Feb 18, 2025
c1c09d0
added named params to handleTopOnEnter.
omar-hanafy Feb 18, 2025
d9e6ea6
move tests
cedvdb Feb 20, 2025
07c15f0
Merge pull request #3 from cedvdb/move_tests
omar-hanafy Feb 22, 2025
3fbe011
Merge branch 'main' into main
omar-hanafy Mar 28, 2025
67df52a
added tests
cedvdb Apr 6, 2025
eef39b1
Merge pull request #4 from cedvdb/omar-add-on-enter-tests
omar-hanafy Apr 7, 2025
359eb0e
Merge branch 'flutter:main' into main
omar-hanafy Apr 7, 2025
cc57519
[go_router] Fix onEnter callback exception handling and enhance tests
omar-hanafy Apr 8, 2025
d4f2416
[go_router] updated Should allow redirection with query parameters te…
omar-hanafy Apr 9, 2025
56f2dbe
Merge branch 'main' into main
omar-hanafy Apr 16, 2025
c458982
Merge branch 'main' into main
omar-hanafy Apr 28, 2025
921dcb3
Merge branch 'main' into main
omar-hanafy May 30, 2025
757f5a1
[go_router] Use specific imports in on_enter.dart
omar-hanafy May 30, 2025
b5e1e9e
Merge branch 'main' of https://github.com/omar-hanafy/packages
omar-hanafy May 30, 2025
86c506b
Merge branch 'main' into main
omar-hanafy Jun 10, 2025
3c4a85f
Merge branch 'main' into main
omar-hanafy Jun 11, 2025
9d52c0d
Merge branch 'main' into main
omar-hanafy Jun 18, 2025
97c5ed8
Merge branch 'main' into main
omar-hanafy Jun 24, 2025
0323a45
Merge branch 'main' into main
omar-hanafy Jul 9, 2025
4a9e6ff
[go_router] Replace boolean return with sealed class API for onEnter
omar-hanafy Jul 9, 2025
3b2df49
[go_router] Make OnEnterHandler private and ensure onEnter priority o…
omar-hanafy Aug 2, 2025
1dd95d8
Merge branch 'main' into main
omar-hanafy Aug 2, 2025
ade3f54
Merge branch 'main' into main
omar-hanafy Aug 19, 2025
ed43b0b
Merge branch 'main' into main
omar-hanafy Aug 19, 2025
d0d5e6d
[go_router] added allow/block factories for the OnEnterResult
omar-hanafy Aug 19, 2025
a484965
[go_router] ran dart format
omar-hanafy Aug 19, 2025
10404f8
[go_router] returned back missing docs in GoRouterRedirect
omar-hanafy Aug 19, 2025
2b3d0be
[go_router] Fix license headers to match repository standards
omar-hanafy Aug 19, 2025
b554e6c
[go_router] sealed `onEnter` (Allow/Block.then) + compose legacy redi…
omar-hanafy Aug 20, 2025
99ab3c3
[go_router] Fix license headers to match repository standards
omar-hanafy Aug 20, 2025
265f26f
[go_router] Refactor parser and on_enter for clarity and type safety
omar-hanafy Aug 22, 2025
01f7ea6
[go_router] Remove unused initialLocation parameter from parser.
omar-hanafy Aug 22, 2025
22a29bd
[go_router] Ensure onEnter runs during state restoration, and unified…
omar-hanafy Aug 27, 2025
887c528
Merge branch 'main' into main
omar-hanafy Aug 28, 2025
37712e5
Merge branch 'main' into main
omar-hanafy Aug 30, 2025
ee55004
Merge branch 'main' into main
omar-hanafy Sep 21, 2025
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
5 changes: 3 additions & 2 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT
## 14.7.0

* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
- Updated the minimum supported SDK version to Flutter 3.22/Dart 3.4.
- Added new top level `onEnter` callback for controlling incoming route navigation.

## 14.6.2

Expand Down
154 changes: 154 additions & 0 deletions packages/go_router/example/lib/top_level_on_enter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Copyright 2013 The Flutter Authors.
// 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:go_router/go_router.dart';

void main() => runApp(const App());

/// The main application widget.
class App extends StatelessWidget {
/// Constructs an [App].
const App({super.key});

/// The title of the app.
static const String title = 'GoRouter Example: Top-level onEnter';

@override
Widget build(BuildContext context) => MaterialApp.router(
routerConfig: GoRouter(
initialLocation: '/home',

/// A callback invoked for every route navigation attempt.
///
/// If the callback returns `false`, the navigation is blocked.
/// Use this to handle authentication, referrals, or other route-based logic.
onEnter: (BuildContext context, GoRouterState state) {
// Save the referral code (if provided) and block navigation to the /referral route.
if (state.uri.path == '/referral') {
saveReferralCode(context, state.uri.queryParameters['code']);
return false;
}

return true; // Allow navigation for all other routes.
},

/// The list of application routes.
routes: <GoRoute>[
GoRoute(
path: '/login',
builder: (BuildContext context, GoRouterState state) =>
const LoginScreen(),
),
GoRoute(
path: '/home',
builder: (BuildContext context, GoRouterState state) =>
const HomeScreen(),
),
GoRoute(
path: '/settings',
builder: (BuildContext context, GoRouterState state) =>
const SettingsScreen(),
),
],
),
title: title,
);
}

/// The login screen widget.
class LoginScreen extends StatelessWidget {
/// Constructs a [LoginScreen].
const LoginScreen({super.key});

@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text(App.title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => context.go('/home'),
child: const Text('Go to Home'),
),
ElevatedButton(
onPressed: () => context.go('/settings'),
child: const Text('Go to Settings'),
),
],
),
),
);
}

/// The home screen widget.
class HomeScreen extends StatelessWidget {
/// Constructs a [HomeScreen].
const HomeScreen({super.key});

@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text(App.title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => context.go('/login'),
child: const Text('Go to Login'),
),
ElevatedButton(
onPressed: () => context.go('/settings'),
child: const Text('Go to Settings'),
),
ElevatedButton(
// This would typically be triggered by an incoming deep link.
onPressed: () => context.go('/referral?code=12345'),
child: const Text('Save Referral Code'),
),
],
),
),
);
}

/// The settings screen widget.
class SettingsScreen extends StatelessWidget {
/// Constructs a [SettingsScreen].
const SettingsScreen({super.key});

@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text(App.title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => context.go('/login'),
child: const Text('Go to Login'),
),
ElevatedButton(
onPressed: () => context.go('/home'),
child: const Text('Go to Home'),
),
],
),
),
);
}

/// Saves a referral code.
///
/// Displays a [SnackBar] with the referral code for demonstration purposes.
/// Replace this with real referral handling logic.
void saveReferralCode(BuildContext context, String? code) {
if (code != null) {
// Here you can implement logic to save the referral code as needed.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Referral code saved: $code')),
);
}
}
33 changes: 33 additions & 0 deletions packages/go_router/lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@ import 'state.dart';
typedef GoRouterRedirect = FutureOr<String?> Function(
BuildContext context, GoRouterState state);

/// The signature of the onEnter callback.
typedef OnEnter = bool Function(BuildContext context, GoRouterState state);

/// The route configuration for GoRouter configured by the app.
class RouteConfiguration {
/// Constructs a [RouteConfiguration].
RouteConfiguration(
this._routingConfig, {
required this.navigatorKey,
this.extraCodec,
this.onEnter,
}) {
_onRoutingTableChanged();
_routingConfig.addListener(_onRoutingTableChanged);
Expand Down Expand Up @@ -246,6 +250,35 @@ class RouteConfiguration {
/// example.
final Codec<Object?, Object?>? extraCodec;

/// A callback invoked for every incoming route before it is processed.
///
/// This callback allows you to control navigation by inspecting the incoming
/// route and conditionally preventing the navigation. If the callback returns
/// `true`, the GoRouter proceeds with the regular navigation and redirection
/// logic. If the callback returns `false`, the navigation is canceled.
///
/// When a deep link opens the app and `onEnter` returns `false`, GoRouter
/// will automatically redirect to the initial route or '/'.
///
/// Example:
/// ```dart
/// final GoRouter router = GoRouter(
/// routes: [...],
/// onEnter: (BuildContext context, Uri uri) {
/// if (uri.path == '/login' && isUserLoggedIn()) {
/// return false; // Prevent navigation to /login
/// }
/// if (uri.path == '/referral') {
/// // Save the referral code and prevent navigation
/// saveReferralCode(uri.queryParameters['code']);
/// return false;
/// }
/// return true; // Allow navigation
/// },
/// );
/// ```
final OnEnter? onEnter;

final Map<String, String> _nameToPath = <String, String>{};

/// Looks up the url location by a [GoRoute]'s name.
Expand Down
Loading
Loading