Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
chunhtai committed Dec 6, 2023
1 parent 723b388 commit 77e95ca
Show file tree
Hide file tree
Showing 11 changed files with 478 additions and 662 deletions.
601 changes: 209 additions & 392 deletions packages/go_router/lib/src/builder.dart

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/go_router/lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ class RouteConfiguration {
if (match is RouteMatch) {
routeMatches.add(match);
}
return true;
});

final FutureOr<String?> routeLevelRedirectResult =
Expand Down
135 changes: 42 additions & 93 deletions packages/go_router/lib/src/delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,27 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>

final RouteConfiguration _configuration;

_NavigatorStateIterator _createNavigatorStateIterator() =>
_NavigatorStateIterator(currentConfiguration, navigatorKey.currentState!);

@override
Future<bool> popRoute() async {
final _NavigatorStateIterator iterator = _createNavigatorStateIterator();
while (iterator.moveNext()) {
final bool didPop = await iterator.current.maybePop();
if (didPop) {
return true;
NavigatorState? state = navigatorKey.currentState;
if (state == null) {
return false;
}
if (!state.canPop()) {
state = null;
}
RouteMatchBase walker = currentConfiguration.matches.last;
while (walker is ShellRouteMatch) {
if (walker.navigatorKey.currentState?.canPop() ?? false) {
state = walker.navigatorKey.currentState;
}
walker = walker.matches.last;
}
if (state != null) {
return state.maybePop();
}
// This should be the only place where the last GoRoute exit the screen.
final GoRoute lastRoute =
currentConfiguration.matches.last.route as GoRoute;
final GoRoute lastRoute = currentConfiguration.last.route;
if (lastRoute.onExit != null && navigatorKey.currentContext != null) {
return !(await lastRoute.onExit!(navigatorKey.currentContext!));
}
Expand All @@ -73,25 +79,36 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>

/// Returns `true` if the active Navigator can pop.
bool canPop() {
final _NavigatorStateIterator iterator = _createNavigatorStateIterator();
while (iterator.moveNext()) {
if (iterator.current.canPop()) {
if (navigatorKey.currentState?.canPop() ?? false) {
return true;
}
RouteMatchBase walker = currentConfiguration.matches.last;
while (walker is ShellRouteMatch) {
if (walker.navigatorKey.currentState?.canPop() ?? false) {
return true;
}
walker = walker.matches.last;
}
return false;
}

/// Pops the top-most route.
void pop<T extends Object?>([T? result]) {
final _NavigatorStateIterator iterator = _createNavigatorStateIterator();
while (iterator.moveNext()) {
if (iterator.current.canPop()) {
iterator.current.pop<T>(result);
return;
NavigatorState? state;
if (navigatorKey.currentState?.canPop() ?? false) {
state = navigatorKey.currentState;
}
RouteMatchBase walker = currentConfiguration.matches.last;
while (walker is ShellRouteMatch) {
if (walker.navigatorKey.currentState?.canPop() ?? false) {
state = walker.navigatorKey.currentState;
}
walker = walker.matches.last;
}
throw GoError('There is nothing to pop');
if (state == null) {
throw GoError('There is nothing to pop');
}
state.pop(result);
}

void _debugAssertMatchListNotEmpty() {
Expand All @@ -103,14 +120,13 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
}

bool _handlePopPageWithRouteMatch(
Route<Object?> route, Object? result, RouteMatch? match) {
Route<Object?> route, Object? result, RouteMatchBase match) {
if (route.willHandlePopInternally) {
final bool popped = route.didPop(result);
assert(!popped);
return popped;
}
assert(match != null);
final RouteBase routeBase = match!.route;
final RouteBase routeBase = match.route;
if (routeBase is! GoRoute || routeBase.onExit == null) {
route.didPop(result);
_completeRouteMatch(result, match);
Expand All @@ -130,7 +146,7 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
return false;
}

void _completeRouteMatch(Object? result, RouteMatch match) {
void _completeRouteMatch(Object? result, RouteMatchBase match) {
if (match is ImperativeRouteMatch) {
match.complete(result);
}
Expand Down Expand Up @@ -178,12 +194,14 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
if (match is RouteMatch) {
currentGoRouteMatches.add(match);
}
return true;
});
final List<RouteMatch> newGoRouteMatches = <RouteMatch>[];
configuration.visitRouteMatches((RouteMatchBase match) {
if (match is RouteMatch) {
newGoRouteMatches.add(match);
}
return true;
});

final int compareUntil = math.min(
Expand Down Expand Up @@ -250,77 +268,8 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>

Future<void> _setCurrentConfiguration(RouteMatchList configuration) {
currentConfiguration = configuration;
print('configuration set to:\n$configuration');
notifyListeners();
return SynchronousFuture<void>(null);
}
}

/// An iterator that iterates through navigators that [GoRouterDelegate]
/// created from the inner to outer.
///
/// The iterator starts with the navigator that hosts the top-most route. This
/// navigator may not be the inner-most navigator if the top-most route is a
/// pageless route, such as a dialog or bottom sheet.
class _NavigatorStateIterator implements Iterator<NavigatorState> {
_NavigatorStateIterator(this.matchList, this.root)
: index = matchList.matches.length - 1;

final RouteMatchList matchList;
int index;

final NavigatorState root;
@override
late NavigatorState current;

RouteBase _getRouteAtIndex(int index) => matchList.matches[index].route;

void _findsNextIndex() {
final GlobalKey<NavigatorState>? parentNavigatorKey =
_getRouteAtIndex(index).parentNavigatorKey;
if (parentNavigatorKey == null) {
index -= 1;
return;
}

for (index -= 1; index >= 0; index -= 1) {
final RouteBase route = _getRouteAtIndex(index);
if (route is ShellRouteBase) {
if (route.navigatorKeyForSubRoute(_getRouteAtIndex(index + 1)) ==
parentNavigatorKey) {
return;
}
}
}
assert(root == parentNavigatorKey.currentState);
}

@override
bool moveNext() {
if (index < 0) {
return false;
}
_findsNextIndex();

while (index >= 0) {
final RouteBase route = _getRouteAtIndex(index);
if (route is ShellRouteBase) {
final GlobalKey<NavigatorState> navigatorKey =
route.navigatorKeyForSubRoute(_getRouteAtIndex(index + 1));
// Must have a ModalRoute parent because the navigator ShellRoute
// created must not be the root navigator.
final ModalRoute<Object?> parentModalRoute =
ModalRoute.of(navigatorKey.currentContext!)!;
// There may be pageless route on top of ModalRoute that the
// parentNavigatorKey is in. For example an open dialog.
if (parentModalRoute.isCurrent) {
current = navigatorKey.currentState!;
return true;
}
}
_findsNextIndex();
}
assert(index == -1);
current = root;
return true;
}
}
Loading

0 comments on commit 77e95ca

Please sign in to comment.