Jonny Borges

fix microtask and routes

@@ -7,14 +7,11 @@ import 'package:get/get.dart'; @@ -7,14 +7,11 @@ import 'package:get/get.dart';
7 // import 'package:get_test/get_test.dart'; 7 // import 'package:get_test/get_test.dart';
8 import 'package:matcher/matcher.dart' as m; 8 import 'package:matcher/matcher.dart' as m;
9 9
10 -  
11 import '../lib/pages/home/domain/adapters/repository_adapter.dart'; 10 import '../lib/pages/home/domain/adapters/repository_adapter.dart';
12 import '../lib/pages/home/domain/entity/cases_model.dart'; 11 import '../lib/pages/home/domain/entity/cases_model.dart';
13 import '../lib/pages/home/presentation/controllers/home_controller.dart'; 12 import '../lib/pages/home/presentation/controllers/home_controller.dart';
14 13
15 -  
16 class MockRepositorySuccess implements IHomeRepository { 14 class MockRepositorySuccess implements IHomeRepository {
17 -  
18 @override 15 @override
19 Future<CasesModel> getCases() async { 16 Future<CasesModel> getCases() async {
20 return CasesModel( 17 return CasesModel(
1 typedef ValueUpdater<T> = T Function(); 1 typedef ValueUpdater<T> = T Function();
  2 +
2 /// This allows a value of type T or T? 3 /// This allows a value of type T or T?
3 /// to be treated as a value of type T?. 4 /// to be treated as a value of type T?.
4 /// 5 ///
@@ -47,27 +47,6 @@ extension Inst on GetInterface { @@ -47,27 +47,6 @@ extension Inst on GetInterface {
47 // ); 47 // );
48 // } 48 // }
49 49
50 - /// async version of `Get.put()`.  
51 - /// Awaits for the resolution of the Future from `builder()` parameter and  
52 - /// stores the Instance returned.  
53 - Future<S> putAsync<S>(  
54 - AsyncInstanceBuilderCallback<S> builder, {  
55 - String? tag,  
56 - bool permanent = false,  
57 - }) async {  
58 - return put<S>(await builder(), tag: tag, permanent: permanent);  
59 - }  
60 -  
61 - /// Injects an instance `<S>` in memory to be globally accessible.  
62 - ///  
63 - /// No need to define the generic type `<S>` as it's inferred from  
64 - /// the [dependency]  
65 - ///  
66 - /// - [dependency] The Instance to be injected.  
67 - /// - [tag] optionally, use a [tag] as an "id" to create multiple records of  
68 - /// the same Type<[S]>  
69 - /// - [permanent] keeps the Instance in memory, not following  
70 - /// `Get.smartManagement` rules.  
71 S put<S>( 50 S put<S>(
72 S dependency, { 51 S dependency, {
73 String? tag, 52 String? tag,
@@ -544,9 +544,9 @@ extension GetNavigationExt on GetInterface { @@ -544,9 +544,9 @@ extension GetNavigationExt on GetInterface {
544 // return page; 544 // return page;
545 // } else if (page is Widget) { 545 // } else if (page is Widget) {
546 // Get.log( 546 // Get.log(
547 -// '''WARNING, consider using: "Get.$method(() => Page())" 547 +// '''WARNING, consider using: "Get.$method(() => Page())"
548 //instead of "Get.$method(Page())". 548 //instead of "Get.$method(Page())".
549 -// Using a widget function instead of a widget fully guarantees that the widget 549 +// Using a widget function instead of a widget fully guarantees that the widget
550 //and its controllers will be removed from memory when they are no longer used. 550 //and its controllers will be removed from memory when they are no longer used.
551 // '''); 551 // ''');
552 // return () => page; 552 // return () => page;
@@ -1253,8 +1253,6 @@ extension GetNavigationExt on GetInterface { @@ -1253,8 +1253,6 @@ extension GetNavigationExt on GetInterface {
1253 set parameters(Map<String, String?> newParameters) => 1253 set parameters(Map<String, String?> newParameters) =>
1254 _getxController.parameters = newParameters; 1254 _getxController.parameters = newParameters;
1255 1255
1256 -  
1257 -  
1258 bool get testMode => _getxController.testMode; 1256 bool get testMode => _getxController.testMode;
1259 set testMode(bool isTest) => _getxController.testMode = isTest; 1257 set testMode(bool isTest) => _getxController.testMode = isTest;
1260 1258
@@ -19,7 +19,8 @@ class GetInformationParser extends RouteInformationParser<RouteDecoder> { @@ -19,7 +19,8 @@ class GetInformationParser extends RouteInformationParser<RouteDecoder> {
19 if (location == '/') { 19 if (location == '/') {
20 //check if there is a corresponding page 20 //check if there is a corresponding page
21 //if not, relocate to initialRoute 21 //if not, relocate to initialRoute
22 - if (!(Get.rootController.routerDelegate as GetDelegate).registeredRoutes 22 + if (!(Get.rootController.routerDelegate as GetDelegate)
  23 + .registeredRoutes
23 .any((element) => element.name == '/')) { 24 .any((element) => element.name == '/')) {
24 location = initialRoute; 25 location = initialRoute;
25 } 26 }
@@ -45,7 +45,7 @@ class GetPage<T> extends Page<T> { @@ -45,7 +45,7 @@ class GetPage<T> extends Page<T> {
45 45
46 final List<GetPage> children; 46 final List<GetPage> children;
47 final List<GetMiddleware>? middlewares; 47 final List<GetMiddleware>? middlewares;
48 - // final PathDecoded path; 48 + final PathDecoded path;
49 final GetPage? unknownRoute; 49 final GetPage? unknownRoute;
50 final bool showCupertinoParallax; 50 final bool showCupertinoParallax;
51 51
@@ -82,7 +82,7 @@ class GetPage<T> extends Page<T> { @@ -82,7 +82,7 @@ class GetPage<T> extends Page<T> {
82 PreventDuplicateHandlingMode.reorderRoutes, 82 PreventDuplicateHandlingMode.reorderRoutes,
83 this.completer, 83 this.completer,
84 LocalKey? key, 84 LocalKey? key,
85 - }) : // path = _nameToRegex(name), 85 + }) : path = _nameToRegex(name),
86 assert(name.startsWith('/'), 86 assert(name.startsWith('/'),
87 'It is necessary to start route name [$name] with a slash: /$name'), 87 'It is necessary to start route name [$name] with a slash: /$name'),
88 super( 88 super(
@@ -168,26 +168,26 @@ class GetPage<T> extends Page<T> { @@ -168,26 +168,26 @@ class GetPage<T> extends Page<T> {
168 return _page; 168 return _page;
169 } 169 }
170 170
171 - // static PathDecoded _nameToRegex(String path) {  
172 - // var keys = <String?>[]; 171 + static PathDecoded _nameToRegex(String path) {
  172 + var keys = <String?>[];
173 173
174 - // String _replace(Match pattern) {  
175 - // var buffer = StringBuffer('(?:'); 174 + String _replace(Match pattern) {
  175 + var buffer = StringBuffer('(?:');
176 176
177 - // if (pattern[1] != null) buffer.write('.');  
178 - // buffer.write('([\\w%+-._~!\$&\'()*,;=:@]+))');  
179 - // if (pattern[3] != null) buffer.write('?'); 177 + if (pattern[1] != null) buffer.write('.');
  178 + buffer.write('([\\w%+-._~!\$&\'()*,;=:@]+))');
  179 + if (pattern[3] != null) buffer.write('?');
180 180
181 - // keys.add(pattern[2]);  
182 - // return "$buffer";  
183 - // } 181 + keys.add(pattern[2]);
  182 + return "$buffer";
  183 + }
184 184
185 - // var stringPath = '$path/?'  
186 - // .replaceAllMapped(RegExp(r'(\.)?:(\w+)(\?)?'), _replace)  
187 - // .replaceAll('//', '/'); 185 + var stringPath = '$path/?'
  186 + .replaceAllMapped(RegExp(r'(\.)?:(\w+)(\?)?'), _replace)
  187 + .replaceAll('//', '/');
188 188
189 - // return PathDecoded(RegExp('^$stringPath\$'), keys);  
190 - // } 189 + return PathDecoded(RegExp('^$stringPath\$'), keys);
  190 + }
191 191
192 @override 192 @override
193 bool operator ==(Object other) { 193 bool operator ==(Object other) {
@@ -205,20 +205,20 @@ class GetPage<T> extends Page<T> { @@ -205,20 +205,20 @@ class GetPage<T> extends Page<T> {
205 } 205 }
206 } 206 }
207 207
208 -// @immutable  
209 -// class PathDecoded {  
210 -// final RegExp regex;  
211 -// final List<String?> keys;  
212 -// const PathDecoded(this.regex, this.keys); 208 +@immutable
  209 +class PathDecoded {
  210 + final RegExp regex;
  211 + final List<String?> keys;
  212 + const PathDecoded(this.regex, this.keys);
213 213
214 -// @override  
215 -// int get hashCode => regex.hashCode; 214 + @override
  215 + int get hashCode => regex.hashCode;
216 216
217 -// @override  
218 -// bool operator ==(Object other) {  
219 -// if (identical(this, other)) return true; 217 + @override
  218 + bool operator ==(Object other) {
  219 + if (identical(this, other)) return true;
220 220
221 -// return other is PathDecoded &&  
222 -// other.regex == regex; // && listEquals(other.keys, keys);  
223 -// }  
224 -// } 221 + return other is PathDecoded &&
  222 + other.regex == regex; // && listEquals(other.keys, keys);
  223 + }
  224 +}
@@ -26,31 +26,28 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -26,31 +26,28 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
26 26
27 List<RouteDecoder> get activePages => _activePages; 27 List<RouteDecoder> get activePages => _activePages;
28 28
29 - final _routeTree = ParseRouteTree(); 29 + final _routeTree = ParseRouteTree(routes: []);
30 30
31 - final List<GetPage> _routes = [];  
32 -  
33 - List<GetPage> get registeredRoutes => _routes; 31 + List<GetPage> get registeredRoutes => _routeTree.routes;
34 32
35 void addPages(List<GetPage> getPages) { 33 void addPages(List<GetPage> getPages) {
36 - _routes.addRoutes(getPages); 34 + _routeTree.addRoutes(getPages);
37 } 35 }
38 36
39 void clearRouteTree() { 37 void clearRouteTree() {
40 - _routes.clear(); 38 + _routeTree.routes.clear();
41 } 39 }
42 40
43 void addPage(GetPage getPage) { 41 void addPage(GetPage getPage) {
44 - _routes.addRoute(getPage); 42 + _routeTree.addRoute(getPage);
45 } 43 }
46 44
47 void removePage(GetPage getPage) { 45 void removePage(GetPage getPage) {
48 - _routes.removeRoute(getPage); 46 + _routeTree.removeRoute(getPage);
49 } 47 }
50 48
51 - RouteDecoder? matchRoute(String name, {PageSettings? arguments}) {  
52 - final settings = _buildPageSettings(name, arguments);  
53 - return _getRouteDecoder(settings); 49 + RouteDecoder matchRoute(String name, {PageSettings? arguments}) {
  50 + return _routeTree.matchRoute(name, arguments: arguments);
54 } 51 }
55 52
56 // GlobalKey<NavigatorState> get navigatorKey => Get.key; 53 // GlobalKey<NavigatorState> get navigatorKey => Get.key;
@@ -141,9 +138,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -141,9 +138,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
141 } 138 }
142 139
143 Map<String, String> get parameters { 140 Map<String, String> get parameters {
144 - return currentConfiguration?.route?.parameters ??  
145 - // currentConfiguration?.pageSettings?.params ??  
146 - {}; 141 + return currentConfiguration?.pageSettings?.params ?? {};
147 } 142 }
148 143
149 PageSettings? get pageSettings { 144 PageSettings? get pageSettings {
@@ -365,7 +360,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -365,7 +360,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
365 }) async { 360 }) async {
366 routeName = _cleanRouteName("/${page.runtimeType}"); 361 routeName = _cleanRouteName("/${page.runtimeType}");
367 // if (preventDuplicateHandlingMode == 362 // if (preventDuplicateHandlingMode ==
368 - // PreventDuplicateHandlingMode.Recreate) { 363 + //PreventDuplicateHandlingMode.Recreate) {
369 // routeName = routeName + page.hashCode.toString(); 364 // routeName = routeName + page.hashCode.toString();
370 // } 365 // }
371 366
@@ -384,14 +379,14 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -384,14 +379,14 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
384 preventDuplicateHandlingMode: preventDuplicateHandlingMode, 379 preventDuplicateHandlingMode: preventDuplicateHandlingMode,
385 ); 380 );
386 381
387 - _routes.addRoute(getPage); 382 + _routeTree.addRoute(getPage);
388 final args = _buildPageSettings(routeName, arguments); 383 final args = _buildPageSettings(routeName, arguments);
389 final route = _getRouteDecoder<T>(args); 384 final route = _getRouteDecoder<T>(args);
390 final result = await _push<T>( 385 final result = await _push<T>(
391 route!, 386 route!,
392 rebuildStack: rebuildStack, 387 rebuildStack: rebuildStack,
393 ); 388 );
394 - _routes.removeRoute(getPage); 389 + _routeTree.removeRoute(getPage);
395 return result; 390 return result;
396 } 391 }
397 392
@@ -628,7 +623,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -628,7 +623,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
628 623
629 Future<T?> _replace<T>(PageSettings arguments, GetPage<T> page) async { 624 Future<T?> _replace<T>(PageSettings arguments, GetPage<T> page) async {
630 final index = _activePages.length > 1 ? _activePages.length - 1 : 0; 625 final index = _activePages.length > 1 ? _activePages.length - 1 : 0;
631 - _routes.addRoute(page); 626 + _routeTree.addRoute(page);
632 627
633 final activePage = _getRouteDecoder(arguments); 628 final activePage = _getRouteDecoder(arguments);
634 629
@@ -638,7 +633,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -638,7 +633,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
638 633
639 notifyListeners(); 634 notifyListeners();
640 final result = await activePage.route?.completer?.future as Future<T?>?; 635 final result = await activePage.route?.completer?.future as Future<T?>?;
641 - _routes.removeRoute(page); 636 + _routeTree.removeRoute(page);
642 637
643 return result; 638 return result;
644 } 639 }
@@ -683,8 +678,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -683,8 +678,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
683 page = uri.toString(); 678 page = uri.toString();
684 } 679 }
685 680
686 - final decoder =  
687 - _routeTree.matchRoute(registeredRoutes, page, arguments: arguments); 681 + final decoder = _routeTree.matchRoute(page, arguments: arguments);
688 final route = decoder.route; 682 final route = decoder.route;
689 if (route == null) return null; 683 if (route == null) return null;
690 684
@@ -707,7 +701,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -707,7 +701,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
707 completer: _activePages.isEmpty ? null : Completer(), 701 completer: _activePages.isEmpty ? null : Completer(),
708 arguments: arguments, 702 arguments: arguments,
709 parameters: parameters, 703 parameters: parameters,
710 - // key: ValueKey(arguments.name), 704 + key: ValueKey(arguments.name),
711 ); 705 );
712 706
713 return decoder; 707 return decoder;
@@ -13,10 +13,6 @@ class Dependencies { @@ -13,10 +13,6 @@ class Dependencies {
13 return find<S>(); 13 return find<S>();
14 } 14 }
15 15
16 - Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,  
17 - {String? tag, bool permanent = false}) async =>  
18 - Get.putAsync<S>(builder, tag: tag, permanent: permanent);  
19 -  
20 void create<S>(InstanceBuilderCallback<S> builder, 16 void create<S>(InstanceBuilderCallback<S> builder,
21 {String? tag, bool permanent = true}) => 17 {String? tag, bool permanent = true}) =>
22 Get.create<S>(builder, tag: tag, permanent: permanent); 18 Get.create<S>(builder, tag: tag, permanent: permanent);
1 -import 'dart:math';  
2 -  
3 import 'package:flutter/foundation.dart'; 1 import 'package:flutter/foundation.dart';
4 2
5 import '../../../route_manager.dart'; 3 import '../../../route_manager.dart';
@@ -18,11 +16,10 @@ class RouteDecoder { @@ -18,11 +16,10 @@ class RouteDecoder {
18 final args = PageSettings(uri); 16 final args = PageSettings(uri);
19 final decoder = (Get.rootController.routerDelegate as GetDelegate) 17 final decoder = (Get.rootController.routerDelegate as GetDelegate)
20 .matchRoute(location, arguments: args); 18 .matchRoute(location, arguments: args);
21 -  
22 - decoder!.route = decoder.route?.copy( 19 + decoder.route = decoder.route?.copy(
23 completer: null, 20 completer: null,
24 arguments: args, 21 arguments: args,
25 - parameters: decoder.parameters, 22 + parameters: args.params,
26 ); 23 );
27 return decoder; 24 return decoder;
28 } 25 }
@@ -81,62 +78,96 @@ class RouteDecoder { @@ -81,62 +78,96 @@ class RouteDecoder {
81 } 78 }
82 79
83 class ParseRouteTree { 80 class ParseRouteTree {
84 - RouteDecoder matchRoute(List<GetPage> routes, String name,  
85 - {PageSettings? arguments}) {  
86 - final args = arguments ?? PageSettings(Uri.parse(name));  
87 - final treeBranch = routes  
88 - .where((e) => RouteParser.hasMatch(  
89 - pushedRoute: name, routeName: e.name, withChildren: true))  
90 - .map((e) {  
91 - final parameters =  
92 - RouteParser.parse(pushedRoute: name, routeName: e.name).parameters;  
93 - final routeParams = e.parameters;  
94 - if (routeParams != null) {  
95 - parameters.addAll(routeParams);  
96 - }  
97 - if (args.params.isNotEmpty) {  
98 - parameters.addAll(args.params); 81 + ParseRouteTree({
  82 + required this.routes,
  83 + });
  84 +
  85 + final List<GetPage> routes;
  86 +
  87 + RouteDecoder matchRoute(String name, {PageSettings? arguments}) {
  88 + final uri = Uri.parse(name);
  89 + // /home/profile/123 => home,profile,123 => /,/home,/home/profile,/home/profile/123
  90 + final split = uri.path.split('/').where((element) => element.isNotEmpty);
  91 + var curPath = '/';
  92 + final cumulativePaths = <String>[
  93 + '/',
  94 + ];
  95 + for (var item in split) {
  96 + if (curPath.endsWith('/')) {
  97 + curPath += item;
  98 + } else {
  99 + curPath += '/$item';
99 } 100 }
  101 + cumulativePaths.add(curPath);
  102 + }
100 103
101 - args.params.clear();  
102 - args.params.addAll(parameters);  
103 -  
104 - return e.copy(  
105 - settings: args,  
106 - parameters: parameters, 104 + final treeBranch = cumulativePaths
  105 + .map((e) => MapEntry(e, _findRoute(e)))
  106 + .where((element) => element.value != null)
  107 +
  108 + ///Prevent page be disposed
  109 + .map((e) => MapEntry(e.key, e.value!.copy(key: ValueKey(e.key))))
  110 + .toList();
  111 +
  112 + final params = Map<String, String>.from(uri.queryParameters);
  113 + if (treeBranch.isNotEmpty) {
  114 + //route is found, do further parsing to get nested query params
  115 + final lastRoute = treeBranch.last;
  116 + final parsedParams = _parseParams(name, lastRoute.value.path);
  117 + if (parsedParams.isNotEmpty) {
  118 + params.addAll(parsedParams);
  119 + }
  120 + //copy parameters to all pages.
  121 + final mappedTreeBranch = treeBranch
  122 + .map(
  123 + (e) => e.value.copy(
  124 + parameters: {
  125 + if (e.value.parameters != null) ...e.value.parameters!,
  126 + ...params,
  127 + },
  128 + name: e.key,
  129 + ),
  130 + )
  131 + .toList();
  132 + arguments?.params.clear();
  133 + arguments?.params.addAll(params);
  134 + return RouteDecoder(
  135 + mappedTreeBranch,
  136 + arguments,
107 ); 137 );
108 - }).toList(); 138 + }
  139 +
  140 + arguments?.params.clear();
  141 + arguments?.params.addAll(params);
109 142
110 //route not found 143 //route not found
111 return RouteDecoder( 144 return RouteDecoder(
112 - treeBranch, 145 + treeBranch.map((e) => e.value).toList(),
113 arguments, 146 arguments,
114 ); 147 );
115 } 148 }
116 -}  
117 149
118 -extension FirstWhereOrNullExt<T> on List<GetPage<T>> {  
119 - void addRoutes(List<GetPage<T>> getPages) { 150 + void addRoutes<T>(List<GetPage<T>> getPages) {
120 for (final route in getPages) { 151 for (final route in getPages) {
121 addRoute(route); 152 addRoute(route);
122 } 153 }
123 } 154 }
124 155
125 - void removeRoutes(List<GetPage<T>> getPages) { 156 + void removeRoutes<T>(List<GetPage<T>> getPages) {
126 for (final route in getPages) { 157 for (final route in getPages) {
127 removeRoute(route); 158 removeRoute(route);
128 } 159 }
129 } 160 }
130 161
131 - void removeRoute(GetPage<T> route) {  
132 - remove(route); 162 + void removeRoute<T>(GetPage<T> route) {
  163 + routes.remove(route);
133 for (var page in _flattenPage(route)) { 164 for (var page in _flattenPage(route)) {
134 removeRoute(page); 165 removeRoute(page);
135 } 166 }
136 } 167 }
137 168
138 - void addRoute(GetPage<T> route) {  
139 - add(route); 169 + void addRoute<T>(GetPage<T> route) {
  170 + routes.add(route);
140 171
141 // Add Page children. 172 // Add Page children.
142 for (var page in _flattenPage(route)) { 173 for (var page in _flattenPage(route)) {
@@ -144,15 +175,14 @@ extension FirstWhereOrNullExt<T> on List<GetPage<T>> { @@ -144,15 +175,14 @@ extension FirstWhereOrNullExt<T> on List<GetPage<T>> {
144 } 175 }
145 } 176 }
146 177
147 - List<GetPage<T>> _flattenPage(GetPage<T> route) {  
148 - final result = <GetPage<T>>[]; 178 + List<GetPage> _flattenPage(GetPage route) {
  179 + final result = <GetPage>[];
149 if (route.children.isEmpty) { 180 if (route.children.isEmpty) {
150 return result; 181 return result;
151 } 182 }
152 183
153 - var parentPathOld = route.name; 184 + final parentPath = route.name;
154 for (var page in route.children) { 185 for (var page in route.children) {
155 - final parentPath2 = (parentPathOld + page.name).replaceAll(r'//', '/');  
156 // Add Parent middlewares to children 186 // Add Parent middlewares to children
157 final parentMiddlewares = [ 187 final parentMiddlewares = [
158 if (page.middlewares != null) ...page.middlewares!, 188 if (page.middlewares != null) ...page.middlewares!,
@@ -160,146 +190,71 @@ extension FirstWhereOrNullExt<T> on List<GetPage<T>> { @@ -160,146 +190,71 @@ extension FirstWhereOrNullExt<T> on List<GetPage<T>> {
160 ]; 190 ];
161 result.add( 191 result.add(
162 _addChild( 192 _addChild(
163 - page as GetPage<T>,  
164 - parentPath2, 193 + page,
  194 + parentPath,
165 parentMiddlewares, 195 parentMiddlewares,
166 ), 196 ),
167 ); 197 );
168 198
169 final children = _flattenPage(page); 199 final children = _flattenPage(page);
170 - // for (var child in children) {  
171 - // final parentPath = (parentPath2 + page.name).replaceAll(r'//', '/');  
172 - // result.add(_addChild(  
173 - // child,  
174 - // parentPath,  
175 - // [  
176 - // ...parentMiddlewares,  
177 - // if (child.middlewares != null) ...child.middlewares!,  
178 - // ],  
179 - // ));  
180 - // } 200 + for (var child in children) {
  201 + result.add(_addChild(
  202 + child,
  203 + parentPath,
  204 + [
  205 + ...parentMiddlewares,
  206 + if (child.middlewares != null) ...child.middlewares!,
  207 + ],
  208 + ));
  209 + }
181 } 210 }
182 return result; 211 return result;
183 } 212 }
184 213
185 /// Change the Path for a [GetPage] 214 /// Change the Path for a [GetPage]
186 - GetPage<T> _addChild(  
187 - GetPage<T> origin, String parentPath, List<GetMiddleware> middlewares) { 215 + GetPage _addChild(
  216 + GetPage origin, String parentPath, List<GetMiddleware> middlewares) {
188 return origin.copy( 217 return origin.copy(
189 middlewares: middlewares, 218 middlewares: middlewares,
190 - name: parentPath,  
191 - key: ValueKey(parentPath), 219 + name: (parentPath + origin.name).replaceAll(r'//', '/'),
  220 + // key:
192 ); 221 );
193 } 222 }
194 223
195 - // GetPage<T>? _findRoute(String name) {  
196 - // final value = firstWhereOrNull(  
197 - // (route) => route.path.regex.hasMatch(name),  
198 - // );  
199 -  
200 - // return value;  
201 - // }  
202 -} 224 + GetPage? _findRoute(String name) {
  225 + final value = routes.firstWhereOrNull(
  226 + (route) => route.path.regex.hasMatch(name),
  227 + );
203 228
204 -extension FirstWhereExt<T> on List<T> {  
205 - /// The first element satisfying [test], or `null` if there are none.  
206 - T? firstWhereOrNull(bool Function(T element) test) {  
207 - for (var element in this) {  
208 - if (test(element)) return element;  
209 - }  
210 - return null; 229 + return value;
211 } 230 }
212 -}  
213 -  
214 -class RouteParser {  
215 - static RouteParser parse({required String pushedRoute, required routeName}) {  
216 - final data = RouteParser(pushedRoute: pushedRoute, routeName: routeName);  
217 231
218 - final minLength =  
219 - min(data.originalPathSegments.length, data.newPathSegments.length);  
220 -  
221 - for (var i = 0; i < minLength; i++) {  
222 - final originalPathSegment = data.originalPathSegments[i];  
223 - final newPathSegment = Uri.parse(data.newPathSegments[i]);  
224 -  
225 - if (originalPathSegment.startsWith(':')) {  
226 - final key = originalPathSegment.replaceFirst(':', '');  
227 - data.parameters[key] = newPathSegment.toString();  
228 - data.matchingSegments.add(newPathSegment);  
229 - continue; 232 + Map<String, String> _parseParams(String path, PathDecoded routePath) {
  233 + final params = <String, String>{};
  234 + var idx = path.indexOf('?');
  235 + if (idx > -1) {
  236 + path = path.substring(0, idx);
  237 + final uri = Uri.tryParse(path);
  238 + if (uri != null) {
  239 + params.addAll(uri.queryParameters);
230 } 240 }
231 -  
232 - if (newPathSegment.path == originalPathSegment) {  
233 - data.matchingSegments.add(newPathSegment);  
234 - data.parameters.addAll(data.newRouteUri.queryParameters);  
235 -  
236 - continue;  
237 - } else {  
238 - break;  
239 - }  
240 - }  
241 -  
242 - return data;  
243 - }  
244 -  
245 - static bool hasMatch({  
246 - required String pushedRoute,  
247 - required routeName,  
248 - bool withChildren = false,  
249 - }) {  
250 - final data = RouteParser(pushedRoute: pushedRoute, routeName: routeName);  
251 - final matches = <bool>[];  
252 -  
253 - final minLength =  
254 - min(data.originalPathSegments.length, data.newPathSegments.length);  
255 -  
256 - if ((!withChildren &&  
257 - data.newPathSegments.length > data.originalPathSegments.length) ||  
258 - data.newPathSegments.length < data.originalPathSegments.length) {  
259 - matches.add(false);  
260 } 241 }
  242 + var paramsMatch = routePath.regex.firstMatch(path);
261 243
262 - for (var i = 0; i < minLength; i++) {  
263 - final originalPathSegment = data.originalPathSegments[i];  
264 - final newPathSegment = Uri.parse(data.newPathSegments[i]);  
265 -  
266 - if (originalPathSegment.startsWith(':')) {  
267 - matches.add(true);  
268 - continue;  
269 - }  
270 -  
271 - if (newPathSegment.path == originalPathSegment) {  
272 - matches.add(true);  
273 - continue;  
274 - } else {  
275 - matches.add(false);  
276 - break;  
277 - } 244 + for (var i = 0; i < routePath.keys.length; i++) {
  245 + var param = Uri.decodeQueryComponent(paramsMatch![i + 1]!);
  246 + params[routePath.keys[i]!] = param;
278 } 247 }
279 -  
280 - return matches.every((element) => element); 248 + return params;
281 } 249 }
  250 +}
282 251
283 - RouteParser({required String routeName, required String pushedRoute})  
284 - : _cleanRouteName = '/' +  
285 - routeName  
286 - .replaceAll(RegExp(r'^\s+|\s+$'), '')  
287 - .replaceAll(RegExp(r'^\/+|\/+$'), ''),  
288 - newRouteUri = Uri.parse(pushedRoute) {  
289 - originalRouteUri = Uri(path: _cleanRouteName); 252 +extension FirstWhereOrNullExt<T> on List<T> {
  253 + /// The first element satisfying [test], or `null` if there are none.
  254 + T? firstWhereOrNull(bool Function(T element) test) {
  255 + for (var element in this) {
  256 + if (test(element)) return element;
  257 + }
  258 + return null;
290 } 259 }
291 - late final Uri originalRouteUri;  
292 -  
293 - final Uri newRouteUri;  
294 - final Map<String, String> parameters = <String, String>{};  
295 - final List<Uri> matchingSegments = <Uri>[];  
296 - final String _cleanRouteName;  
297 -  
298 - List<String> get newPathSegments => newRouteUri.pathSegments;  
299 - List<String> get originalPathSegments => originalRouteUri.pathSegments;  
300 - String get matchingPath => '/' + matchingSegments.join('/');  
301 -  
302 - @override  
303 - String toString() =>  
304 - 'RouteParser(originalRouteUri: $originalRouteUri, newRouteUri: $newRouteUri, _cleanRouteName: $_cleanRouteName)';  
305 } 260 }
@@ -234,9 +234,8 @@ class PageRedirect { @@ -234,9 +234,8 @@ class PageRedirect {
234 if (settings == null && route != null) { 234 if (settings == null && route != null) {
235 settings = route; 235 settings = route;
236 } 236 }
237 - final match = context.navigation  
238 - .matchRoute((settings!.arguments as PageSettings).name);  
239 - Get.parameters = match!.parameters; 237 + final match = context.navigation.matchRoute(settings!.name!);
  238 + Get.parameters = match.parameters;
240 239
241 // No Match found 240 // No Match found
242 if (match.route == null) { 241 if (match.route == null) {
@@ -147,8 +147,7 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> { @@ -147,8 +147,7 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
147 return ret; 147 return ret;
148 }, 148 },
149 emptyPage: (delegate) => 149 emptyPage: (delegate) =>
150 - delegate.matchRoute(initialRoute)?.route ??  
151 - delegate.notFoundRoute, 150 + delegate.matchRoute(initialRoute).route ?? delegate.notFoundRoute,
152 key: Get.nestedKey(anchorRoute)?.navigatorKey, 151 key: Get.nestedKey(anchorRoute)?.navigatorKey,
153 delegate: delegate, 152 delegate: delegate,
154 ); 153 );
@@ -68,18 +68,6 @@ mixin StateMixin<T> on ListNotifier { @@ -68,18 +68,6 @@ mixin StateMixin<T> on ListNotifier {
68 if (status != this.status) { 68 if (status != this.status) {
69 this.status = status; 69 this.status = status;
70 } 70 }
71 - // var _canUpdate = false;  
72 - // if (status != null) {  
73 - // _status = status;  
74 - // _canUpdate = true;  
75 - // }  
76 - // if (newState != _value) {  
77 - // _value = newState;  
78 - // _canUpdate = true;  
79 - // }  
80 - // if (_canUpdate) {  
81 - // refresh();  
82 - // }  
83 } 71 }
84 72
85 void futurize(Future<T> Function() Function() body, 73 void futurize(Future<T> Function() Function() body,
1 -import 'dart:async';  
2 import 'dart:collection'; 1 import 'dart:collection';
3 2
4 import 'package:flutter/foundation.dart'; 3 import 'package:flutter/foundation.dart';
@@ -24,8 +23,8 @@ class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin; @@ -24,8 +23,8 @@ class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin;
24 mixin ListNotifierSingleMixin on Listenable { 23 mixin ListNotifierSingleMixin on Listenable {
25 List<GetStateUpdate>? _updaters = <GetStateUpdate>[]; 24 List<GetStateUpdate>? _updaters = <GetStateUpdate>[];
26 25
27 - int _version = 0;  
28 - int _microtaskVersion = 0; 26 + // final int _version = 0;
  27 + // final int _microtaskVersion = 0;
29 28
30 @override 29 @override
31 Disposer addListener(GetStateUpdate listener) { 30 Disposer addListener(GetStateUpdate listener) {
@@ -61,16 +60,18 @@ mixin ListNotifierSingleMixin on Listenable { @@ -61,16 +60,18 @@ mixin ListNotifierSingleMixin on Listenable {
61 } 60 }
62 61
63 void _notifyUpdate() { 62 void _notifyUpdate() {
64 - if (_microtaskVersion == _version) {  
65 - _microtaskVersion++;  
66 - scheduleMicrotask(() {  
67 - _version++;  
68 - _microtaskVersion = _version;  
69 - for (var element in _updaters!) {  
70 - element();  
71 - }  
72 - }); 63 + // if (_microtaskVersion == _version) {
  64 + // _microtaskVersion++;
  65 + // scheduleMicrotask(() {
  66 + // _version++;
  67 + // _microtaskVersion = _version;
  68 + final list = _updaters?.toList() ?? [];
  69 +
  70 + for (var element in list) {
  71 + element();
73 } 72 }
  73 + // });
  74 + // }
74 } 75 }
75 76
76 bool get isDisposed => _updaters == null; 77 bool get isDisposed => _updaters == null;
@@ -2,7 +2,6 @@ import 'dart:async'; @@ -2,7 +2,6 @@ import 'dart:async';
2 2
3 import 'package:flutter/widgets.dart'; 3 import 'package:flutter/widgets.dart';
4 4
5 -import '../../../get_core/src/typedefs.dart';  
6 import 'list_notifier.dart'; 5 import 'list_notifier.dart';
7 6
8 typedef ValueBuilderUpdateCallback<T> = void Function(T snapshot); 7 typedef ValueBuilderUpdateCallback<T> = void Function(T snapshot);
  1 +export 'src/equality/equality.dart';
1 export 'src/extensions/export.dart'; 2 export 'src/extensions/export.dart';
2 export 'src/get_utils/get_utils.dart'; 3 export 'src/get_utils/get_utils.dart';
3 export 'src/platform/platform.dart'; 4 export 'src/platform/platform.dart';
  1 +library equality;
  2 +
  3 +import 'dart:collection';
  4 +
  5 +mixin Equality {
  6 + List get props;
  7 +
  8 + @override
  9 + bool operator ==(dynamic other) {
  10 + return identical(this, other) ||
  11 + const DeepCollectionEquality().equals(props, other.props);
  12 + }
  13 +
  14 + @override
  15 + int get hashCode {
  16 + return runtimeType.hashCode ^ const DeepCollectionEquality().hash(props);
  17 + }
  18 +}
  19 +
  20 +const int _hashMask = 0x7fffffff;
  21 +
  22 +/// A generic equality relation on objects.
  23 +abstract class IEquality<E> {
  24 + const factory IEquality() = DefaultEquality<E>;
  25 +
  26 + /// Compare two elements for being equal.
  27 + ///
  28 + /// This should be a proper equality relation.
  29 + bool equals(E e1, E e2);
  30 +
  31 + /// Get a hashcode of an element.
  32 + ///
  33 + /// The hashcode should be compatible with [equals], so that if
  34 + /// `equals(a, b)` then `hash(a) == hash(b)`.
  35 + int hash(E e);
  36 +
  37 + /// Test whether an object is a valid argument to [equals] and [hash].
  38 + ///
  39 + /// Some implementations may be restricted to only work on specific types
  40 + /// of objects.
  41 + bool isValidKey(Object? o);
  42 +}
  43 +
  44 +class DefaultEquality<E> implements IEquality<E> {
  45 + const DefaultEquality();
  46 + @override
  47 + bool equals(Object? e1, Object? e2) => e1 == e2;
  48 + @override
  49 + int hash(Object? e) => e.hashCode;
  50 + @override
  51 + bool isValidKey(Object? o) => true;
  52 +}
  53 +
  54 +/// Equality of objects that compares only the identity of the objects.
  55 +class IdentityEquality<E> implements IEquality<E> {
  56 + const IdentityEquality();
  57 + @override
  58 + bool equals(E e1, E e2) => identical(e1, e2);
  59 + @override
  60 + int hash(E e) => identityHashCode(e);
  61 + @override
  62 + bool isValidKey(Object? o) => true;
  63 +}
  64 +
  65 +class DeepCollectionEquality implements IEquality {
  66 + final IEquality _base = const DefaultEquality<Never>();
  67 + final bool _unordered = false;
  68 + const DeepCollectionEquality();
  69 +
  70 + @override
  71 + bool equals(e1, e2) {
  72 + if (e1 is Set) {
  73 + return e2 is Set && SetEquality(this).equals(e1, e2);
  74 + }
  75 + if (e1 is Map) {
  76 + return e2 is Map && MapEquality(keys: this, values: this).equals(e1, e2);
  77 + }
  78 +
  79 + if (e1 is List) {
  80 + return e2 is List && ListEquality(this).equals(e1, e2);
  81 + }
  82 + if (e1 is Iterable) {
  83 + return e2 is Iterable && IterableEquality(this).equals(e1, e2);
  84 + }
  85 +
  86 + return _base.equals(e1, e2);
  87 + }
  88 +
  89 + @override
  90 + int hash(Object? o) {
  91 + if (o is Set) return SetEquality(this).hash(o);
  92 + if (o is Map) return MapEquality(keys: this, values: this).hash(o);
  93 + if (!_unordered) {
  94 + if (o is List) return ListEquality(this).hash(o);
  95 + if (o is Iterable) return IterableEquality(this).hash(o);
  96 + } else if (o is Iterable) {
  97 + return UnorderedIterableEquality(this).hash(o);
  98 + }
  99 + return _base.hash(o);
  100 + }
  101 +
  102 + @override
  103 + bool isValidKey(Object? o) =>
  104 + o is Iterable || o is Map || _base.isValidKey(o);
  105 +}
  106 +
  107 +/// Equality on lists.
  108 +///
  109 +/// Two lists are equal if they have the same length and their elements
  110 +/// at each index are equal.
  111 +class ListEquality<E> implements IEquality<List<E>> {
  112 + final IEquality<E> _elementEquality;
  113 + const ListEquality(
  114 + [IEquality<E> elementEquality = const DefaultEquality<Never>()])
  115 + : _elementEquality = elementEquality;
  116 +
  117 + @override
  118 + bool equals(List<E>? list1, List<E>? list2) {
  119 + if (identical(list1, list2)) return true;
  120 + if (list1 == null || list2 == null) return false;
  121 + var length = list1.length;
  122 + if (length != list2.length) return false;
  123 + for (var i = 0; i < length; i++) {
  124 + if (!_elementEquality.equals(list1[i], list2[i])) return false;
  125 + }
  126 + return true;
  127 + }
  128 +
  129 + @override
  130 + int hash(List<E>? list) {
  131 + if (list == null) return null.hashCode;
  132 + // Jenkins's one-at-a-time hash function.
  133 + // This code is almost identical to the one in IterableEquality, except
  134 + // that it uses indexing instead of iterating to get the elements.
  135 + var hash = 0;
  136 + for (var i = 0; i < list.length; i++) {
  137 + var c = _elementEquality.hash(list[i]);
  138 + hash = (hash + c) & _hashMask;
  139 + hash = (hash + (hash << 10)) & _hashMask;
  140 + hash ^= (hash >> 6);
  141 + }
  142 + hash = (hash + (hash << 3)) & _hashMask;
  143 + hash ^= (hash >> 11);
  144 + hash = (hash + (hash << 15)) & _hashMask;
  145 + return hash;
  146 + }
  147 +
  148 + @override
  149 + bool isValidKey(Object? o) => o is List<E>;
  150 +}
  151 +
  152 +/// Equality on maps.
  153 +///
  154 +/// Two maps are equal if they have the same number of entries, and if the
  155 +/// entries of the two maps are pairwise equal on both key and value.
  156 +class MapEquality<K, V> implements IEquality<Map<K, V>> {
  157 + final IEquality<K> _keyEquality;
  158 + final IEquality<V> _valueEquality;
  159 + const MapEquality(
  160 + {IEquality<K> keys = const DefaultEquality<Never>(),
  161 + IEquality<V> values = const DefaultEquality<Never>()})
  162 + : _keyEquality = keys,
  163 + _valueEquality = values;
  164 +
  165 + @override
  166 + bool equals(Map<K, V>? map1, Map<K, V>? map2) {
  167 + if (identical(map1, map2)) return true;
  168 + if (map1 == null || map2 == null) return false;
  169 + var length = map1.length;
  170 + if (length != map2.length) return false;
  171 + Map<_MapEntry, int> equalElementCounts = HashMap();
  172 + for (var key in map1.keys) {
  173 + var entry = _MapEntry(this, key, map1[key]);
  174 + var count = equalElementCounts[entry] ?? 0;
  175 + equalElementCounts[entry] = count + 1;
  176 + }
  177 + for (var key in map2.keys) {
  178 + var entry = _MapEntry(this, key, map2[key]);
  179 + var count = equalElementCounts[entry];
  180 + if (count == null || count == 0) return false;
  181 + equalElementCounts[entry] = count - 1;
  182 + }
  183 + return true;
  184 + }
  185 +
  186 + @override
  187 + int hash(Map<K, V>? map) {
  188 + if (map == null) return null.hashCode;
  189 + var hash = 0;
  190 + for (var key in map.keys) {
  191 + var keyHash = _keyEquality.hash(key);
  192 + var valueHash = _valueEquality.hash(map[key] as V);
  193 + hash = (hash + 3 * keyHash + 7 * valueHash) & _hashMask;
  194 + }
  195 + hash = (hash + (hash << 3)) & _hashMask;
  196 + hash ^= (hash >> 11);
  197 + hash = (hash + (hash << 15)) & _hashMask;
  198 + return hash;
  199 + }
  200 +
  201 + @override
  202 + bool isValidKey(Object? o) => o is Map<K, V>;
  203 +}
  204 +
  205 +class _MapEntry {
  206 + final MapEquality equality;
  207 + final Object? key;
  208 + final Object? value;
  209 + _MapEntry(this.equality, this.key, this.value);
  210 +
  211 + @override
  212 + int get hashCode =>
  213 + (3 * equality._keyEquality.hash(key) +
  214 + 7 * equality._valueEquality.hash(value)) &
  215 + _hashMask;
  216 +
  217 + @override
  218 + bool operator ==(Object other) =>
  219 + other is _MapEntry &&
  220 + equality._keyEquality.equals(key, other.key) &&
  221 + equality._valueEquality.equals(value, other.value);
  222 +}
  223 +
  224 +/// Equality on iterables.
  225 +///
  226 +/// Two iterables are equal if they have the same elements in the same order.
  227 +class IterableEquality<E> implements IEquality<Iterable<E>> {
  228 + final IEquality<E?> _elementEquality;
  229 + const IterableEquality(
  230 + [IEquality<E> elementEquality = const DefaultEquality<Never>()])
  231 + : _elementEquality = elementEquality;
  232 +
  233 + @override
  234 + bool equals(Iterable<E>? elements1, Iterable<E>? elements2) {
  235 + if (identical(elements1, elements2)) return true;
  236 + if (elements1 == null || elements2 == null) return false;
  237 + var it1 = elements1.iterator;
  238 + var it2 = elements2.iterator;
  239 + while (true) {
  240 + var hasNext = it1.moveNext();
  241 + if (hasNext != it2.moveNext()) return false;
  242 + if (!hasNext) return true;
  243 + if (!_elementEquality.equals(it1.current, it2.current)) return false;
  244 + }
  245 + }
  246 +
  247 + @override
  248 + int hash(Iterable<E>? elements) {
  249 + if (elements == null) return null.hashCode;
  250 + // Jenkins's one-at-a-time hash function.
  251 + var hash = 0;
  252 + for (var element in elements) {
  253 + var c = _elementEquality.hash(element);
  254 + hash = (hash + c) & _hashMask;
  255 + hash = (hash + (hash << 10)) & _hashMask;
  256 + hash ^= (hash >> 6);
  257 + }
  258 + hash = (hash + (hash << 3)) & _hashMask;
  259 + hash ^= (hash >> 11);
  260 + hash = (hash + (hash << 15)) & _hashMask;
  261 + return hash;
  262 + }
  263 +
  264 + @override
  265 + bool isValidKey(Object? o) => o is Iterable<E>;
  266 +}
  267 +
  268 +/// Equality of sets.
  269 +///
  270 +/// Two sets are considered equal if they have the same number of elements,
  271 +/// and the elements of one set can be paired with the elements
  272 +/// of the other set, so that each pair are equal.
  273 +class SetEquality<E> extends _UnorderedEquality<E, Set<E>> {
  274 + const SetEquality(
  275 + [IEquality<E> elementEquality = const DefaultEquality<Never>()])
  276 + : super(elementEquality);
  277 +
  278 + @override
  279 + bool isValidKey(Object? o) => o is Set<E>;
  280 +}
  281 +
  282 +abstract class _UnorderedEquality<E, T extends Iterable<E>>
  283 + implements IEquality<T> {
  284 + final IEquality<E> _elementEquality;
  285 +
  286 + const _UnorderedEquality(this._elementEquality);
  287 +
  288 + @override
  289 + bool equals(T? elements1, T? elements2) {
  290 + if (identical(elements1, elements2)) return true;
  291 + if (elements1 == null || elements2 == null) return false;
  292 + var counts = HashMap<E, int>(
  293 + equals: _elementEquality.equals,
  294 + hashCode: _elementEquality.hash,
  295 + isValidKey: _elementEquality.isValidKey);
  296 + var length = 0;
  297 + for (var e in elements1) {
  298 + var count = counts[e] ?? 0;
  299 + counts[e] = count + 1;
  300 + length++;
  301 + }
  302 + for (var e in elements2) {
  303 + var count = counts[e];
  304 + if (count == null || count == 0) return false;
  305 + counts[e] = count - 1;
  306 + length--;
  307 + }
  308 + return length == 0;
  309 + }
  310 +
  311 + @override
  312 + int hash(T? elements) {
  313 + if (elements == null) return null.hashCode;
  314 + var hash = 0;
  315 + for (E element in elements) {
  316 + var c = _elementEquality.hash(element);
  317 + hash = (hash + c) & _hashMask;
  318 + }
  319 + hash = (hash + (hash << 3)) & _hashMask;
  320 + hash ^= (hash >> 11);
  321 + hash = (hash + (hash << 15)) & _hashMask;
  322 + return hash;
  323 + }
  324 +}
  325 +
  326 +/// Equality of the elements of two iterables without considering order.
  327 +///
  328 +/// Two iterables are considered equal if they have the same number of elements,
  329 +/// and the elements of one set can be paired with the elements
  330 +/// of the other iterable, so that each pair are equal.
  331 +class UnorderedIterableEquality<E> extends _UnorderedEquality<E, Iterable<E>> {
  332 + const UnorderedIterableEquality(
  333 + [IEquality<E> elementEquality = const DefaultEquality<Never>()])
  334 + : super(elementEquality);
  335 +
  336 + @override
  337 + bool isValidKey(Object? o) => o is Iterable<E>;
  338 +}
@@ -29,12 +29,7 @@ class Api implements Service { @@ -29,12 +29,7 @@ class Api implements Service {
29 } 29 }
30 30
31 void main() { 31 void main() {
32 - test('Get.putAsync test', () async {  
33 - await Get.putAsync<String>(Mock.test);  
34 - expect('test', Get.find<String>());  
35 - Get.reset();  
36 - });  
37 - 32 + TestWidgetsFlutterBinding.ensureInitialized();
38 test('Get.put test', () async { 33 test('Get.put test', () async {
39 final instance = Get.put<Controller>(Controller()); 34 final instance = Get.put<Controller>(Controller());
40 expect(instance, Get.find<Controller>()); 35 expect(instance, Get.find<Controller>());
@@ -4,7 +4,7 @@ import 'package:get/get.dart'; @@ -4,7 +4,7 @@ import 'package:get/get.dart';
4 4
5 void main() { 5 void main() {
6 test('Parse Page with children', () { 6 test('Parse Page with children', () {
7 - // final testParams = {'hi': 'value'}; 7 + final testParams = {'hi': 'value'};
8 final pageTree = GetPage( 8 final pageTree = GetPage(
9 name: '/city', 9 name: '/city',
10 page: () => Container(), 10 page: () => Container(),
@@ -40,7 +40,7 @@ void main() { @@ -40,7 +40,7 @@ void main() {
40 name: '/pen', 40 name: '/pen',
41 transition: Transition.cupertino, 41 transition: Transition.cupertino,
42 page: () => Container(), 42 page: () => Container(),
43 - // parameters: testParams, 43 + parameters: testParams,
44 ), 44 ),
45 GetPage( 45 GetPage(
46 name: '/paper', 46 name: '/paper',
@@ -58,63 +58,20 @@ void main() { @@ -58,63 +58,20 @@ void main() {
58 ), 58 ),
59 ], 59 ],
60 ); 60 );
61 - final routes = <GetPage>[];  
62 - final tree = ParseRouteTree();  
63 61
64 - routes.addRoute(pageTree); 62 + final tree = ParseRouteTree(routes: <GetPage>[]);
  63 +
  64 + tree.addRoute(pageTree);
65 65
66 // tree.addRoute(pageTree); 66 // tree.addRoute(pageTree);
67 final searchRoute = '/city/work/office/pen'; 67 final searchRoute = '/city/work/office/pen';
68 - final match = tree.matchRoute(routes, searchRoute); 68 + final match = tree.matchRoute(searchRoute);
69 expect(match, isNotNull); 69 expect(match, isNotNull);
70 expect(match.route!.name, searchRoute); 70 expect(match.route!.name, searchRoute);
71 - final testRouteParam = match.parameters;  
72 - print(testRouteParam);  
73 - // for (final tParam in testParams.entries) {  
74 - // expect(testRouteParam[tParam.key], tParam.value);  
75 - // }  
76 - });  
77 -  
78 - test('Parse ', () {  
79 - final testParams = {'hi': 'value'};  
80 - final pageTree = GetPage(  
81 - name: '/city',  
82 - parameters: testParams,  
83 - page: () => Container(),  
84 - );  
85 - final routes = <GetPage>[];  
86 - final tree = ParseRouteTree();  
87 -  
88 - routes.addRoute(pageTree);  
89 -  
90 - // tree.addRoute(pageTree);  
91 - final searchRoute = '/city?abc=1234';  
92 -  
93 - final hasMatch = RouteParser.hasMatch(  
94 - pushedRoute: searchRoute, routeName: pageTree.name);  
95 - expect(hasMatch, true);  
96 -  
97 - final parsed =  
98 - RouteParser.parse(pushedRoute: searchRoute, routeName: pageTree.name);  
99 -  
100 - final match = tree.matchRoute(routes, searchRoute);  
101 - expect(match, isNotNull);  
102 - expect(parsed.newRouteUri.toString(), searchRoute);  
103 - final testRouteParam = match.route?.parameters;  
104 - 71 + final testRouteParam = match.route!.parameters!;
105 for (final tParam in testParams.entries) { 72 for (final tParam in testParams.entries) {
106 - expect(testRouteParam![tParam.key], tParam.value); 73 + expect(testRouteParam[tParam.key], tParam.value);
107 } 74 }
108 -  
109 - final hasMatch2 = RouteParser.hasMatch(  
110 - pushedRoute: '/home/123/ana', routeName: '/home/:id/:name');  
111 - print(hasMatch2);  
112 - expect(hasMatch2, true);  
113 -  
114 - final parsed2 = RouteParser.parse(  
115 - pushedRoute: '/home/123/ana/profile',  
116 - routeName: '/home/:id/:name/profile');  
117 - print(parsed2.parameters);  
118 }); 75 });
119 76
120 test('Parse Page without children', () { 77 test('Parse Page without children', () {
@@ -157,14 +114,14 @@ void main() { @@ -157,14 +114,14 @@ void main() {
157 transition: Transition.rightToLeft), 114 transition: Transition.rightToLeft),
158 ]; 115 ];
159 116
160 - final tree = ParseRouteTree(); 117 + final tree = ParseRouteTree(routes: pageTree);
161 118
162 // for (var p in pageTree) { 119 // for (var p in pageTree) {
163 // tree.addRoute(p); 120 // tree.addRoute(p);
164 // } 121 // }
165 122
166 final searchRoute = '/city/work/office/pen'; 123 final searchRoute = '/city/work/office/pen';
167 - final match = tree.matchRoute(pageTree, searchRoute); 124 + final match = tree.matchRoute(searchRoute);
168 expect(match, isNotNull); 125 expect(match, isNotNull);
169 expect(match.route!.name, searchRoute); 126 expect(match.route!.name, searchRoute);
170 }); 127 });
@@ -182,8 +139,6 @@ void main() { @@ -182,8 +139,6 @@ void main() {
182 ], 139 ],
183 )); 140 ));
184 141
185 - print(Get.parameters);  
186 -  
187 expect(Get.parameters['name'], 'juan'); 142 expect(Get.parameters['name'], 'juan');
188 143
189 Get.toNamed('/second/1234'); 144 Get.toNamed('/second/1234');
@@ -3,8 +3,8 @@ import 'package:flutter_test/flutter_test.dart'; @@ -3,8 +3,8 @@ import 'package:flutter_test/flutter_test.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
4 4
5 void main() { 5 void main() {
6 - final controller = Get.put(Controller());  
7 testWidgets("GetxController smoke test", (tester) async { 6 testWidgets("GetxController smoke test", (tester) async {
  7 + final controller = Get.put(Controller());
8 await tester.pumpWidget( 8 await tester.pumpWidget(
9 MaterialApp( 9 MaterialApp(
10 home: Column( 10 home: Column(