-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[go_router] Support for top level onEnter callback.
#8339
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
61 commits
Select commit
Hold shift + click to select a range
6be9a5d
[go_router] Added top level onEnter callback.
omar-hanafy 171b639
added version 14.7.0
omar-hanafy f52a269
Merge branch 'main' into main
omar-hanafy 3bbd241
Merge branch 'main' into main
omar-hanafy 6a60006
Merge branch 'main' into main
omar-hanafy d1e1fc2
[go_router] added nextState, and currentState to OnEnter signature, a…
omar-hanafy 516db13
Merge branch 'main' into main
omar-hanafy e1f10b1
Merge branch 'main' into main
omar-hanafy 7a847b8
Merge branch 'main' into main
omar-hanafy b08d804
Merge branch 'main' into main
omar-hanafy 1e25466
Merge branch 'main' into main
omar-hanafy aec8e47
Add router instance to OnEnter callback
omar-hanafy 2bdc147
Merge branch 'main' into main
omar-hanafy 1bd3c18
[go_router] Async onEnter, improved redirection, and loop prevention.
omar-hanafy 61729b2
Merge branch 'main' into main
omar-hanafy 8334a64
Merge branch 'main' into main
omar-hanafy f28337e
improved redirection and async handling.
omar-hanafy 4092405
extracting the onEnter logic into its own helper class.
omar-hanafy c1c09d0
added named params to handleTopOnEnter.
omar-hanafy d9e6ea6
move tests
cedvdb 07c15f0
Merge pull request #3 from cedvdb/move_tests
omar-hanafy 3fbe011
Merge branch 'main' into main
omar-hanafy 67df52a
added tests
cedvdb eef39b1
Merge pull request #4 from cedvdb/omar-add-on-enter-tests
omar-hanafy 359eb0e
Merge branch 'flutter:main' into main
omar-hanafy cc57519
[go_router] Fix onEnter callback exception handling and enhance tests
omar-hanafy d4f2416
[go_router] updated Should allow redirection with query parameters te…
omar-hanafy 56f2dbe
Merge branch 'main' into main
omar-hanafy c458982
Merge branch 'main' into main
omar-hanafy 921dcb3
Merge branch 'main' into main
omar-hanafy 757f5a1
[go_router] Use specific imports in on_enter.dart
omar-hanafy b5e1e9e
Merge branch 'main' of https://github.com/omar-hanafy/packages
omar-hanafy 86c506b
Merge branch 'main' into main
omar-hanafy 3c4a85f
Merge branch 'main' into main
omar-hanafy 9d52c0d
Merge branch 'main' into main
omar-hanafy 97c5ed8
Merge branch 'main' into main
omar-hanafy 0323a45
Merge branch 'main' into main
omar-hanafy 4a9e6ff
[go_router] Replace boolean return with sealed class API for onEnter
omar-hanafy 3b2df49
[go_router] Make OnEnterHandler private and ensure onEnter priority o…
omar-hanafy 1dd95d8
Merge branch 'main' into main
omar-hanafy ade3f54
Merge branch 'main' into main
omar-hanafy ed43b0b
Merge branch 'main' into main
omar-hanafy d0d5e6d
[go_router] added allow/block factories for the OnEnterResult
omar-hanafy a484965
[go_router] ran dart format
omar-hanafy 10404f8
[go_router] returned back missing docs in GoRouterRedirect
omar-hanafy 2b3d0be
[go_router] Fix license headers to match repository standards
omar-hanafy b554e6c
[go_router] sealed `onEnter` (Allow/Block.then) + compose legacy redi…
omar-hanafy 99ab3c3
[go_router] Fix license headers to match repository standards
omar-hanafy 265f26f
[go_router] Refactor parser and on_enter for clarity and type safety
omar-hanafy 01f7ea6
[go_router] Remove unused initialLocation parameter from parser.
omar-hanafy 22a29bd
[go_router] Ensure onEnter runs during state restoration, and unified…
omar-hanafy 887c528
Merge branch 'main' into main
omar-hanafy 37712e5
Merge branch 'main' into main
omar-hanafy ee55004
Merge branch 'main' into main
omar-hanafy 9e37af9
[go_router] polish onEnter handling and docs
omar-hanafy faa9d81
Merge branch 'main' into main
omar-hanafy 20c4148
[go_router] Refine onEnter documentation and API adjustments
omar-hanafy 2b4c348
[go_router] Improve context safety and docs in navigation logic
omar-hanafy d1bc684
[go_router] Improve documentation for legacy redirect method
omar-hanafy 54afc72
Merge branch 'main' into main
omar-hanafy 33996c6
Merge remote-tracking branch 'upstream/main'
omar-hanafy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
extracting the onEnter logic into its own helper class.
- Loading branch information
commit 4092405d39c023dfd378d7b4fd1798238b5dba7a
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| // on_enter.dart | ||
| // ignore_for_file: use_build_context_synchronously | ||
| // 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 'dart:async'; | ||
|
|
||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:flutter/widgets.dart'; | ||
|
|
||
| import '../go_router.dart'; | ||
|
|
||
| /// Handles the `onEnter` callback logic and redirection history for GoRouter. | ||
| /// | ||
| /// This class encapsulates the logic to execute the top-level `onEnter` | ||
| /// callback, track redirection history, enforce the redirection limit, | ||
| /// and generate an error match list when the limit is exceeded. | ||
| class OnEnterHandler { | ||
| /// Creates an [OnEnterHandler] instance. | ||
| /// | ||
| /// [configuration] is the route configuration. | ||
| /// [router] is used to access GoRouter methods. | ||
| /// [onParserException] is the exception handler for the parser. | ||
| OnEnterHandler({ | ||
| required RouteConfiguration configuration, | ||
| required GoRouter router, | ||
| required ParserExceptionHandler? onParserException, | ||
| }) : _onParserException = onParserException, | ||
| _configuration = configuration, | ||
| _router = router; | ||
|
|
||
| /// The route configuration for the current router. | ||
| /// | ||
| /// This object contains all the route definitions, redirection logic, and other | ||
| /// navigation settings. It is used to determine which routes match the incoming | ||
| /// URI and to build the corresponding navigation state. | ||
| final RouteConfiguration _configuration; | ||
|
|
||
| /// Optional exception handler for route parsing errors. | ||
| /// | ||
| /// When an error occurs during route parsing (e.g., when the onEnter redirection | ||
| /// limit is exceeded), this handler is invoked with the current [BuildContext] | ||
| /// and a [RouteMatchList] that contains the error details. It must conform to the | ||
| /// [ParserExceptionHandler] typedef and is responsible for returning a fallback | ||
| /// [RouteMatchList]. | ||
| final ParserExceptionHandler? _onParserException; | ||
|
|
||
| /// The [GoRouter] instance used to perform navigation actions. | ||
| /// | ||
| /// This instance provides access to various navigation methods and serves as a | ||
| /// fallback when the [BuildContext] does not have an inherited GoRouter. It is | ||
| /// essential for executing onEnter callbacks and handling redirections. | ||
| final GoRouter _router; | ||
|
|
||
| /// A history of URIs encountered during onEnter redirections. | ||
| /// | ||
| /// This list tracks each URI that triggers an onEnter redirection and is used to | ||
| /// enforce the redirection limit defined in [RouteConfiguration.redirectLimit]. It | ||
| /// helps prevent infinite redirection loops by generating an error if the limit is exceeded. | ||
| final List<Uri> _redirectionHistory = <Uri>[]; | ||
|
|
||
| /// Executes the top-level `onEnter` callback and decides whether navigation | ||
| /// should proceed. | ||
| /// | ||
| /// This method first checks for redirection errors via | ||
| /// [_redirectionErrorMatchList]. If no error is found, it builds the current | ||
| /// and next navigation states, executes the onEnter callback, and based on its | ||
| /// result returns either [onCanEnter] or [onCanNotEnter]. | ||
| /// | ||
| /// [context] is the BuildContext. | ||
| /// [routeInformation] is the current RouteInformation. | ||
| /// [infoState] is the state embedded in the RouteInformation. | ||
| /// [lastMatchList] is the last successful match list (if any). | ||
| /// [onCanEnter] is called when navigation is allowed. | ||
| /// [onCanNotEnter] is called when navigation is blocked. | ||
| /// | ||
| /// Returns a Future that resolves to a [RouteMatchList]. | ||
| Future<RouteMatchList> handleTopOnEnter( | ||
| BuildContext context, | ||
| RouteInformation routeInformation, | ||
| RouteInformationState<dynamic> infoState, | ||
| RouteMatchList? lastMatchList, | ||
| Future<RouteMatchList> Function() onCanEnter, | ||
| Future<RouteMatchList> Function() onCanNotEnter, | ||
| ) { | ||
| final OnEnter? topOnEnter = _configuration.topOnEnter; | ||
| // If no onEnter is configured, simply allow navigation. | ||
| if (topOnEnter == null) { | ||
| return onCanEnter(); | ||
| } | ||
|
|
||
| // Check if the redirection history already exceeds the configured limit. | ||
| final RouteMatchList? redirectionErrorMatchList = | ||
| _redirectionErrorMatchList(context, routeInformation.uri, infoState); | ||
|
|
||
| if (redirectionErrorMatchList != null) { | ||
| // Return immediately if the redirection limit is exceeded. | ||
| return SynchronousFuture<RouteMatchList>(redirectionErrorMatchList); | ||
| } | ||
|
|
||
| // Build route matches for the incoming URI. | ||
| final RouteMatchList incomingMatches = _configuration.findMatch( | ||
| routeInformation.uri, | ||
| extra: infoState.extra, | ||
| ); | ||
|
|
||
| // Build the next navigation state. | ||
| final GoRouterState nextState = | ||
| _configuration.buildTopLevelGoRouterState(incomingMatches); | ||
| // Use the last successful state if available. | ||
| final GoRouterState currentState = lastMatchList != null | ||
| ? _configuration.buildTopLevelGoRouterState(lastMatchList) | ||
| : nextState; | ||
|
|
||
| // Execute the onEnter callback and get a Future<bool> result. | ||
| final Future<bool> canEnterFuture = topOnEnter( | ||
| context, | ||
| currentState, | ||
| nextState, | ||
| _router, | ||
| ); | ||
| // Reset history after attempting the callback. | ||
| _resetRedirectionHistory(); | ||
| // Return the appropriate match list based on whether navigation is allowed. | ||
| return canEnterFuture.then( | ||
| (bool canEnter) => canEnter ? onCanEnter() : onCanNotEnter(), | ||
| ); | ||
| } | ||
|
|
||
| /// Processes the redirection history and checks for redirection limits. | ||
| /// | ||
| /// Adds [redirectedUri] to the redirection history. If the number of redirections | ||
| /// exceeds [_configuration.redirectLimit], returns an error match list. | ||
| /// Otherwise, returns null. | ||
| RouteMatchList? _redirectionErrorMatchList( | ||
| BuildContext context, | ||
| Uri redirectedUri, | ||
| RouteInformationState<dynamic> infoState, | ||
| ) { | ||
| _redirectionHistory.add(redirectedUri); | ||
| if (_redirectionHistory.length > _configuration.redirectLimit) { | ||
| final String formattedHistory = | ||
| _formatOnEnterRedirectionHistory(_redirectionHistory); | ||
| final RouteMatchList errorMatchList = _errorRouteMatchList( | ||
| redirectedUri, | ||
| GoException('Too many onEnter calls detected: $formattedHistory'), | ||
| extra: infoState.extra, | ||
| ); | ||
| _resetRedirectionHistory(); | ||
| // Use onParserException if available to process the error match list. | ||
| return _onParserException != null | ||
| ? _onParserException(context, errorMatchList) | ||
| : errorMatchList; | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| /// Resets the onEnter redirection history. | ||
| void _resetRedirectionHistory() { | ||
| _redirectionHistory.clear(); | ||
| } | ||
|
|
||
| /// Formats the redirection history as a string for error messages. | ||
| String _formatOnEnterRedirectionHistory(List<Uri> history) { | ||
| return history.map((Uri uri) => uri.toString()).join(' => '); | ||
| } | ||
|
|
||
| /// Creates an error match list for a given [uri] and [exception]. | ||
| static RouteMatchList _errorRouteMatchList( | ||
| Uri uri, | ||
| GoException exception, { | ||
| Object? extra, | ||
| }) { | ||
| return RouteMatchList( | ||
| matches: const <RouteMatch>[], | ||
| extra: extra, | ||
| error: exception, | ||
| uri: uri, | ||
| pathParameters: const <String, String>{}, | ||
| ); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.