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
81 additions
and
15 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) { | 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. | ||
| 51 | _removeDependencyByRoute(disposed); | 52 | _removeDependencyByRoute(disposed); | 
| 52 | - } | ||
| 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