Adjustments in context Navigations methods.
- Add `String? routeName` to the following context Navigation methods: `to`, `off`, `offAll`. To enforce the usage of `RouteSettings` and avoid issues with GetxController not being disposed properly, and also to keep control and consistency in the methods. - modified `RouterReportManager.reportRouteDispose` to make it work with context Routes. - added extension_navigator.dart `_cleanRouteName` to remove unwanted format where the Route name is taking from the page Type in context Routes. - added `GetStringUtils.paramCase` to support potentially a clean url name for the context Routes. So `/()=> MyView` can become `/my-view' - added `GetUtils.snakeCase` and `GetUtils.paramCase` to support `_cleanRouteName` url Strings (currently deactivated.) Base code taken from the ReCase package and proper credit attributed in comments.
Showing
4 changed files
with
82 additions
and
16 deletions
@@ -539,6 +539,7 @@ extension GetNavigation on GetInterface { | @@ -539,6 +539,7 @@ extension GetNavigation on GetInterface { | ||
539 | Curve? curve, | 539 | Curve? curve, |
540 | Duration? duration, | 540 | Duration? duration, |
541 | int? id, | 541 | int? id, |
542 | + String? routeName, | ||
542 | bool fullscreenDialog = false, | 543 | bool fullscreenDialog = false, |
543 | dynamic arguments, | 544 | dynamic arguments, |
544 | Bindings? binding, | 545 | Bindings? binding, |
@@ -546,18 +547,20 @@ extension GetNavigation on GetInterface { | @@ -546,18 +547,20 @@ extension GetNavigation on GetInterface { | ||
546 | bool? popGesture, | 547 | bool? popGesture, |
547 | double Function(BuildContext context)? gestureWidth, | 548 | double Function(BuildContext context)? gestureWidth, |
548 | }) { | 549 | }) { |
549 | - var routeName = "/${page.runtimeType.toString()}"; | 550 | + // var routeName = "/${page.runtimeType}"; |
551 | + routeName ??= "/${page.runtimeType}"; | ||
552 | + routeName = _cleanRouteName(routeName); | ||
550 | if (preventDuplicates && routeName == currentRoute) { | 553 | if (preventDuplicates && routeName == currentRoute) { |
551 | return null; | 554 | return null; |
552 | } | 555 | } |
553 | return global(id).currentState?.push<T>( | 556 | return global(id).currentState?.push<T>( |
554 | GetPageRoute<T>( | 557 | GetPageRoute<T>( |
555 | opaque: opaque ?? true, | 558 | opaque: opaque ?? true, |
556 | - page: _resolve(page, 'to'), | 559 | + page: _resolvePage(page, 'to'), |
557 | routeName: routeName, | 560 | routeName: routeName, |
558 | gestureWidth: gestureWidth, | 561 | gestureWidth: gestureWidth, |
559 | settings: RouteSettings( | 562 | settings: RouteSettings( |
560 | - // name: forceRouteName ? '${a.runtimeType}' : '', | 563 | + name: routeName, |
561 | arguments: arguments, | 564 | arguments: arguments, |
562 | ), | 565 | ), |
563 | popGesture: popGesture ?? defaultPopGesture, | 566 | popGesture: popGesture ?? defaultPopGesture, |
@@ -570,7 +573,7 @@ extension GetNavigation on GetInterface { | @@ -570,7 +573,7 @@ extension GetNavigation on GetInterface { | ||
570 | ); | 573 | ); |
571 | } | 574 | } |
572 | 575 | ||
573 | - GetPageBuilder _resolve(dynamic page, String method) { | 576 | + GetPageBuilder _resolvePage(dynamic page, String method) { |
574 | if (page is GetPageBuilder) { | 577 | if (page is GetPageBuilder) { |
575 | return page; | 578 | return page; |
576 | } else if (page is Widget) { | 579 | } else if (page is Widget) { |
@@ -909,6 +912,7 @@ you can only use widgets and widget functions here'''; | @@ -909,6 +912,7 @@ you can only use widgets and widget functions here'''; | ||
909 | Curve? curve, | 912 | Curve? curve, |
910 | bool? popGesture, | 913 | bool? popGesture, |
911 | int? id, | 914 | int? id, |
915 | + String? routeName, | ||
912 | dynamic arguments, | 916 | dynamic arguments, |
913 | Bindings? binding, | 917 | Bindings? binding, |
914 | bool fullscreenDialog = false, | 918 | bool fullscreenDialog = false, |
@@ -916,16 +920,20 @@ you can only use widgets and widget functions here'''; | @@ -916,16 +920,20 @@ you can only use widgets and widget functions here'''; | ||
916 | Duration? duration, | 920 | Duration? duration, |
917 | double Function(BuildContext context)? gestureWidth, | 921 | double Function(BuildContext context)? gestureWidth, |
918 | }) { | 922 | }) { |
919 | - var routeName = "/${page.runtimeType.toString()}"; | 923 | + routeName ??= "/${page.runtimeType.toString()}"; |
924 | + routeName = _cleanRouteName(routeName); | ||
920 | if (preventDuplicates && routeName == currentRoute) { | 925 | if (preventDuplicates && routeName == currentRoute) { |
921 | return null; | 926 | return null; |
922 | } | 927 | } |
923 | return global(id).currentState?.pushReplacement(GetPageRoute( | 928 | return global(id).currentState?.pushReplacement(GetPageRoute( |
924 | opaque: opaque, | 929 | opaque: opaque, |
925 | gestureWidth: gestureWidth, | 930 | gestureWidth: gestureWidth, |
926 | - page: _resolve(page, 'off'), | 931 | + page: _resolvePage(page, 'off'), |
927 | binding: binding, | 932 | binding: binding, |
928 | - settings: RouteSettings(arguments: arguments), | 933 | + settings: RouteSettings( |
934 | + arguments: arguments, | ||
935 | + name: routeName, | ||
936 | + ), | ||
929 | routeName: routeName, | 937 | routeName: routeName, |
930 | fullscreenDialog: fullscreenDialog, | 938 | fullscreenDialog: fullscreenDialog, |
931 | popGesture: popGesture ?? defaultPopGesture, | 939 | popGesture: popGesture ?? defaultPopGesture, |
@@ -934,7 +942,6 @@ you can only use widgets and widget functions here'''; | @@ -934,7 +942,6 @@ you can only use widgets and widget functions here'''; | ||
934 | transitionDuration: duration ?? defaultTransitionDuration)); | 942 | transitionDuration: duration ?? defaultTransitionDuration)); |
935 | } | 943 | } |
936 | 944 | ||
937 | - /// **Navigation.pushAndRemoveUntil()** shortcut .<br><br> | ||
938 | /// | 945 | /// |
939 | /// Push a `page` and pop several pages in the stack | 946 | /// Push a `page` and pop several pages in the stack |
940 | /// until [predicate] returns true. [predicate] is optional | 947 | /// until [predicate] returns true. [predicate] is optional |
@@ -971,6 +978,7 @@ you can only use widgets and widget functions here'''; | @@ -971,6 +978,7 @@ you can only use widgets and widget functions here'''; | ||
971 | bool opaque = false, | 978 | bool opaque = false, |
972 | bool? popGesture, | 979 | bool? popGesture, |
973 | int? id, | 980 | int? id, |
981 | + String? routeName, | ||
974 | dynamic arguments, | 982 | dynamic arguments, |
975 | Bindings? binding, | 983 | Bindings? binding, |
976 | bool fullscreenDialog = false, | 984 | bool fullscreenDialog = false, |
@@ -979,16 +987,19 @@ you can only use widgets and widget functions here'''; | @@ -979,16 +987,19 @@ you can only use widgets and widget functions here'''; | ||
979 | Duration? duration, | 987 | Duration? duration, |
980 | double Function(BuildContext context)? gestureWidth, | 988 | double Function(BuildContext context)? gestureWidth, |
981 | }) { | 989 | }) { |
982 | - var routeName = "/${page.runtimeType.toString()}"; | ||
983 | - | 990 | + routeName ??= "/${page.runtimeType.toString()}"; |
991 | + routeName = _cleanRouteName(routeName); | ||
984 | return global(id).currentState?.pushAndRemoveUntil<T>( | 992 | return global(id).currentState?.pushAndRemoveUntil<T>( |
985 | GetPageRoute<T>( | 993 | GetPageRoute<T>( |
986 | opaque: opaque, | 994 | opaque: opaque, |
987 | popGesture: popGesture ?? defaultPopGesture, | 995 | popGesture: popGesture ?? defaultPopGesture, |
988 | - page: _resolve(page, 'offAll'), | 996 | + page: _resolvePage(page, 'offAll'), |
989 | binding: binding, | 997 | binding: binding, |
990 | gestureWidth: gestureWidth, | 998 | gestureWidth: gestureWidth, |
991 | - settings: RouteSettings(arguments: arguments), | 999 | + settings: RouteSettings( |
1000 | + name: routeName, | ||
1001 | + arguments: arguments, | ||
1002 | + ), | ||
992 | fullscreenDialog: fullscreenDialog, | 1003 | fullscreenDialog: fullscreenDialog, |
993 | routeName: routeName, | 1004 | routeName: routeName, |
994 | transition: transition ?? defaultTransition, | 1005 | transition: transition ?? defaultTransition, |
@@ -998,6 +1009,21 @@ you can only use widgets and widget functions here'''; | @@ -998,6 +1009,21 @@ you can only use widgets and widget functions here'''; | ||
998 | predicate ?? (route) => false); | 1009 | predicate ?? (route) => false); |
999 | } | 1010 | } |
1000 | 1011 | ||
1012 | + /// Takes a route [name] String generated by [to], [off], [offAll] | ||
1013 | + /// (and similar context navigation methods), cleans the extra chars and | ||
1014 | + /// accommodates the format. | ||
1015 | + /// TODO: check for a more "appealing" URL naming convention. | ||
1016 | + /// `() => MyHomeScreenView` becomes `/my-home-screen-view`. | ||
1017 | + String _cleanRouteName(String name) { | ||
1018 | + name = name.replaceAll('() => ', ''); | ||
1019 | + /// uncommonent for URL styling. | ||
1020 | + // name = name.paramCase!; | ||
1021 | + if (!name.startsWith('/')) { | ||
1022 | + name = '/$name'; | ||
1023 | + } | ||
1024 | + return Uri.tryParse(name)?.toString() ?? name; | ||
1025 | + } | ||
1026 | + | ||
1001 | /// change default config of Get | 1027 | /// change default config of Get |
1002 | void config( | 1028 | void config( |
1003 | {bool? enableLog, | 1029 | {bool? enableLog, |
@@ -46,10 +46,10 @@ class RouterReportManager<T> { | @@ -46,10 +46,10 @@ class RouterReportManager<T> { | ||
46 | static void reportRouteDispose(Route disposed) { | 46 | static void reportRouteDispose(Route disposed) { |
47 | if (Get.smartManagement != SmartManagement.onlyBuilder) { | 47 | if (Get.smartManagement != SmartManagement.onlyBuilder) { |
48 | WidgetsBinding.instance!.addPostFrameCallback((_) { | 48 | WidgetsBinding.instance!.addPostFrameCallback((_) { |
49 | - ///TODO: Is necessary this comparator? | ||
50 | - if (_current != disposed) { | ||
51 | - _removeDependencyByRoute(disposed); | ||
52 | - } | 49 | + ///TODO: Check if it's necessary to compare _current != disposed |
50 | + ///Adding it breaks the context Navigation logic, | ||
51 | + ///as it resolves by Route name. | ||
52 | + _removeDependencyByRoute(disposed); | ||
53 | }); | 53 | }); |
54 | } | 54 | } |
55 | } | 55 | } |
@@ -77,6 +77,8 @@ extension GetStringUtils on String { | @@ -77,6 +77,8 @@ extension GetStringUtils on String { | ||
77 | 77 | ||
78 | String? get camelCase => GetUtils.camelCase(this); | 78 | String? get camelCase => GetUtils.camelCase(this); |
79 | 79 | ||
80 | + String? get paramCase => GetUtils.paramCase(this); | ||
81 | + | ||
80 | String numericOnly({bool firstWordOnly = false}) => | 82 | String numericOnly({bool firstWordOnly = false}) => |
81 | GetUtils.numericOnly(this, firstWordOnly: firstWordOnly); | 83 | GetUtils.numericOnly(this, firstWordOnly: firstWordOnly); |
82 | 84 |
@@ -551,6 +551,44 @@ class GetUtils { | @@ -551,6 +551,44 @@ class GetUtils { | ||
551 | return newString[0].toLowerCase() + newString.substring(1); | 551 | return newString[0].toLowerCase() + newString.substring(1); |
552 | } | 552 | } |
553 | 553 | ||
554 | + /// credits to "ReCase" package. | ||
555 | + static final RegExp _upperAlphaRegex = RegExp(r'[A-Z]'); | ||
556 | + static final _symbolSet = {' ', '.', '/', '_', '\\', '-'}; | ||
557 | + static List<String> _groupIntoWords(String text) { | ||
558 | + var sb = StringBuffer(); | ||
559 | + var words = <String>[]; | ||
560 | + var isAllCaps = text.toUpperCase() == text; | ||
561 | + | ||
562 | + for (var i = 0; i < text.length; i++) { | ||
563 | + var char = text[i]; | ||
564 | + var nextChar = i + 1 == text.length ? null : text[i + 1]; | ||
565 | + if (_symbolSet.contains(char)) { | ||
566 | + continue; | ||
567 | + } | ||
568 | + sb.write(char); | ||
569 | + var isEndOfWord = nextChar == null || | ||
570 | + (_upperAlphaRegex.hasMatch(nextChar) && !isAllCaps) || | ||
571 | + _symbolSet.contains(nextChar); | ||
572 | + if (isEndOfWord) { | ||
573 | + words.add('$sb'); | ||
574 | + sb.clear(); | ||
575 | + } | ||
576 | + } | ||
577 | + return words; | ||
578 | + } | ||
579 | + | ||
580 | + /// snake_case | ||
581 | + static String? snakeCase(String? text, {String separator = '_'}) { | ||
582 | + if (isNullOrBlank(text)!) { | ||
583 | + return null; | ||
584 | + } | ||
585 | + return _groupIntoWords(text!) | ||
586 | + .map((word) => word.toLowerCase()).join(separator); | ||
587 | + } | ||
588 | + | ||
589 | + /// param-case | ||
590 | + static String? paramCase(String? text) => snakeCase(text, separator: '-'); | ||
591 | + | ||
554 | /// Extract numeric value of string | 592 | /// Extract numeric value of string |
555 | /// Example: OTP 12312 27/04/2020 => 1231227042020ß | 593 | /// Example: OTP 12312 27/04/2020 => 1231227042020ß |
556 | /// If firstword only is true, then the example return is "12312" | 594 | /// If firstword only is true, then the example return is "12312" |
-
Please register or login to post a comment