Jonny Borges
Committed by GitHub

Merge pull request #1652 from Bdaya-Dev/fix-router-outlet

[Nav2] Improved router outlet and get delegate
@@ -5,18 +5,22 @@ import '../routes/app_pages.dart'; @@ -5,18 +5,22 @@ import '../routes/app_pages.dart';
5 5
6 class EnsureAuthMiddleware extends GetMiddleware { 6 class EnsureAuthMiddleware extends GetMiddleware {
7 @override 7 @override
8 - GetNavConfig? redirectDelegate(GetNavConfig route) { 8 + Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async {
  9 + // you can do whatever you want here
  10 + // but it's preferable to make this method fast
  11 + // await Future.delayed(Duration(milliseconds: 500));
  12 +
9 if (!AuthService.to.isLoggedInValue) { 13 if (!AuthService.to.isLoggedInValue) {
10 final newRoute = Routes.LOGIN_THEN(route.location!); 14 final newRoute = Routes.LOGIN_THEN(route.location!);
11 return GetNavConfig.fromRoute(newRoute); 15 return GetNavConfig.fromRoute(newRoute);
12 } 16 }
13 - return super.redirectDelegate(route); 17 + return await super.redirectDelegate(route);
14 } 18 }
15 } 19 }
16 20
17 class EnsureNotAuthedMiddleware extends GetMiddleware { 21 class EnsureNotAuthedMiddleware extends GetMiddleware {
18 @override 22 @override
19 - GetNavConfig? redirectDelegate(GetNavConfig route) { 23 + Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async {
20 if (AuthService.to.isLoggedInValue) { 24 if (AuthService.to.isLoggedInValue) {
21 //NEVER navigate to auth screen, when user is already authed 25 //NEVER navigate to auth screen, when user is already authed
22 return null; 26 return null;
@@ -24,6 +28,6 @@ class EnsureNotAuthedMiddleware extends GetMiddleware { @@ -24,6 +28,6 @@ class EnsureNotAuthedMiddleware extends GetMiddleware {
24 //OR redirect user to another screen 28 //OR redirect user to another screen
25 //return GetNavConfig.fromRoute(Routes.PROFILE); 29 //return GetNavConfig.fromRoute(Routes.PROFILE);
26 } 30 }
27 - return super.redirectDelegate(route); 31 + return await super.redirectDelegate(route);
28 } 32 }
29 } 33 }
@@ -21,6 +21,8 @@ class HomeView extends GetView<HomeController> { @@ -21,6 +21,8 @@ class HomeView extends GetView<HomeController> {
21 return Scaffold( 21 return Scaffold(
22 body: GetRouterOutlet( 22 body: GetRouterOutlet(
23 initialRoute: Routes.DASHBOARD, 23 initialRoute: Routes.DASHBOARD,
  24 + // anchorRoute: Routes.HOME,
  25 + key: Get.nestedKey(Routes.HOME),
24 ), 26 ),
25 bottomNavigationBar: BottomNavigationBar( 27 bottomNavigationBar: BottomNavigationBar(
26 currentIndex: currentIndex, 28 currentIndex: currentIndex,
1 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
2 2
3 -class ProfileController extends GetxController {  
4 - //TODO: Implement ProfileController  
5 -  
6 - final count = 0.obs;  
7 - @override  
8 - void onInit() {  
9 - super.onInit();  
10 - }  
11 -  
12 - @override  
13 - void onReady() {  
14 - super.onReady();  
15 - }  
16 -  
17 - @override  
18 - void onClose() {}  
19 - void increment() => count.value++;  
20 -} 3 +class ProfileController extends GetxController {}
@@ -19,6 +19,10 @@ class RootView extends GetView<RootController> { @@ -19,6 +19,10 @@ class RootView extends GetView<RootController> {
19 ), 19 ),
20 body: GetRouterOutlet( 20 body: GetRouterOutlet(
21 initialRoute: Routes.HOME, 21 initialRoute: Routes.HOME,
  22 + // anchorRoute: '/',
  23 + filterPages: (afterAnchor) {
  24 + return afterAnchor.take(1);
  25 + },
22 ), 26 ),
23 ); 27 );
24 }, 28 },
@@ -43,7 +43,6 @@ class AppPages { @@ -43,7 +43,6 @@ class AppPages {
43 binding: LoginBinding(), 43 binding: LoginBinding(),
44 ), 44 ),
45 GetPage( 45 GetPage(
46 - participatesInRootNavigator: false,  
47 preventDuplicates: true, 46 preventDuplicates: true,
48 name: _Paths.HOME, 47 name: _Paths.HOME,
49 page: () => HomeView(), 48 page: () => HomeView(),
@@ -52,56 +52,61 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -52,56 +52,61 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
52 final PopMode backButtonPopMode; 52 final PopMode backButtonPopMode;
53 final PreventDuplicateHandlingMode preventDuplicateHandlingMode; 53 final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
54 54
55 - GetPage? notFoundRoute; 55 + final GetPage notFoundRoute;
56 56
57 final List<NavigatorObserver>? navigatorObservers; 57 final List<NavigatorObserver>? navigatorObservers;
58 final TransitionDelegate<dynamic>? transitionDelegate; 58 final TransitionDelegate<dynamic>? transitionDelegate;
59 - final _resultCompleter = <GetNavConfig, Completer<Object?>>{};  
60 59
61 GlobalKey<NavigatorState> get navigatorKey => 60 GlobalKey<NavigatorState> get navigatorKey =>
62 GetNavigation.getxController.key; 61 GetNavigation.getxController.key;
63 62
64 GetDelegate({ 63 GetDelegate({
65 - this.notFoundRoute, 64 + GetPage? notFoundRoute,
66 this.navigatorObservers, 65 this.navigatorObservers,
67 this.transitionDelegate, 66 this.transitionDelegate,
68 this.backButtonPopMode = PopMode.History, 67 this.backButtonPopMode = PopMode.History,
69 this.preventDuplicateHandlingMode = 68 this.preventDuplicateHandlingMode =
70 PreventDuplicateHandlingMode.ReorderRoutes, 69 PreventDuplicateHandlingMode.ReorderRoutes,
71 - }) { 70 + }) : notFoundRoute = notFoundRoute ??
  71 + GetPage(
  72 + name: '/404',
  73 + page: () => Scaffold(
  74 + body: Text('Route not found'),
  75 + ),
  76 + ) {
72 Get.log('GetDelegate is created !'); 77 Get.log('GetDelegate is created !');
73 } 78 }
74 79
75 - GetNavConfig? runMiddleware(GetNavConfig config) { 80 + Future<GetNavConfig?> runMiddleware(GetNavConfig config) async {
76 final middlewares = config.currentTreeBranch.last.middlewares; 81 final middlewares = config.currentTreeBranch.last.middlewares;
77 if (middlewares == null) { 82 if (middlewares == null) {
78 return config; 83 return config;
79 } 84 }
80 var iterator = config; 85 var iterator = config;
81 for (var item in middlewares) { 86 for (var item in middlewares) {
82 - var redirectRes = item.redirectDelegate(iterator); 87 + var redirectRes = await item.redirectDelegate(iterator);
83 if (redirectRes == null) return null; 88 if (redirectRes == null) return null;
84 iterator = redirectRes; 89 iterator = redirectRes;
85 } 90 }
86 return iterator; 91 return iterator;
87 } 92 }
88 93
89 - void _unsafeHistoryAdd(GetNavConfig config) {  
90 - final res = runMiddleware(config); 94 + Future<void> _unsafeHistoryAdd(GetNavConfig config) async {
  95 + final res = await runMiddleware(config);
91 if (res == null) return; 96 if (res == null) return;
92 history.add(res); 97 history.add(res);
93 } 98 }
94 99
95 - void _unsafeHistoryRemove(GetNavConfig config) { 100 + Future<void> _unsafeHistoryRemove(GetNavConfig config) async {
96 var index = history.indexOf(config); 101 var index = history.indexOf(config);
97 - if (index >= 0) _unsafeHistoryRemoveAt(index); 102 + if (index >= 0) await _unsafeHistoryRemoveAt(index);
98 } 103 }
99 104
100 - GetNavConfig? _unsafeHistoryRemoveAt(int index) { 105 + Future<GetNavConfig?> _unsafeHistoryRemoveAt(int index) async {
101 if (index == history.length - 1 && history.length > 1) { 106 if (index == history.length - 1 && history.length > 1) {
102 //removing WILL update the current route 107 //removing WILL update the current route
103 final toCheck = history[history.length - 2]; 108 final toCheck = history[history.length - 2];
104 - final resMiddleware = runMiddleware(toCheck); 109 + final resMiddleware = await runMiddleware(toCheck);
105 if (resMiddleware == null) return null; 110 if (resMiddleware == null) return null;
106 history[history.length - 2] = resMiddleware; 111 history[history.length - 2] = resMiddleware;
107 } 112 }
@@ -121,38 +126,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -121,38 +126,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
121 // } 126 // }
122 127
123 /// Adds a new history entry and waits for the result 128 /// Adds a new history entry and waits for the result
124 - Future<T?> pushHistory<T>( 129 + Future<void> pushHistory(
125 GetNavConfig config, { 130 GetNavConfig config, {
126 bool rebuildStack = true, 131 bool rebuildStack = true,
127 - }) { 132 + }) async {
128 //this changes the currentConfiguration 133 //this changes the currentConfiguration
129 - final completer = Completer<T?>();  
130 - _resultCompleter[config] = completer;  
131 - _pushHistory(config); 134 + await _pushHistory(config);
132 if (rebuildStack) { 135 if (rebuildStack) {
133 refresh(); 136 refresh();
134 } 137 }
135 - return completer.future;  
136 } 138 }
137 139
138 - void _removeHistoryEntry(GetNavConfig entry) {  
139 - _unsafeHistoryRemove(entry);  
140 - final lastCompleter = _resultCompleter.remove(entry);  
141 - lastCompleter?.complete(entry); 140 + Future<void> _removeHistoryEntry(GetNavConfig entry) async {
  141 + await _unsafeHistoryRemove(entry);
142 } 142 }
143 143
144 - void _pushHistory(GetNavConfig config) { 144 + Future<void> _pushHistory(GetNavConfig config) async {
145 if (config.currentPage!.preventDuplicates) { 145 if (config.currentPage!.preventDuplicates) {
146 final originalEntryIndex = 146 final originalEntryIndex =
147 history.indexWhere((element) => element.location == config.location); 147 history.indexWhere((element) => element.location == config.location);
148 if (originalEntryIndex >= 0) { 148 if (originalEntryIndex >= 0) {
149 switch (preventDuplicateHandlingMode) { 149 switch (preventDuplicateHandlingMode) {
150 case PreventDuplicateHandlingMode.PopUntilOriginalRoute: 150 case PreventDuplicateHandlingMode.PopUntilOriginalRoute:
151 - backUntil(config.location!, popMode: PopMode.Page); 151 + await backUntil(config.location!, popMode: PopMode.Page);
152 break; 152 break;
153 case PreventDuplicateHandlingMode.ReorderRoutes: 153 case PreventDuplicateHandlingMode.ReorderRoutes:
154 - _unsafeHistoryRemoveAt(originalEntryIndex);  
155 - _unsafeHistoryAdd(config); 154 + await _unsafeHistoryRemoveAt(originalEntryIndex);
  155 + await _unsafeHistoryAdd(config);
156 break; 156 break;
157 case PreventDuplicateHandlingMode.DoNothing: 157 case PreventDuplicateHandlingMode.DoNothing:
158 default: 158 default:
@@ -161,7 +161,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -161,7 +161,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
161 return; 161 return;
162 } 162 }
163 } 163 }
164 - _unsafeHistoryAdd(config); 164 + await _unsafeHistoryAdd(config);
165 } 165 }
166 166
167 // GetPageRoute getPageRoute(RouteSettings? settings) { 167 // GetPageRoute getPageRoute(RouteSettings? settings) {
@@ -169,33 +169,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -169,33 +169,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
169 // .page(); 169 // .page();
170 // } 170 // }
171 171
172 - GetNavConfig? _popHistory() { 172 + Future<GetNavConfig?> _popHistory() async {
173 if (!_canPopHistory()) return null; 173 if (!_canPopHistory()) return null;
174 - return _doPopHistory(); 174 + return await _doPopHistory();
175 } 175 }
176 176
177 - GetNavConfig? _doPopHistory() {  
178 - return _unsafeHistoryRemoveAt(history.length - 1); 177 + Future<GetNavConfig?> _doPopHistory() async {
  178 + return await _unsafeHistoryRemoveAt(history.length - 1);
179 } 179 }
180 180
181 - GetNavConfig? _popPage() { 181 + Future<GetNavConfig?> _popPage() async {
182 if (!_canPopPage()) return null; 182 if (!_canPopPage()) return null;
183 - return _doPopPage(); 183 + return await _doPopPage();
184 } 184 }
185 185
186 - GetNavConfig? _pop(PopMode mode) { 186 + Future<GetNavConfig?> _pop(PopMode mode) async {
187 switch (mode) { 187 switch (mode) {
188 case PopMode.History: 188 case PopMode.History:
189 - return _popHistory(); 189 + return await _popHistory();
190 case PopMode.Page: 190 case PopMode.Page:
191 - return _popPage(); 191 + return await _popPage();
192 default: 192 default:
193 return null; 193 return null;
194 } 194 }
195 } 195 }
196 196
197 // returns the popped page 197 // returns the popped page
198 - GetNavConfig? _doPopPage() { 198 + Future<GetNavConfig?> _doPopPage() async {
199 final currentBranch = currentConfiguration?.currentTreeBranch; 199 final currentBranch = currentConfiguration?.currentTreeBranch;
200 if (currentBranch != null && currentBranch.length > 1) { 200 if (currentBranch != null && currentBranch.length > 1) {
201 //remove last part only 201 //remove last part only
@@ -210,13 +210,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -210,13 +210,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
210 final prevLocation = prevHistoryEntry.location; 210 final prevLocation = prevHistoryEntry.location;
211 if (newLocation == prevLocation) { 211 if (newLocation == prevLocation) {
212 //pop the entire history entry 212 //pop the entire history entry
213 - return _popHistory(); 213 + return await _popHistory();
214 } 214 }
215 } 215 }
216 216
217 //create a new route with the remaining tree branch 217 //create a new route with the remaining tree branch
218 - final res = _popHistory();  
219 - _pushHistory( 218 + final res = await _popHistory();
  219 + await _pushHistory(
220 GetNavConfig( 220 GetNavConfig(
221 currentTreeBranch: remaining.toList(), 221 currentTreeBranch: remaining.toList(),
222 location: remaining.last.name, 222 location: remaining.last.name,
@@ -226,12 +226,12 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -226,12 +226,12 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
226 return res; 226 return res;
227 } else { 227 } else {
228 //remove entire entry 228 //remove entire entry
229 - return _popHistory(); 229 + return await _popHistory();
230 } 230 }
231 } 231 }
232 232
233 - Future<GetNavConfig?> popHistory() {  
234 - return SynchronousFuture(_popHistory()); 233 + Future<GetNavConfig?> popHistory() async {
  234 + return await _popHistory();
235 } 235 }
236 236
237 bool _canPopHistory() { 237 bool _canPopHistory() {
@@ -263,6 +263,8 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -263,6 +263,8 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
263 } 263 }
264 264
265 /// gets the visual pages from the current history entry 265 /// gets the visual pages from the current history entry
  266 + ///
  267 + /// visual pages must have [participatesInRootNavigator] set to true
266 List<GetPage> getVisualPages() { 268 List<GetPage> getVisualPages() {
267 final currentHistory = currentConfiguration; 269 final currentHistory = currentConfiguration;
268 if (currentHistory == null) return <GetPage>[]; 270 if (currentHistory == null) return <GetPage>[];
@@ -283,6 +285,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -283,6 +285,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
283 @override 285 @override
284 Widget build(BuildContext context) { 286 Widget build(BuildContext context) {
285 final pages = getVisualPages(); 287 final pages = getVisualPages();
  288 + if (pages.length == 0) return SizedBox.shrink();
286 final extraObservers = navigatorObservers; 289 final extraObservers = navigatorObservers;
287 return GetNavigator( 290 return GetNavigator(
288 key: navigatorKey, 291 key: navigatorKey,
@@ -297,13 +300,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -297,13 +300,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
297 ); 300 );
298 } 301 }
299 302
300 - @override  
301 - Future<void> setInitialRoutePath(GetNavConfig configuration) async {  
302 - //no need to clear history with Reorder route strategy  
303 - // _unsafeHistoryClear();  
304 - // _resultCompleter.clear();  
305 - await pushHistory(configuration);  
306 - } 303 + // @override
  304 + // Future<void> setInitialRoutePath(GetNavConfig configuration) async {
  305 + // //no need to clear history with Reorder route strategy
  306 + // // _unsafeHistoryClear();
  307 + // // _resultCompleter.clear();
  308 + // await pushHistory(configuration);
  309 + // }
307 310
308 @override 311 @override
309 Future<void> setNewRoutePath(GetNavConfig configuration) async { 312 Future<void> setNewRoutePath(GetNavConfig configuration) async {
@@ -317,11 +320,11 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -317,11 +320,11 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
317 return route; 320 return route;
318 } 321 }
319 322
320 - Future<T?> toNamed<T>( 323 + Future<void> toNamed(
321 String page, { 324 String page, {
322 dynamic arguments, 325 dynamic arguments,
323 Map<String, String>? parameters, 326 Map<String, String>? parameters,
324 - }) { 327 + }) async {
325 if (parameters != null) { 328 if (parameters != null) {
326 final uri = Uri(path: page, queryParameters: parameters); 329 final uri = Uri(path: page, queryParameters: parameters);
327 page = uri.toString(); 330 page = uri.toString();
@@ -330,7 +333,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -330,7 +333,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
330 final decoder = Get.routeTree.matchRoute(page, arguments: arguments); 333 final decoder = Get.routeTree.matchRoute(page, arguments: arguments);
331 decoder.replaceArguments(arguments); 334 decoder.replaceArguments(arguments);
332 335
333 - return pushHistory<T>( 336 + await pushHistory(
334 GetNavConfig( 337 GetNavConfig(
335 currentTreeBranch: decoder.treeBranch, 338 currentTreeBranch: decoder.treeBranch,
336 location: page, 339 location: page,
@@ -339,40 +342,34 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -339,40 +342,34 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
339 ); 342 );
340 } 343 }
341 344
342 - Future<T?> offNamed<T>(String page,  
343 - {dynamic arguments, Map<String, String>? parameters}) async { 345 + Future<void> offNamed(
  346 + String page, {
  347 + dynamic arguments,
  348 + Map<String, String>? parameters,
  349 + }) async {
344 await popHistory(); 350 await popHistory();
345 - return await toNamed(page, arguments: arguments, parameters: parameters); 351 + await toNamed(page, arguments: arguments, parameters: parameters);
346 } 352 }
347 353
348 /// Removes routes according to [PopMode] 354 /// Removes routes according to [PopMode]
349 /// until it reaches the specifc [fullRoute], 355 /// until it reaches the specifc [fullRoute],
350 /// DOES NOT remove the [fullRoute] 356 /// DOES NOT remove the [fullRoute]
351 - void backUntil( 357 + Future<void> backUntil(
352 String fullRoute, { 358 String fullRoute, {
353 PopMode popMode = PopMode.Page, 359 PopMode popMode = PopMode.Page,
354 - }) { 360 + }) async {
355 // remove history or page entries until you meet route 361 // remove history or page entries until you meet route
356 var iterator = currentConfiguration; 362 var iterator = currentConfiguration;
357 while (_canPop(popMode) && 363 while (_canPop(popMode) &&
358 iterator != null && 364 iterator != null &&
359 iterator.location != fullRoute) { 365 iterator.location != fullRoute) {
360 - _pop(popMode); 366 + await _pop(popMode);
361 // replace iterator 367 // replace iterator
362 iterator = currentConfiguration; 368 iterator = currentConfiguration;
363 } 369 }
364 refresh(); 370 refresh();
365 } 371 }
366 372
367 - // GetPage _notFound() {  
368 - // return notFoundRoute ??= GetPage(  
369 - // name: '/404',  
370 - // page: () => Scaffold(  
371 - // body: Text('not found'),  
372 - // ),  
373 - // );  
374 - // }  
375 -  
376 Future<bool> handlePopupRoutes({ 373 Future<bool> handlePopupRoutes({
377 Object? result, 374 Object? result,
378 }) async { 375 }) async {
@@ -395,15 +392,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -395,15 +392,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
395 //Returning false will cause the entire app to be popped. 392 //Returning false will cause the entire app to be popped.
396 final wasPopup = await handlePopupRoutes(result: result); 393 final wasPopup = await handlePopupRoutes(result: result);
397 if (wasPopup) return true; 394 if (wasPopup) return true;
398 - final _popped = _pop(popMode); 395 + final _popped = await _pop(popMode);
399 refresh(); 396 refresh();
400 if (_popped != null) { 397 if (_popped != null) {
401 //emulate the old pop with result 398 //emulate the old pop with result
402 - final lastCompleter = _resultCompleter.remove(_popped);  
403 - lastCompleter?.complete(result);  
404 - return Future.value(true); 399 + return true;
405 } 400 }
406 - return Future.value(false); 401 + return false;
407 } 402 }
408 403
409 bool _onPopVisualRoute(Route<dynamic> route, dynamic result) { 404 bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {
@@ -434,15 +429,9 @@ class GetNavigator extends Navigator { @@ -434,15 +429,9 @@ class GetNavigator extends Navigator {
434 List<NavigatorObserver>? observers, 429 List<NavigatorObserver>? observers,
435 bool reportsRouteUpdateToEngine = false, 430 bool reportsRouteUpdateToEngine = false,
436 TransitionDelegate? transitionDelegate, 431 TransitionDelegate? transitionDelegate,
437 - // String? name,  
438 }) : super( 432 }) : super(
439 //keys should be optional 433 //keys should be optional
440 key: key, 434 key: key,
441 - // key != null  
442 - // ? key  
443 - // : name != null  
444 - // ? Get.nestedKey(name)  
445 - // : null,  
446 onPopPage: onPopPage ?? 435 onPopPage: onPopPage ??
447 (route, result) { 436 (route, result) {
448 final didPop = route.didPop(result); 437 final didPop = route.didPop(result);
@@ -21,11 +21,11 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> @@ -21,11 +21,11 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
21 21
22 RouterOutlet({ 22 RouterOutlet({
23 TDelegate? delegate, 23 TDelegate? delegate,
24 - required List<GetPage> Function(T currentNavStack) pickPages, 24 + required Iterable<GetPage> Function(T currentNavStack) pickPages,
25 required Widget Function( 25 required Widget Function(
26 BuildContext context, 26 BuildContext context,
27 TDelegate, 27 TDelegate,
28 - List<GetPage>? page, 28 + Iterable<GetPage>? page,
29 ) 29 )
30 pageBuilder, 30 pageBuilder,
31 }) : this.builder( 31 }) : this.builder(
@@ -77,16 +77,48 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> @@ -77,16 +77,48 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
77 77
78 class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { 78 class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
79 GetRouterOutlet({ 79 GetRouterOutlet({
  80 + String? anchorRoute,
80 required String initialRoute, 81 required String initialRoute,
  82 + Iterable<GetPage> Function(Iterable<GetPage> afterAnchor)? filterPages,
  83 + GlobalKey<NavigatorState>? key,
  84 + }) : this.pickPages(
  85 + pickPages: (config) {
  86 + Iterable<GetPage<dynamic>> ret;
  87 + if (anchorRoute == null) {
  88 + //anchorRoute = initialRoute minus last segment
  89 + final parsedUri = Uri.parse(initialRoute);
  90 + final replacedUri = parsedUri.replace(
  91 + pathSegments: parsedUri.pathSegments.take(
  92 + parsedUri.pathSegments.length - 1,
  93 + ),
  94 + );
  95 + anchorRoute = '/$replacedUri';
  96 + }
  97 + ret = config.currentTreeBranch.pickAfterRoute(anchorRoute!);
  98 + if (filterPages != null) {
  99 + ret = filterPages(ret);
  100 + }
  101 + return ret;
  102 + },
  103 + emptyPage: (delegate) =>
  104 + Get.routeTree.matchRoute(initialRoute).route ??
  105 + delegate.notFoundRoute,
  106 + key: key,
  107 + );
  108 + GetRouterOutlet.pickPages({
81 Widget Function(GetDelegate delegate)? emptyWidget, 109 Widget Function(GetDelegate delegate)? emptyWidget,
  110 + GetPage Function(GetDelegate delegate)? emptyPage,
  111 + required Iterable<GetPage> Function(GetNavConfig currentNavStack) pickPages,
82 bool Function(Route<dynamic>, dynamic)? onPopPage, 112 bool Function(Route<dynamic>, dynamic)? onPopPage,
83 - // String? name, 113 + GlobalKey<NavigatorState>? key,
84 }) : super( 114 }) : super(
85 pageBuilder: (context, rDelegate, pages) { 115 pageBuilder: (context, rDelegate, pages) {
86 - final route = Get.routeTree.matchRoute(initialRoute);  
87 - final pageRes = (pages ?? <GetPage<dynamic>?>[route.route])  
88 - .whereType<GetPage<dynamic>>()  
89 - .toList(); 116 + final pageRes = <GetPage?>[
  117 + ...?pages,
  118 + if (pages == null || pages.length == 0)
  119 + emptyPage?.call(rDelegate),
  120 + ].whereType<GetPage>();
  121 +
90 if (pageRes.length > 0) { 122 if (pageRes.length > 0) {
91 return GetNavigator( 123 return GetNavigator(
92 onPopPage: onPopPage ?? 124 onPopPage: onPopPage ??
@@ -97,19 +129,13 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { @@ -97,19 +129,13 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
97 } 129 }
98 return true; 130 return true;
99 }, 131 },
100 - pages: pageRes,  
101 - //name: name, 132 + pages: pageRes.toList(),
  133 + key: key,
102 ); 134 );
103 } 135 }
104 return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink()); 136 return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink());
105 }, 137 },
106 - pickPages: (currentNavStack) {  
107 - final length = Uri.parse(initialRoute).pathSegments.length;  
108 - return currentNavStack.currentTreeBranch  
109 - .skip(length)  
110 - .take(length)  
111 - .toList();  
112 - }, 138 + pickPages: pickPages,
113 delegate: Get.rootDelegate, 139 delegate: Get.rootDelegate,
114 ); 140 );
115 141
@@ -127,12 +153,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { @@ -127,12 +153,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
127 ); 153 );
128 } 154 }
129 155
130 -// extension PagesListExt on List<GetPage> {  
131 -// List<GetPage> pickAtRoute(String route) {  
132 -// return skipWhile((value) => value.name != route).toList();  
133 -// } 156 +extension PagesListExt on List<GetPage> {
  157 + Iterable<GetPage> pickAtRoute(String route) {
  158 + return skipWhile((value) {
  159 + return value.name != route;
  160 + });
  161 + }
134 162
135 -// List<GetPage> pickAfterRoute(String route) {  
136 -// return skipWhile((value) => value.name != route).skip(1).toList();  
137 -// }  
138 -// } 163 + Iterable<GetPage> pickAfterRoute(String route) {
  164 + return pickAtRoute(route).skip(1);
  165 + }
  166 +}
1 import 'package:flutter/cupertino.dart'; 1 import 'package:flutter/cupertino.dart';
  2 +import 'package:flutter/foundation.dart';
2 import '../../../get.dart'; 3 import '../../../get.dart';
3 4
4 abstract class _RouteMiddleware { 5 abstract class _RouteMiddleware {
@@ -49,7 +50,7 @@ abstract class _RouteMiddleware { @@ -49,7 +50,7 @@ abstract class _RouteMiddleware {
49 /// } 50 /// }
50 /// ``` 51 /// ```
51 /// {@end-tool} 52 /// {@end-tool}
52 - GetNavConfig? redirectDelegate(GetNavConfig route); 53 + Future<GetNavConfig?> redirectDelegate(GetNavConfig route);
53 54
54 /// This function will be called when this Page is called 55 /// This function will be called when this Page is called
55 /// you can use it to change something about the page or give it new page 56 /// you can use it to change something about the page or give it new page
@@ -118,7 +119,8 @@ class GetMiddleware implements _RouteMiddleware { @@ -118,7 +119,8 @@ class GetMiddleware implements _RouteMiddleware {
118 void onPageDispose() {} 119 void onPageDispose() {}
119 120
120 @override 121 @override
121 - GetNavConfig? redirectDelegate(GetNavConfig route) => route; 122 + Future<GetNavConfig?> redirectDelegate(GetNavConfig route) =>
  123 + SynchronousFuture(route);
122 } 124 }
123 125
124 class MiddlewareRunner { 126 class MiddlewareRunner {