Ahmed Fwela

- Improved router delegate

- Rolled back RouterOutlet, and introduced simpler API
@@ -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 }
@@ -19,8 +19,10 @@ class HomeView extends GetView<HomeController> { @@ -19,8 +19,10 @@ class HomeView extends GetView<HomeController> {
19 currentIndex = 1; 19 currentIndex = 1;
20 } 20 }
21 return Scaffold( 21 return Scaffold(
22 - body: GetRouterOutlet( 22 + body: GetRouterOutlet.fromRoute(
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 {}
@@ -17,8 +17,12 @@ class RootView extends GetView<RootController> { @@ -17,8 +17,12 @@ class RootView extends GetView<RootController> {
17 title: Text(title ?? ''), 17 title: Text(title ?? ''),
18 centerTitle: true, 18 centerTitle: true,
19 ), 19 ),
20 - body: GetRouterOutlet( 20 + body: GetRouterOutlet.fromRoute(
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 }
@@ -113,38 +118,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -113,38 +118,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
113 // } 118 // }
114 119
115 /// Adds a new history entry and waits for the result 120 /// Adds a new history entry and waits for the result
116 - Future<T?> pushHistory<T>( 121 + Future<void> pushHistory(
117 GetNavConfig config, { 122 GetNavConfig config, {
118 bool rebuildStack = true, 123 bool rebuildStack = true,
119 - }) { 124 + }) async {
120 //this changes the currentConfiguration 125 //this changes the currentConfiguration
121 - final completer = Completer<T?>();  
122 - _resultCompleter[config] = completer;  
123 - _pushHistory(config); 126 + await _pushHistory(config);
124 if (rebuildStack) { 127 if (rebuildStack) {
125 refresh(); 128 refresh();
126 } 129 }
127 - return completer.future;  
128 } 130 }
129 131
130 - void _removeHistoryEntry(GetNavConfig entry) {  
131 - _unsafeHistoryRemove(entry);  
132 - final lastCompleter = _resultCompleter.remove(entry);  
133 - lastCompleter?.complete(entry); 132 + Future<void> _removeHistoryEntry(GetNavConfig entry) async {
  133 + await _unsafeHistoryRemove(entry);
134 } 134 }
135 135
136 - void _pushHistory(GetNavConfig config) { 136 + Future<void> _pushHistory(GetNavConfig config) async {
137 if (config.currentPage!.preventDuplicates) { 137 if (config.currentPage!.preventDuplicates) {
138 final originalEntryIndex = 138 final originalEntryIndex =
139 history.indexWhere((element) => element.location == config.location); 139 history.indexWhere((element) => element.location == config.location);
140 if (originalEntryIndex >= 0) { 140 if (originalEntryIndex >= 0) {
141 switch (preventDuplicateHandlingMode) { 141 switch (preventDuplicateHandlingMode) {
142 case PreventDuplicateHandlingMode.PopUntilOriginalRoute: 142 case PreventDuplicateHandlingMode.PopUntilOriginalRoute:
143 - until(config.location!, popMode: PopMode.Page); 143 + await until(config.location!, popMode: PopMode.Page);
144 break; 144 break;
145 case PreventDuplicateHandlingMode.ReorderRoutes: 145 case PreventDuplicateHandlingMode.ReorderRoutes:
146 - _unsafeHistoryRemoveAt(originalEntryIndex);  
147 - _unsafeHistoryAdd(config); 146 + await _unsafeHistoryRemoveAt(originalEntryIndex);
  147 + await _unsafeHistoryAdd(config);
148 break; 148 break;
149 case PreventDuplicateHandlingMode.DoNothing: 149 case PreventDuplicateHandlingMode.DoNothing:
150 default: 150 default:
@@ -153,7 +153,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -153,7 +153,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
153 return; 153 return;
154 } 154 }
155 } 155 }
156 - _unsafeHistoryAdd(config); 156 + await _unsafeHistoryAdd(config);
157 } 157 }
158 158
159 // GetPageRoute getPageRoute(RouteSettings? settings) { 159 // GetPageRoute getPageRoute(RouteSettings? settings) {
@@ -161,33 +161,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -161,33 +161,33 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
161 // .page(); 161 // .page();
162 // } 162 // }
163 163
164 - GetNavConfig? _popHistory() { 164 + Future<GetNavConfig?> _popHistory() async {
165 if (!_canPopHistory()) return null; 165 if (!_canPopHistory()) return null;
166 - return _doPopHistory(); 166 + return await _doPopHistory();
167 } 167 }
168 168
169 - GetNavConfig? _doPopHistory() {  
170 - return _unsafeHistoryRemoveAt(history.length - 1); 169 + Future<GetNavConfig?> _doPopHistory() async {
  170 + return await _unsafeHistoryRemoveAt(history.length - 1);
171 } 171 }
172 172
173 - GetNavConfig? _popPage() { 173 + Future<GetNavConfig?> _popPage() async {
174 if (!_canPopPage()) return null; 174 if (!_canPopPage()) return null;
175 - return _doPopPage(); 175 + return await _doPopPage();
176 } 176 }
177 177
178 - GetNavConfig? _pop(PopMode mode) { 178 + Future<GetNavConfig?> _pop(PopMode mode) async {
179 switch (mode) { 179 switch (mode) {
180 case PopMode.History: 180 case PopMode.History:
181 - return _popHistory(); 181 + return await _popHistory();
182 case PopMode.Page: 182 case PopMode.Page:
183 - return _popPage(); 183 + return await _popPage();
184 default: 184 default:
185 return null; 185 return null;
186 } 186 }
187 } 187 }
188 188
189 // returns the popped page 189 // returns the popped page
190 - GetNavConfig? _doPopPage() { 190 + Future<GetNavConfig?> _doPopPage() async {
191 final currentBranch = currentConfiguration?.currentTreeBranch; 191 final currentBranch = currentConfiguration?.currentTreeBranch;
192 if (currentBranch != null && currentBranch.length > 1) { 192 if (currentBranch != null && currentBranch.length > 1) {
193 //remove last part only 193 //remove last part only
@@ -202,13 +202,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -202,13 +202,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
202 final prevLocation = prevHistoryEntry.location; 202 final prevLocation = prevHistoryEntry.location;
203 if (newLocation == prevLocation) { 203 if (newLocation == prevLocation) {
204 //pop the entire history entry 204 //pop the entire history entry
205 - return _popHistory(); 205 + return await _popHistory();
206 } 206 }
207 } 207 }
208 208
209 //create a new route with the remaining tree branch 209 //create a new route with the remaining tree branch
210 - final res = _popHistory();  
211 - _pushHistory( 210 + final res = await _popHistory();
  211 + await _pushHistory(
212 GetNavConfig( 212 GetNavConfig(
213 currentTreeBranch: remaining.toList(), 213 currentTreeBranch: remaining.toList(),
214 location: remaining.last.name, 214 location: remaining.last.name,
@@ -218,12 +218,12 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -218,12 +218,12 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
218 return res; 218 return res;
219 } else { 219 } else {
220 //remove entire entry 220 //remove entire entry
221 - return _popHistory(); 221 + return await _popHistory();
222 } 222 }
223 } 223 }
224 224
225 - Future<GetNavConfig?> popHistory() {  
226 - return SynchronousFuture(_popHistory()); 225 + Future<GetNavConfig?> popHistory() async {
  226 + return await _popHistory();
227 } 227 }
228 228
229 bool _canPopHistory() { 229 bool _canPopHistory() {
@@ -256,8 +256,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -256,8 +256,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
256 256
257 /// gets the visual pages from the current history entry 257 /// gets the visual pages from the current history entry
258 /// 258 ///
259 - /// visual pages must have the [RouterOutletContainerMiddleWare] middleware  
260 - /// with `stayAt` equal to the route name of the visual page 259 + /// visual pages must have [participatesInRootNavigator] set to true
261 List<GetPage> getVisualPages() { 260 List<GetPage> getVisualPages() {
262 final currentHistory = currentConfiguration; 261 final currentHistory = currentConfiguration;
263 if (currentHistory == null) return <GetPage>[]; 262 if (currentHistory == null) return <GetPage>[];
@@ -278,6 +277,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -278,6 +277,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
278 @override 277 @override
279 Widget build(BuildContext context) { 278 Widget build(BuildContext context) {
280 final pages = getVisualPages(); 279 final pages = getVisualPages();
  280 + if (pages.length == 0) return SizedBox.shrink();
281 final extraObservers = navigatorObservers; 281 final extraObservers = navigatorObservers;
282 return GetNavigator( 282 return GetNavigator(
283 key: navigatorKey, 283 key: navigatorKey,
@@ -292,13 +292,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -292,13 +292,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
292 ); 292 );
293 } 293 }
294 294
295 - @override  
296 - Future<void> setInitialRoutePath(GetNavConfig configuration) async {  
297 - //no need to clear history with Reorder route strategy  
298 - // _unsafeHistoryClear();  
299 - // _resultCompleter.clear();  
300 - await pushHistory(configuration);  
301 - } 295 + // @override
  296 + // Future<void> setInitialRoutePath(GetNavConfig configuration) async {
  297 + // //no need to clear history with Reorder route strategy
  298 + // // _unsafeHistoryClear();
  299 + // // _resultCompleter.clear();
  300 + // await pushHistory(configuration);
  301 + // }
302 302
303 @override 303 @override
304 Future<void> setNewRoutePath(GetNavConfig configuration) async { 304 Future<void> setNewRoutePath(GetNavConfig configuration) async {
@@ -312,10 +312,10 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -312,10 +312,10 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
312 return route; 312 return route;
313 } 313 }
314 314
315 - Future<T?> toNamed<T>(String fullRoute) { 315 + Future<void> toNamed(String fullRoute) async {
316 final decoder = Get.routeTree.matchRoute(fullRoute); 316 final decoder = Get.routeTree.matchRoute(fullRoute);
317 317
318 - return pushHistory<T>( 318 + return await pushHistory(
319 GetNavConfig( 319 GetNavConfig(
320 currentTreeBranch: decoder.treeBranch, 320 currentTreeBranch: decoder.treeBranch,
321 location: fullRoute, 321 location: fullRoute,
@@ -324,40 +324,31 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -324,40 +324,31 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
324 ); 324 );
325 } 325 }
326 326
327 - Future<T?> offNamed<T>(String fullRoute) async { 327 + Future<void> offNamed(String fullRoute) async {
328 await popHistory(); 328 await popHistory();
329 - return await toNamed(fullRoute); 329 + await toNamed(fullRoute);
330 } 330 }
331 331
332 /// Removes routes according to [PopMode] 332 /// Removes routes according to [PopMode]
333 /// until it reaches the specifc [fullRoute], 333 /// until it reaches the specifc [fullRoute],
334 /// DOES NOT remove the [fullRoute] 334 /// DOES NOT remove the [fullRoute]
335 - void until( 335 + Future<void> until(
336 String fullRoute, { 336 String fullRoute, {
337 PopMode popMode = PopMode.Page, 337 PopMode popMode = PopMode.Page,
338 - }) { 338 + }) async {
339 // remove history or page entries until you meet route 339 // remove history or page entries until you meet route
340 340
341 var iterator = currentConfiguration; 341 var iterator = currentConfiguration;
342 while (_canPop(popMode) && 342 while (_canPop(popMode) &&
343 iterator != null && 343 iterator != null &&
344 iterator.location != fullRoute) { 344 iterator.location != fullRoute) {
345 - _pop(popMode); 345 + await _pop(popMode);
346 // replace iterator 346 // replace iterator
347 iterator = currentConfiguration; 347 iterator = currentConfiguration;
348 } 348 }
349 refresh(); 349 refresh();
350 } 350 }
351 351
352 - // GetPage _notFound() {  
353 - // return notFoundRoute ??= GetPage(  
354 - // name: '/404',  
355 - // page: () => Scaffold(  
356 - // body: Text('not found'),  
357 - // ),  
358 - // );  
359 - // }  
360 -  
361 Future<bool> handlePopupRoutes({ 352 Future<bool> handlePopupRoutes({
362 Object? result, 353 Object? result,
363 }) async { 354 }) async {
@@ -380,15 +371,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -380,15 +371,13 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
380 //Returning false will cause the entire app to be popped. 371 //Returning false will cause the entire app to be popped.
381 final wasPopup = await handlePopupRoutes(result: result); 372 final wasPopup = await handlePopupRoutes(result: result);
382 if (wasPopup) return true; 373 if (wasPopup) return true;
383 - final _popped = _pop(popMode); 374 + final _popped = await _pop(popMode);
384 refresh(); 375 refresh();
385 if (_popped != null) { 376 if (_popped != null) {
386 //emulate the old pop with result 377 //emulate the old pop with result
387 - final lastCompleter = _resultCompleter.remove(_popped);  
388 - lastCompleter?.complete(result);  
389 - return Future.value(true); 378 + return true;
390 } 379 }
391 - return Future.value(false); 380 + return false;
392 } 381 }
393 382
394 bool _onPopVisualRoute(Route<dynamic> route, dynamic result) { 383 bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {
@@ -419,15 +408,9 @@ class GetNavigator extends Navigator { @@ -419,15 +408,9 @@ class GetNavigator extends Navigator {
419 List<NavigatorObserver>? observers, 408 List<NavigatorObserver>? observers,
420 bool reportsRouteUpdateToEngine = false, 409 bool reportsRouteUpdateToEngine = false,
421 TransitionDelegate? transitionDelegate, 410 TransitionDelegate? transitionDelegate,
422 - // String? name,  
423 }) : super( 411 }) : super(
424 //keys should be optional 412 //keys should be optional
425 key: key, 413 key: key,
426 - // key != null  
427 - // ? key  
428 - // : name != null  
429 - // ? Get.nestedKey(name)  
430 - // : null,  
431 onPopPage: onPopPage ?? 414 onPopPage: onPopPage ??
432 (route, result) { 415 (route, result) {
433 final didPop = route.didPop(result); 416 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(
@@ -76,17 +76,38 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> @@ -76,17 +76,38 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
76 } 76 }
77 77
78 class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { 78 class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
79 - GetRouterOutlet({ 79 + GetRouterOutlet.fromRoute({
  80 + required String anchorRoute,
80 required String initialRoute, 81 required String initialRoute,
  82 + Iterable<GetPage> Function(Iterable<GetPage> afterAnchor)? filterPages,
  83 + GlobalKey<NavigatorState>? key,
  84 + }) : this(
  85 + pickPages: (config) {
  86 + var ret = config.currentTreeBranch.pickAfterRoute(anchorRoute);
  87 + if (filterPages != null) {
  88 + ret = filterPages(ret);
  89 + }
  90 + return ret;
  91 + },
  92 + emptyPage: (delegate) =>
  93 + Get.routeTree.matchRoute(initialRoute).route ??
  94 + delegate.notFoundRoute,
  95 + key: key,
  96 + );
  97 + GetRouterOutlet({
81 Widget Function(GetDelegate delegate)? emptyWidget, 98 Widget Function(GetDelegate delegate)? emptyWidget,
  99 + GetPage Function(GetDelegate delegate)? emptyPage,
  100 + required Iterable<GetPage> Function(GetNavConfig currentNavStack) pickPages,
82 bool Function(Route<dynamic>, dynamic)? onPopPage, 101 bool Function(Route<dynamic>, dynamic)? onPopPage,
83 - // String? name, 102 + GlobalKey<NavigatorState>? key,
84 }) : super( 103 }) : super(
85 pageBuilder: (context, rDelegate, pages) { 104 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(); 105 + final pageRes = <GetPage?>[
  106 + ...?pages,
  107 + if (pages == null || pages.length == 0)
  108 + emptyPage?.call(rDelegate),
  109 + ].whereType<GetPage>();
  110 +
90 if (pageRes.length > 0) { 111 if (pageRes.length > 0) {
91 return GetNavigator( 112 return GetNavigator(
92 onPopPage: onPopPage ?? 113 onPopPage: onPopPage ??
@@ -97,19 +118,13 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { @@ -97,19 +118,13 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
97 } 118 }
98 return true; 119 return true;
99 }, 120 },
100 - pages: pageRes,  
101 - //name: name, 121 + pages: pageRes.toList(),
  122 + key: key,
102 ); 123 );
103 } 124 }
104 return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink()); 125 return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink());
105 }, 126 },
106 - pickPages: (currentNavStack) {  
107 - final length = Uri.parse(initialRoute).pathSegments.length;  
108 - return currentNavStack.currentTreeBranch  
109 - .skip(length)  
110 - .take(length)  
111 - .toList();  
112 - }, 127 + pickPages: pickPages,
113 delegate: Get.rootDelegate, 128 delegate: Get.rootDelegate,
114 ); 129 );
115 130
@@ -127,12 +142,12 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> { @@ -127,12 +142,12 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, GetNavConfig> {
127 ); 142 );
128 } 143 }
129 144
130 -// extension PagesListExt on List<GetPage> {  
131 -// List<GetPage> pickAtRoute(String route) {  
132 -// return skipWhile((value) => value.name != route).toList();  
133 -// } 145 +extension PagesListExt on List<GetPage> {
  146 + Iterable<GetPage> pickAtRoute(String route) {
  147 + return skipWhile((value) => value.name != route).toList();
  148 + }
134 149
135 -// List<GetPage> pickAfterRoute(String route) {  
136 -// return skipWhile((value) => value.name != route).skip(1).toList();  
137 -// }  
138 -// } 150 + Iterable<GetPage> pickAfterRoute(String route) {
  151 + return skipWhile((value) => value.name != route).skip(1).toList();
  152 + }
  153 +}
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 {