Ahmed Fwela

WIP navigation fixes

@@ -4,6 +4,7 @@ export 'src/bottomsheet/bottomsheet.dart'; @@ -4,6 +4,7 @@ export 'src/bottomsheet/bottomsheet.dart';
4 export 'src/extension_navigation.dart'; 4 export 'src/extension_navigation.dart';
5 export 'src/nav2/get_information_parser.dart'; 5 export 'src/nav2/get_information_parser.dart';
6 export 'src/nav2/get_nav_config.dart'; 6 export 'src/nav2/get_nav_config.dart';
  7 +export 'src/nav2/get_navigator.dart';
7 export 'src/nav2/get_router_delegate.dart'; 8 export 'src/nav2/get_router_delegate.dart';
8 export 'src/nav2/router_outlet.dart'; 9 export 'src/nav2/router_outlet.dart';
9 export 'src/root/get_cupertino_app.dart'; 10 export 'src/root/get_cupertino_app.dart';
  1 +import 'package:flutter/widgets.dart';
  2 +import '../routes/default_route.dart';
  3 +import '../routes/get_route.dart';
  4 +
  5 +class GetNavigator extends Navigator {
  6 + GetNavigator.onGenerateRoute({
  7 + GlobalKey<NavigatorState>? key,
  8 + bool Function(Route<dynamic>, dynamic)? onPopPage,
  9 + required List<GetPage> pages,
  10 + List<NavigatorObserver>? observers,
  11 + bool reportsRouteUpdateToEngine = false,
  12 + TransitionDelegate? transitionDelegate,
  13 + String? initialRoute,
  14 + }) : super(
  15 + //keys should be optional
  16 + key: key,
  17 + initialRoute: initialRoute,
  18 + onPopPage: onPopPage ??
  19 + (route, result) {
  20 + final didPop = route.didPop(result);
  21 + if (!didPop) {
  22 + return false;
  23 + }
  24 + return true;
  25 + },
  26 + onGenerateRoute: (settings) {
  27 + final selectedPageList =
  28 + pages.where((element) => element.name == settings.name);
  29 + if (selectedPageList.isNotEmpty) {
  30 + final selectedPage = selectedPageList.first;
  31 + return GetPageRoute(
  32 + page: selectedPage.page,
  33 + settings: settings,
  34 + );
  35 + }
  36 + },
  37 + reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,
  38 + pages: pages,
  39 + observers: [
  40 + // GetObserver(),
  41 + ...?observers,
  42 + ],
  43 + transitionDelegate:
  44 + transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
  45 + );
  46 +
  47 + GetNavigator({
  48 + GlobalKey<NavigatorState>? key,
  49 + bool Function(Route<dynamic>, dynamic)? onPopPage,
  50 + required List<GetPage> pages,
  51 + List<NavigatorObserver>? observers,
  52 + bool reportsRouteUpdateToEngine = false,
  53 + TransitionDelegate? transitionDelegate,
  54 + String? initialRoute,
  55 + }) : super(
  56 + //keys should be optional
  57 + key: key,
  58 + initialRoute: initialRoute,
  59 + onPopPage: onPopPage ??
  60 + (route, result) {
  61 + final didPop = route.didPop(result);
  62 + if (!didPop) {
  63 + return false;
  64 + }
  65 + return true;
  66 + },
  67 + reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,
  68 + pages: pages,
  69 + observers: [
  70 + // GetObserver(),
  71 + ...?observers,
  72 + ],
  73 + transitionDelegate:
  74 + transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
  75 + );
  76 +}
@@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
4 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
5 import '../../../get.dart'; 5 import '../../../get.dart';
6 import '../../../get_state_manager/src/simple/list_notifier.dart'; 6 import '../../../get_state_manager/src/simple/list_notifier.dart';
  7 +import 'get_navigator.dart';
7 8
8 /// Enables the user to customize the intended pop behavior 9 /// Enables the user to customize the intended pop behavior
9 /// 10 ///
@@ -57,6 +58,9 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -57,6 +58,9 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
57 final List<NavigatorObserver>? navigatorObservers; 58 final List<NavigatorObserver>? navigatorObservers;
58 final TransitionDelegate<dynamic>? transitionDelegate; 59 final TransitionDelegate<dynamic>? transitionDelegate;
59 60
  61 + final Iterable<GetPage> Function(GetNavConfig currentNavStack)?
  62 + pickPagesForRootNavigator;
  63 +
60 GlobalKey<NavigatorState> get navigatorKey => Get.key; 64 GlobalKey<NavigatorState> get navigatorKey => Get.key;
61 65
62 GetDelegate({ 66 GetDelegate({
@@ -66,6 +70,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -66,6 +70,7 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
66 this.backButtonPopMode = PopMode.History, 70 this.backButtonPopMode = PopMode.History,
67 this.preventDuplicateHandlingMode = 71 this.preventDuplicateHandlingMode =
68 PreventDuplicateHandlingMode.ReorderRoutes, 72 PreventDuplicateHandlingMode.ReorderRoutes,
  73 + this.pickPagesForRootNavigator,
69 }) : notFoundRoute = notFoundRoute ?? 74 }) : notFoundRoute = notFoundRoute ??
70 GetPage( 75 GetPage(
71 name: '/404', 76 name: '/404',
@@ -120,10 +125,6 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -120,10 +125,6 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
120 return currentConfiguration?.currentPage?.parameters ?? {}; 125 return currentConfiguration?.currentPage?.parameters ?? {};
121 } 126 }
122 127
123 - // void _unsafeHistoryClear() {  
124 - // history.clear();  
125 - // }  
126 -  
127 /// Adds a new history entry and waits for the result 128 /// Adds a new history entry and waits for the result
128 Future<void> pushHistory( 129 Future<void> pushHistory(
129 GetNavConfig config, { 130 GetNavConfig config, {
@@ -163,11 +164,6 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -163,11 +164,6 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
163 await _unsafeHistoryAdd(config); 164 await _unsafeHistoryAdd(config);
164 } 165 }
165 166
166 - // GetPageRoute getPageRoute(RouteSettings? settings) {  
167 - // return PageRedirect(settings ?? RouteSettings(name: '/404'), _notFound())  
168 - // .page();  
169 - // }  
170 -  
171 Future<GetNavConfig?> _popHistory() async { 167 Future<GetNavConfig?> _popHistory() async {
172 if (!_canPopHistory()) return null; 168 if (!_canPopHistory()) return null;
173 return await _doPopHistory(); 169 return await _doPopHistory();
@@ -263,36 +259,35 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -263,36 +259,35 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
263 259
264 /// gets the visual pages from the current history entry 260 /// gets the visual pages from the current history entry
265 /// 261 ///
266 - /// visual pages must have [participatesInRootNavigator] set to true  
267 - List<GetPage> getVisualPages() {  
268 - final currentHistory = currentConfiguration;  
269 - if (currentHistory == null) return <GetPage>[];  
270 - 262 + /// visual pages must have [GetPage.participatesInRootNavigator] set to true
  263 + Iterable<GetPage> getVisualPages(GetNavConfig currentHistory) {
271 final res = currentHistory.currentTreeBranch 264 final res = currentHistory.currentTreeBranch
272 .where((r) => r.participatesInRootNavigator != null); 265 .where((r) => r.participatesInRootNavigator != null);
273 if (res.length == 0) { 266 if (res.length == 0) {
274 //default behavoir, all routes participate in root navigator 267 //default behavoir, all routes participate in root navigator
275 - return history.map((e) => e.currentPage!).toList(); 268 + return history.map((e) => e.currentPage!);
276 } else { 269 } else {
277 //user specified at least one participatesInRootNavigator 270 //user specified at least one participatesInRootNavigator
278 return res 271 return res
279 - .where((element) => element.participatesInRootNavigator == true)  
280 - .toList(); 272 + .where((element) => element.participatesInRootNavigator == true);
281 } 273 }
282 } 274 }
283 275
284 @override 276 @override
285 Widget build(BuildContext context) { 277 Widget build(BuildContext context) {
286 - final pages = getVisualPages(); 278 + final currentHistory = currentConfiguration;
  279 + final pages = currentHistory == null
  280 + ? <GetPage>[]
  281 + : pickPagesForRootNavigator?.call(currentHistory) ??
  282 + getVisualPages(currentHistory);
287 if (pages.length == 0) return SizedBox.shrink(); 283 if (pages.length == 0) return SizedBox.shrink();
288 - final extraObservers = navigatorObservers;  
289 return GetNavigator( 284 return GetNavigator(
290 key: navigatorKey, 285 key: navigatorKey,
291 onPopPage: _onPopVisualRoute, 286 onPopPage: _onPopVisualRoute,
292 - pages: pages, 287 + pages: pages.toList(),
293 observers: [ 288 observers: [
294 GetObserver(), 289 GetObserver(),
295 - if (extraObservers != null) ...extraObservers, 290 + ...?navigatorObservers,
296 ], 291 ],
297 transitionDelegate: 292 transitionDelegate:
298 transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(), 293 transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
@@ -333,35 +328,24 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -333,35 +328,24 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
333 ), 328 ),
334 ); 329 );
335 } else { 330 } else {
336 - ///TODO: IMPLEMENT ROUTE NOT FOUND  
337 -  
338 - return Future.value();  
339 - }  
340 - }  
341 -  
342 - Future<void>? offAndToNamed(  
343 - String page, {  
344 - dynamic arguments,  
345 - int? id,  
346 - dynamic result,  
347 - Map<String, String>? parameters,  
348 - PopMode popMode = PopMode.History,  
349 - }) async {  
350 - if (parameters != null) {  
351 - final uri = Uri(path: page, queryParameters: parameters);  
352 - page = uri.toString(); 331 + await pushHistory(
  332 + GetNavConfig(
  333 + currentTreeBranch: [notFoundRoute],
  334 + location: notFoundRoute.name,
  335 + state: null, //TODO: persist state?
  336 + ),
  337 + );
353 } 338 }
354 -  
355 - await popRoute(result: result);  
356 - return toNamed(page, arguments: arguments, parameters: parameters);  
357 } 339 }
358 340
  341 + //pops the previous route (if there is one) and goes to new route
359 Future<void> offNamed( 342 Future<void> offNamed(
360 String page, { 343 String page, {
361 dynamic arguments, 344 dynamic arguments,
362 Map<String, String>? parameters, 345 Map<String, String>? parameters,
  346 + PopMode popMode = PopMode.History,
363 }) async { 347 }) async {
364 - history.removeLast(); 348 + await popRoute(popMode: popMode);
365 return toNamed(page, arguments: arguments, parameters: parameters); 349 return toNamed(page, arguments: arguments, parameters: parameters);
366 } 350 }
367 351
@@ -435,76 +419,3 @@ class GetDelegate extends RouterDelegate<GetNavConfig> @@ -435,76 +419,3 @@ class GetDelegate extends RouterDelegate<GetNavConfig>
435 return true; 419 return true;
436 } 420 }
437 } 421 }
438 -  
439 -class GetNavigator extends Navigator {  
440 - GetNavigator.onGenerateRoute({  
441 - GlobalKey<NavigatorState>? key,  
442 - bool Function(Route<dynamic>, dynamic)? onPopPage,  
443 - required List<GetPage> pages,  
444 - List<NavigatorObserver>? observers,  
445 - bool reportsRouteUpdateToEngine = false,  
446 - TransitionDelegate? transitionDelegate,  
447 - String? initialRoute,  
448 - }) : super(  
449 - //keys should be optional  
450 - key: key,  
451 - initialRoute: initialRoute,  
452 - onPopPage: onPopPage ??  
453 - (route, result) {  
454 - final didPop = route.didPop(result);  
455 - if (!didPop) {  
456 - return false;  
457 - }  
458 - return true;  
459 - },  
460 - onGenerateRoute: (settings) {  
461 - final selectedPageList =  
462 - pages.where((element) => element.name == settings.name);  
463 - if (selectedPageList.isNotEmpty) {  
464 - final selectedPage = selectedPageList.first;  
465 - return GetPageRoute(  
466 - page: selectedPage.page,  
467 - settings: settings,  
468 - );  
469 - }  
470 - },  
471 - reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,  
472 - pages: pages,  
473 - observers: [  
474 - // GetObserver(),  
475 - ...?observers,  
476 - ],  
477 - transitionDelegate:  
478 - transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),  
479 - );  
480 -  
481 - GetNavigator({  
482 - GlobalKey<NavigatorState>? key,  
483 - bool Function(Route<dynamic>, dynamic)? onPopPage,  
484 - required List<GetPage> pages,  
485 - List<NavigatorObserver>? observers,  
486 - bool reportsRouteUpdateToEngine = false,  
487 - TransitionDelegate? transitionDelegate,  
488 - String? initialRoute,  
489 - }) : super(  
490 - //keys should be optional  
491 - key: key,  
492 - initialRoute: initialRoute,  
493 - onPopPage: onPopPage ??  
494 - (route, result) {  
495 - final didPop = route.didPop(result);  
496 - if (!didPop) {  
497 - return false;  
498 - }  
499 - return true;  
500 - },  
501 - reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,  
502 - pages: pages,  
503 - observers: [  
504 - // GetObserver(),  
505 - ...?observers,  
506 - ],  
507 - transitionDelegate:  
508 - transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),  
509 - );  
510 -}  
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 2
3 import '../../../get.dart'; 3 import '../../../get.dart';
  4 +import 'get_navigator.dart';
4 import 'get_router_delegate.dart'; 5 import 'get_router_delegate.dart';
5 6
6 class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> 7 class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>