Jonny Borges

refactor root and fix errors

@@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
34 /android/ 34 /android/
35 /web/ 35 /web/
36 /macos/ 36 /macos/
  37 +/windows/
37 38
38 # Web related 39 # Web related
39 lib/generated_plugin_registrant.dart 40 lib/generated_plugin_registrant.dart
1 # This file tracks properties of this Flutter project. 1 # This file tracks properties of this Flutter project.
2 # Used by Flutter tool to assess capabilities and perform upgrades etc. 2 # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 # 3 #
4 -# This file should be version controlled and should not be manually edited. 4 +# This file should be version controlled.
5 5
6 version: 6 version:
7 - revision: 7c6f9dd2396dfe7deb6fd11edc12c10786490083  
8 - channel: dev 7 + revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  8 + channel: stable
9 9
10 project_type: app 10 project_type: app
  11 +
  12 +# Tracks metadata for the flutter migrate command
  13 +migration:
  14 + platforms:
  15 + - platform: root
  16 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  17 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  18 + - platform: android
  19 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  20 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  21 + - platform: ios
  22 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  23 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  24 + - platform: linux
  25 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  26 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  27 + - platform: macos
  28 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  29 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  30 + - platform: web
  31 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  32 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  33 + - platform: windows
  34 + create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  35 + base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
  36 +
  37 + # User provided section
  38 +
  39 + # List of Local paths (relative to this file) that should be
  40 + # ignored by the migrate tool.
  41 + #
  42 + # Files that are not part of the templates will be ignored by default.
  43 + unmanaged_files:
  44 + - 'lib/main.dart'
  45 + - 'ios/Runner.xcodeproj/project.pbxproj'
  1 +# This file configures the analyzer, which statically analyzes Dart code to
  2 +# check for errors, warnings, and lints.
  3 +#
  4 +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
  5 +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
  6 +# invoked from the command line by running `flutter analyze`.
  7 +
  8 +# The following line activates a set of recommended lints for Flutter apps,
  9 +# packages, and plugins designed to encourage good coding practices.
  10 +include: package:flutter_lints/flutter.yaml
  11 +
  12 +linter:
  13 + # The lint rules applied to this project can be customized in the
  14 + # section below to disable rules from the `package:flutter_lints/flutter.yaml`
  15 + # included above or to enable additional rules. A list of all available lints
  16 + # and their documentation is published at
  17 + # https://dart-lang.github.io/linter/lints/index.html.
  18 + #
  19 + # Instead of disabling a lint rule for the entire project in the
  20 + # section below, it can also be suppressed for a single line of code
  21 + # or a specific dart file by using the `// ignore: name_of_lint` and
  22 + # `// ignore_for_file: name_of_lint` syntax on the line or in the file
  23 + # producing the lint.
  24 + rules:
  25 + # avoid_print: false # Uncomment to disable the `avoid_print` rule
  26 + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
  27 +
  28 +# Additional information about this file can be found at
  29 +# https://dart.dev/guides/language/analysis-options
@@ -27,6 +27,24 @@ class InstanceInfo { @@ -27,6 +27,24 @@ class InstanceInfo {
27 } 27 }
28 } 28 }
29 29
  30 +extension ResetInstance on GetInterface {
  31 + /// Clears all registered instances (and/or tags).
  32 + /// Even the persistent ones.
  33 + /// This should be used at the end or tearDown of unit tests.
  34 + ///
  35 + /// `clearFactory` clears the callbacks registered by [lazyPut]
  36 + /// `clearRouteBindings` clears Instances associated with routes.
  37 + ///
  38 + bool resetInstance({bool clearRouteBindings = true}) {
  39 + // if (clearFactory) _factory.clear();
  40 + // deleteAll(force: true);
  41 + if (clearRouteBindings) RouterReportManager.instance.clearRouteKeys();
  42 + Inst._singl.clear();
  43 +
  44 + return true;
  45 + }
  46 +}
  47 +
30 extension Inst on GetInterface { 48 extension Inst on GetInterface {
31 T call<T>() => find<T>(); 49 T call<T>() => find<T>();
32 50
@@ -311,22 +329,6 @@ extension Inst on GetInterface { @@ -311,22 +329,6 @@ extension Inst on GetInterface {
311 return name == null ? type.toString() : type.toString() + name; 329 return name == null ? type.toString() : type.toString() + name;
312 } 330 }
313 331
314 - /// Clears all registered instances (and/or tags).  
315 - /// Even the persistent ones.  
316 - /// This should be used at the end or tearDown of unit tests.  
317 - ///  
318 - /// `clearFactory` clears the callbacks registered by [lazyPut]  
319 - /// `clearRouteBindings` clears Instances associated with routes.  
320 - ///  
321 - bool resetInstance({bool clearRouteBindings = true}) {  
322 - // if (clearFactory) _factory.clear();  
323 - // deleteAll(force: true);  
324 - if (clearRouteBindings) RouterReportManager.instance.clearRouteKeys();  
325 - _singl.clear();  
326 -  
327 - return true;  
328 - }  
329 -  
330 /// Delete registered Class Instance [S] (or [tag]) and, closes any open 332 /// Delete registered Class Instance [S] (or [tag]) and, closes any open
331 /// controllers `DisposableInterface`, cleans up the memory 333 /// controllers `DisposableInterface`, cleans up the memory
332 /// 334 ///
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; @@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
4 4
5 import '../../get.dart'; 5 import '../../get.dart';
6 import 'dialog/dialog_route.dart'; 6 import 'dialog/dialog_route.dart';
  7 +import 'root/get_root.dart';
7 8
8 /// It replaces the Flutter Navigator, but needs no context. 9 /// It replaces the Flutter Navigator, but needs no context.
9 /// You can to use navigator.push(YourRoute()) rather 10 /// You can to use navigator.push(YourRoute()) rather
@@ -219,8 +220,8 @@ extension ExtensionDialog on GetInterface { @@ -219,8 +220,8 @@ extension ExtensionDialog on GetInterface {
219 ), 220 ),
220 child: Text( 221 child: Text(
221 textConfirm ?? "Ok", 222 textConfirm ?? "Ok",
222 - style:  
223 - TextStyle(color: confirmTextColor ?? theme.backgroundColor), 223 + style: TextStyle(
  224 + color: confirmTextColor ?? theme.colorScheme.background),
224 ), 225 ),
225 onPressed: () { 226 onPressed: () {
226 onConfirm?.call(); 227 onConfirm?.call();
@@ -1009,36 +1010,36 @@ extension GetNavigationExt on GetInterface { @@ -1009,36 +1010,36 @@ extension GetNavigationExt on GetInterface {
1009 } 1010 }
1010 return Uri.tryParse(name)?.toString() ?? name; 1011 return Uri.tryParse(name)?.toString() ?? name;
1011 } 1012 }
  1013 + //TODO: Deprecated
  1014 + // /// change default config of Get
  1015 + // void config(
  1016 + // {bool? enableLog,
  1017 + // LogWriterCallback? logWriterCallback,
  1018 + // bool? defaultPopGesture,
  1019 + // bool? defaultOpaqueRoute,
  1020 + // Duration? defaultDurationTransition,
  1021 + // bool? defaultGlobalState,
  1022 + // Transition? defaultTransition}) {
  1023 + // if (enableLog != null) {
  1024 + // Get.isLogEnable = enableLog;
  1025 + // }
  1026 + // if (logWriterCallback != null) {
  1027 + // Get.log = logWriterCallback;
  1028 + // }
  1029 + // if (defaultPopGesture != null) {
  1030 + // _getxController.defaultPopGesture = defaultPopGesture;
  1031 + // }
  1032 + // if (defaultOpaqueRoute != null) {
  1033 + // _getxController.defaultOpaqueRoute = defaultOpaqueRoute;
  1034 + // }
  1035 + // if (defaultTransition != null) {
  1036 + // _getxController.defaultTransition = defaultTransition;
  1037 + // }
1012 1038
1013 - /// change default config of Get  
1014 - void config(  
1015 - {bool? enableLog,  
1016 - LogWriterCallback? logWriterCallback,  
1017 - bool? defaultPopGesture,  
1018 - bool? defaultOpaqueRoute,  
1019 - Duration? defaultDurationTransition,  
1020 - bool? defaultGlobalState,  
1021 - Transition? defaultTransition}) {  
1022 - if (enableLog != null) {  
1023 - Get.isLogEnable = enableLog;  
1024 - }  
1025 - if (logWriterCallback != null) {  
1026 - Get.log = logWriterCallback;  
1027 - }  
1028 - if (defaultPopGesture != null) {  
1029 - _getxController.defaultPopGesture = defaultPopGesture;  
1030 - }  
1031 - if (defaultOpaqueRoute != null) {  
1032 - _getxController.defaultOpaqueRoute = defaultOpaqueRoute;  
1033 - }  
1034 - if (defaultTransition != null) {  
1035 - _getxController.defaultTransition = defaultTransition;  
1036 - }  
1037 -  
1038 - if (defaultDurationTransition != null) {  
1039 - _getxController.defaultTransitionDuration = defaultDurationTransition;  
1040 - }  
1041 - } 1039 + // if (defaultDurationTransition != null) {
  1040 + // _getxController.defaultTransitionDuration = defaultDurationTransition;
  1041 + // }
  1042 + // }
1042 1043
1043 Future<void> updateLocale(Locale l) async { 1044 Future<void> updateLocale(Locale l) async {
1044 Get.locale = l; 1045 Get.locale = l;
@@ -1062,22 +1063,22 @@ extension GetNavigationExt on GetInterface { @@ -1062,22 +1063,22 @@ extension GetNavigationExt on GetInterface {
1062 await engine.performReassemble(); 1063 await engine.performReassemble();
1063 } 1064 }
1064 1065
1065 - void appUpdate() => _getxController.update(); 1066 + void appUpdate() => rootController.update();
1066 1067
1067 void changeTheme(ThemeData theme) { 1068 void changeTheme(ThemeData theme) {
1068 - _getxController.setTheme(theme); 1069 + rootController.setTheme(theme);
1069 } 1070 }
1070 1071
1071 void changeThemeMode(ThemeMode themeMode) { 1072 void changeThemeMode(ThemeMode themeMode) {
1072 - _getxController.setThemeMode(themeMode); 1073 + rootController.setThemeMode(themeMode);
1073 } 1074 }
1074 1075
1075 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { 1076 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
1076 - return _getxController.addKey(newKey); 1077 + return rootController.addKey(newKey);
1077 } 1078 }
1078 1079
1079 GetDelegate? nestedKey(String? key) { 1080 GetDelegate? nestedKey(String? key) {
1080 - return _getxController.nestedKey(key); 1081 + return rootController.nestedKey(key);
1081 } 1082 }
1082 1083
1083 GetDelegate searchDelegate(dynamic k) { 1084 GetDelegate searchDelegate(dynamic k) {
@@ -1106,7 +1107,7 @@ extension GetNavigationExt on GetInterface { @@ -1106,7 +1107,7 @@ extension GetNavigationExt on GetInterface {
1106 1107
1107 /// give current arguments 1108 /// give current arguments
1108 //dynamic get arguments => routing.args; 1109 //dynamic get arguments => routing.args;
1109 - dynamic get arguments => _getxController.rootDelegate.arguments(); 1110 + dynamic get arguments => rootController.rootDelegate.arguments();
1110 1111
1111 /// give name from current route 1112 /// give name from current route
1112 String get currentRoute => routing.current; 1113 String get currentRoute => routing.current;
@@ -1219,11 +1220,13 @@ extension GetNavigationExt on GetInterface { @@ -1219,11 +1220,13 @@ extension GetNavigationExt on GetInterface {
1219 // /// give access to Immutable MediaQuery.of(context).size.width 1220 // /// give access to Immutable MediaQuery.of(context).size.width
1220 // double get width => MediaQuery.of(context).size.width; 1221 // double get width => MediaQuery.of(context).size.width;
1221 1222
1222 - GlobalKey<NavigatorState> get key => _getxController.key; 1223 + GlobalKey<NavigatorState> get key => rootController.key;
  1224 +
  1225 + Map<dynamic, GetDelegate> get keys => rootController.keys;
1223 1226
1224 - Map<dynamic, GetDelegate> get keys => _getxController.keys; 1227 + GetRootState get rootController => GetRootState.controller;
1225 1228
1226 - GetMaterialController get rootController => _getxController; 1229 + ConfigData get _getxController => GetRootState.controller.config;
1227 1230
1228 bool get defaultPopGesture => _getxController.defaultPopGesture; 1231 bool get defaultPopGesture => _getxController.defaultPopGesture;
1229 bool get defaultOpaqueRoute => _getxController.defaultOpaqueRoute; 1232 bool get defaultOpaqueRoute => _getxController.defaultOpaqueRoute;
@@ -1246,20 +1249,18 @@ extension GetNavigationExt on GetInterface { @@ -1246,20 +1249,18 @@ extension GetNavigationExt on GetInterface {
1246 1249
1247 Routing get routing => _getxController.routing; 1250 Routing get routing => _getxController.routing;
1248 1251
1249 - Map<String, String?> get parameters =>  
1250 - _getxController.rootDelegate.parameters;  
1251 set parameters(Map<String, String?> newParameters) => 1252 set parameters(Map<String, String?> newParameters) =>
1252 - _getxController.parameters = newParameters; 1253 + rootController.parameters = newParameters;
  1254 +
  1255 + set testMode(bool isTest) => rootController.testMode = isTest;
1253 1256
1254 bool get testMode => _getxController.testMode; 1257 bool get testMode => _getxController.testMode;
1255 - set testMode(bool isTest) => _getxController.testMode = isTest; 1258 +
  1259 + Map<String, String?> get parameters => rootController.rootDelegate.parameters;
1256 1260
1257 /// Casts the stored router delegate to a desired type 1261 /// Casts the stored router delegate to a desired type
1258 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => 1262 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() =>
1259 _getxController.routerDelegate as TDelegate?; 1263 _getxController.routerDelegate as TDelegate?;
1260 -  
1261 - static final GetMaterialController _getxController =  
1262 - Get.find<GetMaterialController>();  
1263 } 1264 }
1264 1265
1265 extension OverlayExt on GetInterface { 1266 extension OverlayExt on GetInterface {
@@ -7,11 +7,10 @@ import '../../../get_instance/get_instance.dart'; @@ -7,11 +7,10 @@ import '../../../get_instance/get_instance.dart';
7 import '../../../get_state_manager/get_state_manager.dart'; 7 import '../../../get_state_manager/get_state_manager.dart';
8 import '../../../get_utils/get_utils.dart'; 8 import '../../../get_utils/get_utils.dart';
9 import '../../get_navigation.dart'; 9 import '../../get_navigation.dart';
10 -import '../router_report.dart'; 10 +import 'get_root.dart';
11 11
12 class GetCupertinoApp extends StatelessWidget { 12 class GetCupertinoApp extends StatelessWidget {
13 final GlobalKey<NavigatorState>? navigatorKey; 13 final GlobalKey<NavigatorState>? navigatorKey;
14 -  
15 final Widget? home; 14 final Widget? home;
16 final Map<String, WidgetBuilder>? routes; 15 final Map<String, WidgetBuilder>? routes;
17 final String? initialRoute; 16 final String? initialRoute;
@@ -197,11 +196,8 @@ class GetCupertinoApp extends StatelessWidget { @@ -197,11 +196,8 @@ class GetCupertinoApp extends StatelessWidget {
197 196
198 @override 197 @override
199 Widget build(BuildContext context) { 198 Widget build(BuildContext context) {
200 - return Binds(  
201 - binds: [  
202 - Bind.lazyPut<GetMaterialController>(  
203 - () => GetMaterialController(  
204 - ConfigData( 199 + return GetRoot(
  200 + config: ConfigData(
205 backButtonDispatcher: backButtonDispatcher, 201 backButtonDispatcher: backButtonDispatcher,
206 binds: binds, 202 binds: binds,
207 customTransition: customTransition, 203 customTransition: customTransition,
@@ -219,8 +215,6 @@ class GetCupertinoApp extends StatelessWidget { @@ -219,8 +215,6 @@ class GetCupertinoApp extends StatelessWidget {
219 onDispose: onDispose, 215 onDispose: onDispose,
220 onInit: onInit, 216 onInit: onInit,
221 onReady: onReady, 217 onReady: onReady,
222 - opaqueRoute: opaqueRoute,  
223 - popGesture: popGesture,  
224 routeInformationParser: routeInformationParser, 218 routeInformationParser: routeInformationParser,
225 routeInformationProvider: routeInformationProvider, 219 routeInformationProvider: routeInformationProvider,
226 routerDelegate: routerDelegate, 220 routerDelegate: routerDelegate,
@@ -232,23 +226,14 @@ class GetCupertinoApp extends StatelessWidget { @@ -232,23 +226,14 @@ class GetCupertinoApp extends StatelessWidget {
232 translationsKeys: translationsKeys, 226 translationsKeys: translationsKeys,
233 unknownRoute: unknownRoute, 227 unknownRoute: unknownRoute,
234 ), 228 ),
235 - ),  
236 - onClose: () {  
237 - Get.clearTranslations();  
238 - RouterReportManager.dispose();  
239 - Get.resetInstance(clearRouteBindings: true);  
240 - },  
241 - ),  
242 - ...binds,  
243 - ],  
244 child: Builder(builder: (context) { 229 child: Builder(builder: (context) {
245 - final controller = context.listen<GetMaterialController>(); 230 + final controller = GetRoot.of(context);
246 return CupertinoApp.router( 231 return CupertinoApp.router(
247 - routerDelegate: controller.routerDelegate,  
248 - routeInformationParser: controller.routeInformationParser, 232 + routerDelegate: controller.config.routerDelegate,
  233 + routeInformationParser: controller.config.routeInformationParser,
249 backButtonDispatcher: backButtonDispatcher, 234 backButtonDispatcher: backButtonDispatcher,
250 routeInformationProvider: routeInformationProvider, 235 routeInformationProvider: routeInformationProvider,
251 - key: controller.unikey, 236 + key: controller.config.unikey,
252 builder: (context, child) => Directionality( 237 builder: (context, child) => Directionality(
253 textDirection: textDirection ?? 238 textDirection: textDirection ??
254 (rtlLanguages.contains(Get.locale?.languageCode) 239 (rtlLanguages.contains(Get.locale?.languageCode)
1 import 'package:flutter/foundation.dart'; 1 import 'package:flutter/foundation.dart';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
  3 +import 'package:get/instance_manager.dart';
3 4
4 -import '../../../get_core/get_core.dart';  
5 -import '../../../get_instance/get_instance.dart';  
6 import '../../../get_state_manager/get_state_manager.dart'; 5 import '../../../get_state_manager/get_state_manager.dart';
7 import '../../../get_utils/get_utils.dart'; 6 import '../../../get_utils/get_utils.dart';
8 import '../../get_navigation.dart'; 7 import '../../get_navigation.dart';
9 -import '../router_report.dart'; 8 +import 'get_root.dart';
10 9
11 class GetMaterialApp extends StatelessWidget { 10 class GetMaterialApp extends StatelessWidget {
12 final GlobalKey<NavigatorState>? navigatorKey; 11 final GlobalKey<NavigatorState>? navigatorKey;
@@ -193,11 +192,8 @@ class GetMaterialApp extends StatelessWidget { @@ -193,11 +192,8 @@ class GetMaterialApp extends StatelessWidget {
193 192
194 @override 193 @override
195 Widget build(BuildContext context) { 194 Widget build(BuildContext context) {
196 - return Binds(  
197 - binds: [  
198 - Bind.lazyPut<GetMaterialController>(  
199 - () => GetMaterialController(  
200 - ConfigData( 195 + return GetRoot(
  196 + config: ConfigData(
201 backButtonDispatcher: backButtonDispatcher, 197 backButtonDispatcher: backButtonDispatcher,
202 binds: binds, 198 binds: binds,
203 customTransition: customTransition, 199 customTransition: customTransition,
@@ -215,8 +211,6 @@ class GetMaterialApp extends StatelessWidget { @@ -215,8 +211,6 @@ class GetMaterialApp extends StatelessWidget {
215 onDispose: onDispose, 211 onDispose: onDispose,
216 onInit: onInit, 212 onInit: onInit,
217 onReady: onReady, 213 onReady: onReady,
218 - opaqueRoute: opaqueRoute,  
219 - popGesture: popGesture,  
220 routeInformationParser: routeInformationParser, 214 routeInformationParser: routeInformationParser,
221 routeInformationProvider: routeInformationProvider, 215 routeInformationProvider: routeInformationProvider,
222 routerDelegate: routerDelegate, 216 routerDelegate: routerDelegate,
@@ -227,24 +221,32 @@ class GetMaterialApp extends StatelessWidget { @@ -227,24 +221,32 @@ class GetMaterialApp extends StatelessWidget {
227 translations: translations, 221 translations: translations,
228 translationsKeys: translationsKeys, 222 translationsKeys: translationsKeys,
229 unknownRoute: unknownRoute, 223 unknownRoute: unknownRoute,
  224 + theme: theme,
  225 + darkTheme: darkTheme,
  226 + themeMode: themeMode,
230 ), 227 ),
231 - ),  
232 - onClose: () {  
233 - Get.clearTranslations();  
234 - RouterReportManager.dispose();  
235 - Get.resetInstance(clearRouteBindings: true);  
236 - },  
237 - ),  
238 - ...binds,  
239 - ], 228 + // binds: [
  229 + // Bind.lazyPut<GetMaterialController>(
  230 + // () => GetMaterialController(
  231 +
  232 + // ),
  233 + // onClose: () {
  234 + // Get.clearTranslations();
  235 + // RouterReportManager.dispose();
  236 + // Get.resetInstance(clearRouteBindings: true);
  237 + // },
  238 + // ),
  239 + // ...binds,
  240 + // ],
240 child: Builder(builder: (context) { 241 child: Builder(builder: (context) {
241 - final controller = context.listen<GetMaterialController>(); 242 + final controller = GetRoot.of(context);
  243 + print('ROUTERRRR ${controller.config.routerDelegate}');
242 return MaterialApp.router( 244 return MaterialApp.router(
243 - routerDelegate: controller.routerDelegate,  
244 - routeInformationParser: controller.routeInformationParser, 245 + routerDelegate: controller.config.routerDelegate,
  246 + routeInformationParser: controller.config.routeInformationParser,
245 backButtonDispatcher: backButtonDispatcher, 247 backButtonDispatcher: backButtonDispatcher,
246 routeInformationProvider: routeInformationProvider, 248 routeInformationProvider: routeInformationProvider,
247 - key: controller.unikey, 249 + key: controller.config.unikey,
248 builder: (context, child) => Directionality( 250 builder: (context, child) => Directionality(
249 textDirection: textDirection ?? 251 textDirection: textDirection ??
250 (rtlLanguages.contains(Get.locale?.languageCode) 252 (rtlLanguages.contains(Get.locale?.languageCode)
@@ -257,15 +259,13 @@ class GetMaterialApp extends StatelessWidget { @@ -257,15 +259,13 @@ class GetMaterialApp extends StatelessWidget {
257 title: title, 259 title: title,
258 onGenerateTitle: onGenerateTitle, 260 onGenerateTitle: onGenerateTitle,
259 color: color, 261 color: color,
260 - theme: controller.theme ?? theme ?? ThemeData.fallback(),  
261 - darkTheme: controller.darkTheme ??  
262 - darkTheme ??  
263 - theme ?? 262 + theme: controller.config.theme ?? ThemeData.fallback(),
  263 + darkTheme: controller.config.darkTheme ??
  264 + controller.config.theme ??
264 ThemeData.fallback(), 265 ThemeData.fallback(),
265 - themeMode: controller.themeMode ?? themeMode, 266 + themeMode: controller.config.themeMode,
266 locale: Get.locale ?? locale, 267 locale: Get.locale ?? locale,
267 - scaffoldMessengerKey:  
268 - scaffoldMessengerKey ?? controller.scaffoldMessengerKey, 268 + scaffoldMessengerKey: controller.config.scaffoldMessengerKey,
269 localizationsDelegates: localizationsDelegates, 269 localizationsDelegates: localizationsDelegates,
270 localeListResolutionCallback: localeListResolutionCallback, 270 localeListResolutionCallback: localeListResolutionCallback,
271 localeResolutionCallback: localeResolutionCallback, 271 localeResolutionCallback: localeResolutionCallback,
  1 +import 'package:flutter/foundation.dart';
  2 +import 'package:flutter/material.dart';
  3 +
  4 +import '../../../get.dart';
  5 +import '../router_report.dart';
  6 +
  7 +class ConfigData {
  8 + final ValueChanged<Routing?>? routingCallback;
  9 + final Transition? defaultTransition;
  10 + final VoidCallback? onInit;
  11 + final VoidCallback? onReady;
  12 + final VoidCallback? onDispose;
  13 + final bool? enableLog;
  14 + final LogWriterCallback? logWriterCallback;
  15 + final SmartManagement smartManagement;
  16 + final List<Bind> binds;
  17 + final Duration? transitionDuration;
  18 + final bool? defaultGlobalState;
  19 + final List<GetPage>? getPages;
  20 + final GetPage? unknownRoute;
  21 + final RouteInformationProvider? routeInformationProvider;
  22 + final RouteInformationParser<Object>? routeInformationParser;
  23 + final RouterDelegate<Object>? routerDelegate;
  24 + final BackButtonDispatcher? backButtonDispatcher;
  25 + final List<NavigatorObserver>? navigatorObservers;
  26 + final GlobalKey<NavigatorState>? navigatorKey;
  27 + final GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey;
  28 + final Map<String, Map<String, String>>? translationsKeys;
  29 + final Translations? translations;
  30 + final Locale? locale;
  31 + final Locale? fallbackLocale;
  32 + final String? initialRoute;
  33 + final CustomTransition? customTransition;
  34 + final Widget? home;
  35 + final bool testMode;
  36 + final Key? unikey;
  37 + final ThemeData? theme;
  38 + final ThemeData? darkTheme;
  39 + final ThemeMode? themeMode;
  40 + final bool defaultPopGesture;
  41 + final bool defaultOpaqueRoute;
  42 + final Duration defaultTransitionDuration;
  43 + final Curve defaultTransitionCurve;
  44 + final Curve defaultDialogTransitionCurve;
  45 + final Duration defaultDialogTransitionDuration;
  46 + final Routing routing;
  47 + final Map<String, String?> parameters;
  48 +
  49 + ConfigData({
  50 + required this.routingCallback,
  51 + required this.defaultTransition,
  52 + required this.onInit,
  53 + required this.onReady,
  54 + required this.onDispose,
  55 + required this.enableLog,
  56 + required this.logWriterCallback,
  57 + required this.smartManagement,
  58 + required this.binds,
  59 + required this.transitionDuration,
  60 + required this.defaultGlobalState,
  61 + required this.getPages,
  62 + required this.unknownRoute,
  63 + required this.routeInformationProvider,
  64 + required this.routeInformationParser,
  65 + required this.routerDelegate,
  66 + required this.backButtonDispatcher,
  67 + required this.navigatorObservers,
  68 + required this.navigatorKey,
  69 + required this.scaffoldMessengerKey,
  70 + required this.translationsKeys,
  71 + required this.translations,
  72 + required this.locale,
  73 + required this.fallbackLocale,
  74 + required this.initialRoute,
  75 + required this.customTransition,
  76 + required this.home,
  77 + this.theme,
  78 + this.darkTheme,
  79 + this.themeMode,
  80 + this.unikey,
  81 + this.testMode = false,
  82 + this.defaultOpaqueRoute = true,
  83 + this.defaultTransitionDuration = const Duration(milliseconds: 300),
  84 + this.defaultTransitionCurve = Curves.easeOutQuad,
  85 + this.defaultDialogTransitionCurve = Curves.easeOutQuad,
  86 + this.defaultDialogTransitionDuration = const Duration(milliseconds: 300),
  87 + this.parameters = const {},
  88 + Routing? routing,
  89 + bool? defaultPopGesture,
  90 + }) : defaultPopGesture = defaultPopGesture ?? GetPlatform.isIOS,
  91 + routing = routing ?? Routing();
  92 +
  93 + ConfigData copyWith({
  94 + ValueChanged<Routing?>? routingCallback,
  95 + Transition? defaultTransition,
  96 + VoidCallback? onInit,
  97 + VoidCallback? onReady,
  98 + VoidCallback? onDispose,
  99 + bool? enableLog,
  100 + LogWriterCallback? logWriterCallback,
  101 + SmartManagement? smartManagement,
  102 + List<Bind>? binds,
  103 + Duration? transitionDuration,
  104 + bool? defaultGlobalState,
  105 + List<GetPage>? getPages,
  106 + GetPage? unknownRoute,
  107 + RouteInformationProvider? routeInformationProvider,
  108 + RouteInformationParser<Object>? routeInformationParser,
  109 + RouterDelegate<Object>? routerDelegate,
  110 + BackButtonDispatcher? backButtonDispatcher,
  111 + List<NavigatorObserver>? navigatorObservers,
  112 + GlobalKey<NavigatorState>? navigatorKey,
  113 + GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey,
  114 + Map<String, Map<String, String>>? translationsKeys,
  115 + Translations? translations,
  116 + Locale? locale,
  117 + Locale? fallbackLocale,
  118 + String? initialRoute,
  119 + CustomTransition? customTransition,
  120 + Widget? home,
  121 + bool? testMode,
  122 + Key? unikey,
  123 + ThemeData? theme,
  124 + ThemeData? darkTheme,
  125 + ThemeMode? themeMode,
  126 + bool? defaultPopGesture,
  127 + bool? defaultOpaqueRoute,
  128 + Duration? defaultTransitionDuration,
  129 + Curve? defaultTransitionCurve,
  130 + Curve? defaultDialogTransitionCurve,
  131 + Duration? defaultDialogTransitionDuration,
  132 + Routing? routing,
  133 + Map<String, String?>? parameters,
  134 + }) {
  135 + return ConfigData(
  136 + routingCallback: routingCallback ?? this.routingCallback,
  137 + defaultTransition: defaultTransition ?? this.defaultTransition,
  138 + onInit: onInit ?? this.onInit,
  139 + onReady: onReady ?? this.onReady,
  140 + onDispose: onDispose ?? this.onDispose,
  141 + enableLog: enableLog ?? this.enableLog,
  142 + logWriterCallback: logWriterCallback ?? this.logWriterCallback,
  143 + smartManagement: smartManagement ?? this.smartManagement,
  144 + binds: binds ?? this.binds,
  145 + transitionDuration: transitionDuration ?? this.transitionDuration,
  146 + defaultGlobalState: defaultGlobalState ?? this.defaultGlobalState,
  147 + getPages: getPages ?? this.getPages,
  148 + unknownRoute: unknownRoute ?? this.unknownRoute,
  149 + routeInformationProvider:
  150 + routeInformationProvider ?? this.routeInformationProvider,
  151 + routeInformationParser:
  152 + routeInformationParser ?? this.routeInformationParser,
  153 + routerDelegate: routerDelegate ?? this.routerDelegate,
  154 + backButtonDispatcher: backButtonDispatcher ?? this.backButtonDispatcher,
  155 + navigatorObservers: navigatorObservers ?? this.navigatorObservers,
  156 + navigatorKey: navigatorKey ?? this.navigatorKey,
  157 + scaffoldMessengerKey: scaffoldMessengerKey ?? this.scaffoldMessengerKey,
  158 + translationsKeys: translationsKeys ?? this.translationsKeys,
  159 + translations: translations ?? this.translations,
  160 + locale: locale ?? this.locale,
  161 + fallbackLocale: fallbackLocale ?? this.fallbackLocale,
  162 + initialRoute: initialRoute ?? this.initialRoute,
  163 + customTransition: customTransition ?? this.customTransition,
  164 + home: home ?? this.home,
  165 + testMode: testMode ?? this.testMode,
  166 + unikey: unikey ?? this.unikey,
  167 + theme: theme ?? this.theme,
  168 + darkTheme: darkTheme ?? this.darkTheme,
  169 + themeMode: themeMode ?? this.themeMode,
  170 + defaultPopGesture: defaultPopGesture ?? this.defaultPopGesture,
  171 + defaultOpaqueRoute: defaultOpaqueRoute ?? this.defaultOpaqueRoute,
  172 + defaultTransitionDuration:
  173 + defaultTransitionDuration ?? this.defaultTransitionDuration,
  174 + defaultTransitionCurve:
  175 + defaultTransitionCurve ?? this.defaultTransitionCurve,
  176 + defaultDialogTransitionCurve:
  177 + defaultDialogTransitionCurve ?? this.defaultDialogTransitionCurve,
  178 + defaultDialogTransitionDuration: defaultDialogTransitionDuration ??
  179 + this.defaultDialogTransitionDuration,
  180 + routing: routing ?? this.routing,
  181 + parameters: parameters ?? this.parameters,
  182 + );
  183 + }
  184 +
  185 + @override
  186 + bool operator ==(Object other) {
  187 + if (identical(this, other)) return true;
  188 +
  189 + return other is ConfigData &&
  190 + other.routingCallback == routingCallback &&
  191 + other.defaultTransition == defaultTransition &&
  192 + other.onInit == onInit &&
  193 + other.onReady == onReady &&
  194 + other.onDispose == onDispose &&
  195 + other.enableLog == enableLog &&
  196 + other.logWriterCallback == logWriterCallback &&
  197 + other.smartManagement == smartManagement &&
  198 + listEquals(other.binds, binds) &&
  199 + other.transitionDuration == transitionDuration &&
  200 + other.defaultGlobalState == defaultGlobalState &&
  201 + listEquals(other.getPages, getPages) &&
  202 + other.unknownRoute == unknownRoute &&
  203 + other.routeInformationProvider == routeInformationProvider &&
  204 + other.routeInformationParser == routeInformationParser &&
  205 + other.routerDelegate == routerDelegate &&
  206 + other.backButtonDispatcher == backButtonDispatcher &&
  207 + listEquals(other.navigatorObservers, navigatorObservers) &&
  208 + other.navigatorKey == navigatorKey &&
  209 + other.scaffoldMessengerKey == scaffoldMessengerKey &&
  210 + mapEquals(other.translationsKeys, translationsKeys) &&
  211 + other.translations == translations &&
  212 + other.locale == locale &&
  213 + other.fallbackLocale == fallbackLocale &&
  214 + other.initialRoute == initialRoute &&
  215 + other.customTransition == customTransition &&
  216 + other.home == home &&
  217 + other.testMode == testMode &&
  218 + other.unikey == unikey &&
  219 + other.theme == theme &&
  220 + other.darkTheme == darkTheme &&
  221 + other.themeMode == themeMode &&
  222 + other.defaultPopGesture == defaultPopGesture &&
  223 + other.defaultOpaqueRoute == defaultOpaqueRoute &&
  224 + other.defaultTransitionDuration == defaultTransitionDuration &&
  225 + other.defaultTransitionCurve == defaultTransitionCurve &&
  226 + other.defaultDialogTransitionCurve == defaultDialogTransitionCurve &&
  227 + other.defaultDialogTransitionDuration ==
  228 + defaultDialogTransitionDuration &&
  229 + other.routing == routing &&
  230 + mapEquals(other.parameters, parameters);
  231 + }
  232 +
  233 + @override
  234 + int get hashCode {
  235 + return routingCallback.hashCode ^
  236 + defaultTransition.hashCode ^
  237 + onInit.hashCode ^
  238 + onReady.hashCode ^
  239 + onDispose.hashCode ^
  240 + enableLog.hashCode ^
  241 + logWriterCallback.hashCode ^
  242 + smartManagement.hashCode ^
  243 + binds.hashCode ^
  244 + transitionDuration.hashCode ^
  245 + defaultGlobalState.hashCode ^
  246 + getPages.hashCode ^
  247 + unknownRoute.hashCode ^
  248 + routeInformationProvider.hashCode ^
  249 + routeInformationParser.hashCode ^
  250 + routerDelegate.hashCode ^
  251 + backButtonDispatcher.hashCode ^
  252 + navigatorObservers.hashCode ^
  253 + navigatorKey.hashCode ^
  254 + scaffoldMessengerKey.hashCode ^
  255 + translationsKeys.hashCode ^
  256 + translations.hashCode ^
  257 + locale.hashCode ^
  258 + fallbackLocale.hashCode ^
  259 + initialRoute.hashCode ^
  260 + customTransition.hashCode ^
  261 + home.hashCode ^
  262 + testMode.hashCode ^
  263 + unikey.hashCode ^
  264 + theme.hashCode ^
  265 + darkTheme.hashCode ^
  266 + themeMode.hashCode ^
  267 + defaultPopGesture.hashCode ^
  268 + defaultOpaqueRoute.hashCode ^
  269 + defaultTransitionDuration.hashCode ^
  270 + defaultTransitionCurve.hashCode ^
  271 + defaultDialogTransitionCurve.hashCode ^
  272 + defaultDialogTransitionDuration.hashCode ^
  273 + routing.hashCode ^
  274 + parameters.hashCode;
  275 + }
  276 +}
  277 +
  278 +class GetRoot extends StatefulWidget {
  279 + GetRoot({
  280 + Key? key,
  281 + required this.config,
  282 + required this.child,
  283 + }) : super(key: key);
  284 + final ConfigData config;
  285 + final Widget child;
  286 + @override
  287 + State<GetRoot> createState() => GetRootState();
  288 +
  289 + static GetRootState of(BuildContext context) {
  290 + // Handles the case where the input context is a navigator element.
  291 + GetRootState? root;
  292 + if (context is StatefulElement && context.state is GetRootState) {
  293 + root = context.state as GetRootState;
  294 + }
  295 + root = context.findRootAncestorStateOfType<GetRootState>() ?? root;
  296 + assert(() {
  297 + if (root == null) {
  298 + throw FlutterError(
  299 + 'GetRoot operation requested with a context that does not include a GetRoot.\n'
  300 + 'The context used must be that of a '
  301 + 'widget that is a descendant of a GetRoot widget.',
  302 + );
  303 + }
  304 + return true;
  305 + }());
  306 + return root!;
  307 + }
  308 +}
  309 +
  310 +class GetRootState extends State<GetRoot> with WidgetsBindingObserver {
  311 + static GetRootState? _controller;
  312 + static GetRootState get controller {
  313 + if (_controller == null) {
  314 + throw Exception('GetRoot is not part of the three');
  315 + } else {
  316 + return _controller!;
  317 + }
  318 + }
  319 +
  320 + late ConfigData config;
  321 +
  322 + @override
  323 + void initState() {
  324 + config = widget.config;
  325 + GetRootState._controller = this;
  326 + ambiguate(Engine.instance)!.addObserver(this);
  327 + onInit();
  328 + super.initState();
  329 + }
  330 +
  331 + // @override
  332 + // void didUpdateWidget(covariant GetRoot oldWidget) {
  333 + // if (oldWidget.config != widget.config) {
  334 + // config = widget.config;
  335 + // }
  336 +
  337 + // super.didUpdateWidget(oldWidget);
  338 + // }
  339 +
  340 + void onClose() {
  341 + config.onDispose?.call();
  342 + Get.clearTranslations();
  343 + RouterReportManager.instance.clearRouteKeys();
  344 + RouterReportManager.dispose();
  345 + Get.resetInstance(clearRouteBindings: true);
  346 + _controller = null;
  347 + ambiguate(Engine.instance)!.removeObserver(this);
  348 + }
  349 +
  350 + @override
  351 + void dispose() {
  352 + onClose();
  353 + super.dispose();
  354 + }
  355 +
  356 + void onInit() {
  357 + if (config.getPages == null && config.home == null) {
  358 + throw 'You need add pages or home';
  359 + }
  360 +
  361 + if (config.routerDelegate == null) {
  362 + final newDelegate = GetDelegate.createDelegate(
  363 + pages: config.getPages ??
  364 + [
  365 + GetPage(
  366 + name: cleanRouteName("/${config.home.runtimeType}"),
  367 + page: () => config.home!,
  368 + ),
  369 + ],
  370 + notFoundRoute: config.unknownRoute,
  371 + navigatorKey: config.navigatorKey,
  372 + navigatorObservers: (config.navigatorObservers == null
  373 + ? <NavigatorObserver>[
  374 + GetObserver(config.routingCallback, Get.routing)
  375 + ]
  376 + : <NavigatorObserver>[
  377 + GetObserver(config.routingCallback, config.routing),
  378 + ...config.navigatorObservers!
  379 + ]),
  380 + );
  381 + config = config.copyWith(routerDelegate: newDelegate);
  382 + }
  383 +
  384 + if (config.routeInformationParser == null) {
  385 + final newRouteInformationParser =
  386 + GetInformationParser.createInformationParser(
  387 + initialRoute: config.initialRoute ??
  388 + config.getPages?.first.name ??
  389 + cleanRouteName("/${config.home.runtimeType}"),
  390 + );
  391 +
  392 + config =
  393 + config.copyWith(routeInformationParser: newRouteInformationParser);
  394 + }
  395 +
  396 + if (config.locale != null) Get.locale = config.locale;
  397 +
  398 + if (config.fallbackLocale != null) {
  399 + Get.fallbackLocale = config.fallbackLocale;
  400 + }
  401 +
  402 + if (config.translations != null) {
  403 + Get.addTranslations(config.translations!.keys);
  404 + } else if (config.translationsKeys != null) {
  405 + Get.addTranslations(config.translationsKeys!);
  406 + }
  407 +
  408 + Get.smartManagement = config.smartManagement;
  409 + config.onInit?.call();
  410 +
  411 + Get.isLogEnable = config.enableLog ?? kDebugMode;
  412 + Get.log = config.logWriterCallback ?? defaultLogWriterCallback;
  413 +
  414 + if (config.defaultTransition == null) {
  415 + config = config.copyWith(defaultTransition: getThemeTransition());
  416 + }
  417 +
  418 + // defaultOpaqueRoute = config.opaqueRoute ?? true;
  419 + // defaultPopGesture = config.popGesture ?? GetPlatform.isIOS;
  420 + // defaultTransitionDuration =
  421 + // config.transitionDuration ?? Duration(milliseconds: 300);
  422 +
  423 + Future(() => onReady());
  424 + }
  425 +
  426 + set parameters(Map<String, String?> newParameters) {
  427 + // rootController.parameters = newParameters;
  428 + config = config.copyWith(parameters: newParameters);
  429 + }
  430 +
  431 + set testMode(bool isTest) {
  432 + config = config.copyWith(testMode: isTest);
  433 + // _getxController.testMode = isTest;
  434 + }
  435 +
  436 + void onReady() {
  437 + config.onReady?.call();
  438 + }
  439 +
  440 + Transition? getThemeTransition() {
  441 + final platform = Get.theme.platform;
  442 + final matchingTransition =
  443 + Get.theme.pageTransitionsTheme.builders[platform];
  444 + switch (matchingTransition) {
  445 + case CupertinoPageTransitionsBuilder():
  446 + return Transition.cupertino;
  447 + case ZoomPageTransitionsBuilder():
  448 + return Transition.zoom;
  449 + case FadeUpwardsPageTransitionsBuilder():
  450 + return Transition.fade;
  451 + case OpenUpwardsPageTransitionsBuilder():
  452 + return Transition.native;
  453 + default:
  454 + return null;
  455 + }
  456 + }
  457 +
  458 + @override
  459 + void didChangeLocales(List<Locale>? locales) {
  460 + Get.asap(() {
  461 + final locale = Get.deviceLocale;
  462 + if (locale != null) {
  463 + Get.updateLocale(locale);
  464 + }
  465 + });
  466 + }
  467 +
  468 + void setTheme(ThemeData value) {
  469 + if (config.darkTheme == null) {
  470 + config = config.copyWith(theme: value);
  471 + } else {
  472 + if (value.brightness == Brightness.light) {
  473 + config = config.copyWith(theme: value);
  474 + } else {
  475 + config = config.copyWith(darkTheme: value);
  476 + }
  477 + }
  478 + update();
  479 + }
  480 +
  481 + void setThemeMode(ThemeMode value) {
  482 + config = config.copyWith(themeMode: value);
  483 + update();
  484 + }
  485 +
  486 + void restartApp() {
  487 + config = config.copyWith(unikey: UniqueKey());
  488 + update();
  489 + }
  490 +
  491 + void update() {
  492 + setState(() {});
  493 + }
  494 +
  495 + GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey;
  496 +
  497 + GetDelegate get rootDelegate => config.routerDelegate as GetDelegate;
  498 +
  499 + RouteInformationParser<Object> get informationParser =>
  500 + config.routeInformationParser!;
  501 +
  502 + GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
  503 + rootDelegate.navigatorKey = newKey;
  504 + return key;
  505 + }
  506 +
  507 + Map<dynamic, GetDelegate> keys = {};
  508 +
  509 + GetDelegate? nestedKey(String? key) {
  510 + if (key == null) {
  511 + return rootDelegate;
  512 + }
  513 + keys.putIfAbsent(
  514 + key,
  515 + () => GetDelegate(
  516 + showHashOnUrl: true,
  517 + //debugLabel: 'Getx nested key: ${key.toString()}',
  518 + pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],
  519 + ),
  520 + );
  521 + return keys[key];
  522 + }
  523 +
  524 + @override
  525 + Widget build(BuildContext context) {
  526 + return widget.child;
  527 + }
  528 +
  529 + String cleanRouteName(String name) {
  530 + name = name.replaceAll('() => ', '');
  531 +
  532 + /// uncommonent for URL styling.
  533 + // name = name.paramCase!;
  534 + if (!name.startsWith('/')) {
  535 + name = '/$name';
  536 + }
  537 + return Uri.tryParse(name)?.toString() ?? name;
  538 + }
  539 +}
@@ -3,278 +3,49 @@ import 'package:flutter/material.dart'; @@ -3,278 +3,49 @@ import 'package:flutter/material.dart';
3 3
4 import '../../../get.dart'; 4 import '../../../get.dart';
5 5
6 -class ConfigData {  
7 - final ValueChanged<Routing?>? routingCallback;  
8 - final Transition? defaultTransition;  
9 - final bool? opaqueRoute;  
10 - final VoidCallback? onInit;  
11 - final VoidCallback? onReady;  
12 - final VoidCallback? onDispose;  
13 - final bool? enableLog;  
14 - final LogWriterCallback? logWriterCallback;  
15 - final bool? popGesture;  
16 - final SmartManagement smartManagement;  
17 - final List<Bind> binds;  
18 - final Duration? transitionDuration;  
19 - final bool? defaultGlobalState;  
20 - final List<GetPage>? getPages;  
21 - final GetPage? unknownRoute;  
22 - final RouteInformationProvider? routeInformationProvider;  
23 - final RouteInformationParser<Object>? routeInformationParser;  
24 - final RouterDelegate<Object>? routerDelegate;  
25 - final BackButtonDispatcher? backButtonDispatcher;  
26 - final List<NavigatorObserver>? navigatorObservers;  
27 - final GlobalKey<NavigatorState>? navigatorKey;  
28 - final GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey;  
29 - final Map<String, Map<String, String>>? translationsKeys;  
30 - final Translations? translations;  
31 - final Locale? locale;  
32 - final Locale? fallbackLocale;  
33 - final String? initialRoute;  
34 - final CustomTransition? customTransition;  
35 - final Widget? home;  
36 6
37 - ConfigData({  
38 - required this.routingCallback,  
39 - required this.defaultTransition,  
40 - required this.opaqueRoute,  
41 - required this.onInit,  
42 - required this.onReady,  
43 - required this.onDispose,  
44 - required this.enableLog,  
45 - required this.logWriterCallback,  
46 - required this.popGesture,  
47 - required this.smartManagement,  
48 - required this.binds,  
49 - required this.transitionDuration,  
50 - required this.defaultGlobalState,  
51 - required this.getPages,  
52 - required this.unknownRoute,  
53 - required this.routeInformationProvider,  
54 - required this.routeInformationParser,  
55 - required this.routerDelegate,  
56 - required this.backButtonDispatcher,  
57 - required this.navigatorObservers,  
58 - required this.navigatorKey,  
59 - required this.scaffoldMessengerKey,  
60 - required this.translationsKeys,  
61 - required this.translations,  
62 - required this.locale,  
63 - required this.fallbackLocale,  
64 - required this.initialRoute,  
65 - required this.customTransition,  
66 - required this.home,  
67 - });  
68 -}  
69 7
70 -class GetMaterialController extends FullLifeCycleController {  
71 - GetMaterialController(this.config);  
72 -  
73 - late final RouterDelegate<Object> routerDelegate;  
74 - late final RouteInformationParser<Object> routeInformationParser;  
75 - final ConfigData config;  
76 -  
77 - @override  
78 - void onReady() {  
79 - config.onReady?.call();  
80 - super.onReady();  
81 - }  
82 -  
83 - @override  
84 - void onInit() {  
85 - super.onInit();  
86 -  
87 - if (config.getPages == null && config.home == null) {  
88 - throw 'You need add pages or home';  
89 - }  
90 - print('route delefate from onInit');  
91 - routerDelegate = config.routerDelegate ??  
92 - createDelegate(  
93 - pages: config.getPages ??  
94 - [  
95 - GetPage(  
96 - name: cleanRouteName("/${config.home.runtimeType}"),  
97 - page: () => config.home!,  
98 - ),  
99 - ],  
100 - notFoundRoute: config.unknownRoute,  
101 - navigatorKey: config.navigatorKey,  
102 - navigatorObservers: (config.navigatorObservers == null  
103 - ? <NavigatorObserver>[  
104 - GetObserver(config.routingCallback, Get.routing)  
105 - ]  
106 - : <NavigatorObserver>[  
107 - GetObserver(config.routingCallback, routing),  
108 - ...config.navigatorObservers!  
109 - ]),  
110 - );  
111 -  
112 - routeInformationParser = config.routeInformationParser ??  
113 - createInformationParser(  
114 - initialRoute: config.initialRoute ??  
115 - config.getPages?.first.name ??  
116 - cleanRouteName("/${config.home.runtimeType}"),  
117 - );  
118 -  
119 - if (config.locale != null) Get.locale = config.locale;  
120 -  
121 - if (config.fallbackLocale != null) {  
122 - Get.fallbackLocale = config.fallbackLocale;  
123 - }  
124 -  
125 - if (config.translations != null) {  
126 - Get.addTranslations(config.translations!.keys);  
127 - } else if (config.translationsKeys != null) {  
128 - Get.addTranslations(config.translationsKeys!);  
129 - }  
130 -  
131 - customTransition = config.customTransition;  
132 -  
133 - Get.smartManagement = config.smartManagement;  
134 - config.onInit?.call();  
135 -  
136 - Get.isLogEnable = config.enableLog ?? kDebugMode;  
137 - Get.log = config.logWriterCallback ?? defaultLogWriterCallback;  
138 - defaultTransition = config.defaultTransition ?? getThemeTransition();  
139 - defaultOpaqueRoute = config.opaqueRoute ?? true;  
140 - defaultPopGesture = config.popGesture ?? GetPlatform.isIOS;  
141 - defaultTransitionDuration =  
142 - config.transitionDuration ?? Duration(milliseconds: 300);  
143 - }  
144 -  
145 - Transition? getThemeTransition() {  
146 - final platform = Get.theme.platform;  
147 - final matchingTransition =  
148 - Get.theme.pageTransitionsTheme.builders[platform];  
149 - switch (matchingTransition) {  
150 - case CupertinoPageTransitionsBuilder():  
151 - return Transition.cupertino;  
152 - case ZoomPageTransitionsBuilder():  
153 - return Transition.zoom;  
154 - case FadeUpwardsPageTransitionsBuilder():  
155 - return Transition.fade;  
156 - case OpenUpwardsPageTransitionsBuilder():  
157 - return Transition.native;  
158 - default:  
159 - return null;  
160 - }  
161 - }  
162 -  
163 - String cleanRouteName(String name) {  
164 - name = name.replaceAll('() => ', '');  
165 -  
166 - /// uncommonent for URL styling.  
167 - // name = name.paramCase!;  
168 - if (!name.startsWith('/')) {  
169 - name = '/$name';  
170 - }  
171 - return Uri.tryParse(name)?.toString() ?? name;  
172 - }  
173 -  
174 - bool testMode = false;  
175 - Key? unikey;  
176 - ThemeData? theme;  
177 - ThemeData? darkTheme;  
178 - ThemeMode? themeMode;  
179 -  
180 - final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();  
181 -  
182 - bool defaultPopGesture = GetPlatform.isIOS;  
183 - bool defaultOpaqueRoute = true;  
184 - Transition? defaultTransition;  
185 - Duration defaultTransitionDuration = Duration(milliseconds: 300);  
186 - Curve defaultTransitionCurve = Curves.easeOutQuad;  
187 - Curve defaultDialogTransitionCurve = Curves.easeOutQuad;  
188 - Duration defaultDialogTransitionDuration = Duration(milliseconds: 300);  
189 -  
190 - final routing = Routing();  
191 -  
192 - Map<String, String?> parameters = {};  
193 - CustomTransition? customTransition;  
194 -  
195 - Map<dynamic, GetDelegate> keys = {};  
196 -  
197 - GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey;  
198 -  
199 - GetDelegate get rootDelegate => routerDelegate as GetDelegate;  
200 -  
201 - GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {  
202 - rootDelegate.navigatorKey = newKey;  
203 - return key;  
204 - }  
205 -  
206 - @override  
207 - void didChangeLocales(List<Locale>? locales) {  
208 - Get.asap(() {  
209 - final locale = Get.deviceLocale;  
210 - if (locale != null) {  
211 - Get.updateLocale(locale);  
212 - }  
213 - });  
214 - }  
215 -  
216 - void restartApp() {  
217 - unikey = UniqueKey();  
218 - update();  
219 - }  
220 -  
221 - void setTheme(ThemeData value) {  
222 - if (darkTheme == null) {  
223 - theme = value;  
224 - } else {  
225 - if (value.brightness == Brightness.light) {  
226 - theme = value;  
227 - } else {  
228 - darkTheme = value;  
229 - }  
230 - }  
231 - update();  
232 - }  
233 -  
234 - void setThemeMode(ThemeMode value) {  
235 - themeMode = value;  
236 - update();  
237 - }  
238 -  
239 - GetDelegate? nestedKey(String? key) {  
240 - if (key == null) {  
241 - return routerDelegate as GetDelegate;  
242 - }  
243 - keys.putIfAbsent(  
244 - key,  
245 - () => GetDelegate(  
246 - showHashOnUrl: true,  
247 - //debugLabel: 'Getx nested key: ${key.toString()}',  
248 - pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],  
249 - ),  
250 - );  
251 - return keys[key];  
252 - }  
253 -  
254 - GetInformationParser createInformationParser({String initialRoute = '/'}) {  
255 - return GetInformationParser(  
256 - initialRoute: initialRoute,  
257 - );  
258 - }  
259 -  
260 - GetDelegate createDelegate({  
261 - GetPage<dynamic>? notFoundRoute,  
262 - List<GetPage> pages = const [],  
263 - List<NavigatorObserver>? navigatorObservers,  
264 - TransitionDelegate<dynamic>? transitionDelegate,  
265 - PopMode backButtonPopMode = PopMode.history,  
266 - PreventDuplicateHandlingMode preventDuplicateHandlingMode =  
267 - PreventDuplicateHandlingMode.reorderRoutes,  
268 - GlobalKey<NavigatorState>? navigatorKey,  
269 - }) {  
270 - return GetDelegate(  
271 - notFoundRoute: notFoundRoute,  
272 - navigatorObservers: navigatorObservers,  
273 - transitionDelegate: transitionDelegate,  
274 - backButtonPopMode: backButtonPopMode,  
275 - preventDuplicateHandlingMode: preventDuplicateHandlingMode,  
276 - pages: pages,  
277 - navigatorKey: navigatorKey,  
278 - );  
279 - }  
280 -} 8 +// class GetMaterialController extends FullLifeCycleController {
  9 +// GetMaterialController(this.config);
  10 +
  11 +// // late final RouterDelegate<Object> routerDelegate;
  12 +// // late final RouteInformationParser<Object> routeInformationParser;
  13 +// final ConfigData config;
  14 +// // bool testMode = false;
  15 +// // Key? unikey;
  16 +// // ThemeData? theme;
  17 +// // ThemeData? darkTheme;
  18 +// // ThemeMode? themeMode;
  19 +
  20 +// // final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
  21 +
  22 +// // bool defaultPopGesture = GetPlatform.isIOS;
  23 +// // bool defaultOpaqueRoute = true;
  24 +// // Transition? defaultTransition;
  25 +// // Duration defaultTransitionDuration = Duration(milliseconds: 300);
  26 +// // Curve defaultTransitionCurve = Curves.easeOutQuad;
  27 +// // Curve defaultDialogTransitionCurve = Curves.easeOutQuad;
  28 +// // Duration defaultDialogTransitionDuration = Duration(milliseconds: 300);
  29 +
  30 +// // final routing = Routing();
  31 +
  32 +// // Map<String, String?> parameters = {};
  33 +// // CustomTransition? customTransition;
  34 +
  35 +// // Map<dynamic, GetDelegate> keys = {};
  36 +
  37 +// // GetDelegate? nestedKey(String? key) {
  38 +// // if (key == null) {
  39 +// // return routerDelegate as GetDelegate;
  40 +// // }
  41 +// // keys.putIfAbsent(
  42 +// // key,
  43 +// // () => GetDelegate(
  44 +// // showHashOnUrl: true,
  45 +// // //debugLabel: 'Getx nested key: ${key.toString()}',
  46 +// // pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],
  47 +// // ),
  48 +// // );
  49 +// // return keys[key];
  50 +// // }
  51 +// }
1 import 'dart:collection'; 1 import 'dart:collection';
2 2
3 -import 'package:flutter/widgets.dart';  
4 -  
5 import '../../get.dart'; 3 import '../../get.dart';
6 4
7 class RouterReportManager<T> { 5 class RouterReportManager<T> {
@@ -4,6 +4,11 @@ import 'package:flutter/widgets.dart'; @@ -4,6 +4,11 @@ import 'package:flutter/widgets.dart';
4 import '../../../get.dart'; 4 import '../../../get.dart';
5 5
6 class GetInformationParser extends RouteInformationParser<RouteDecoder> { 6 class GetInformationParser extends RouteInformationParser<RouteDecoder> {
  7 + factory GetInformationParser.createInformationParser(
  8 + {String initialRoute = '/'}) {
  9 + return GetInformationParser(initialRoute: initialRoute);
  10 + }
  11 +
7 final String initialRoute; 12 final String initialRoute;
8 13
9 GetInformationParser({ 14 GetInformationParser({
@@ -19,7 +24,7 @@ class GetInformationParser extends RouteInformationParser<RouteDecoder> { @@ -19,7 +24,7 @@ class GetInformationParser extends RouteInformationParser<RouteDecoder> {
19 if (location == '/') { 24 if (location == '/') {
20 //check if there is a corresponding page 25 //check if there is a corresponding page
21 //if not, relocate to initialRoute 26 //if not, relocate to initialRoute
22 - if (!(Get.rootController.routerDelegate as GetDelegate) 27 + if (!(Get.rootController.rootDelegate)
23 .registeredRoutes 28 .registeredRoutes
24 .any((element) => element.name == '/')) { 29 .any((element) => element.name == '/')) {
25 location = initialRoute; 30 location = initialRoute;
@@ -43,8 +43,10 @@ class GetPage<T> extends Page<T> { @@ -43,8 +43,10 @@ class GetPage<T> extends Page<T> {
43 @override 43 @override
44 final String name; 44 final String name;
45 45
  46 + final bool inheritParentPath;
  47 +
46 final List<GetPage> children; 48 final List<GetPage> children;
47 - final List<GetMiddleware>? middlewares; 49 + final List<GetMiddleware> middlewares;
48 final PathDecoded path; 50 final PathDecoded path;
49 final GetPage? unknownRoute; 51 final GetPage? unknownRoute;
50 final bool showCupertinoParallax; 52 final bool showCupertinoParallax;
@@ -73,7 +75,7 @@ class GetPage<T> extends Page<T> { @@ -73,7 +75,7 @@ class GetPage<T> extends Page<T> {
73 this.customTransition, 75 this.customTransition,
74 this.fullscreenDialog = false, 76 this.fullscreenDialog = false,
75 this.children = const <GetPage>[], 77 this.children = const <GetPage>[],
76 - this.middlewares, 78 + this.middlewares = const [],
77 this.unknownRoute, 79 this.unknownRoute,
78 this.arguments, 80 this.arguments,
79 this.showCupertinoParallax = true, 81 this.showCupertinoParallax = true,
@@ -81,6 +83,7 @@ class GetPage<T> extends Page<T> { @@ -81,6 +83,7 @@ class GetPage<T> extends Page<T> {
81 this.preventDuplicateHandlingMode = 83 this.preventDuplicateHandlingMode =
82 PreventDuplicateHandlingMode.reorderRoutes, 84 PreventDuplicateHandlingMode.reorderRoutes,
83 this.completer, 85 this.completer,
  86 + this.inheritParentPath = true,
84 LocalKey? key, 87 LocalKey? key,
85 }) : path = _nameToRegex(name), 88 }) : path = _nameToRegex(name),
86 assert(name.startsWith('/'), 89 assert(name.startsWith('/'),
@@ -92,7 +95,7 @@ class GetPage<T> extends Page<T> { @@ -92,7 +95,7 @@ class GetPage<T> extends Page<T> {
92 ); 95 );
93 // settings = RouteSettings(name: name, arguments: Get.arguments); 96 // settings = RouteSettings(name: name, arguments: Get.arguments);
94 97
95 - GetPage<T> copy({ 98 + GetPage<T> copyWith({
96 LocalKey? key, 99 LocalKey? key,
97 String? name, 100 String? name,
98 GetPageBuilder? page, 101 GetPageBuilder? page,
@@ -121,6 +124,7 @@ class GetPage<T> extends Page<T> { @@ -121,6 +124,7 @@ class GetPage<T> extends Page<T> {
121 Object? arguments, 124 Object? arguments,
122 bool? showCupertinoParallax, 125 bool? showCupertinoParallax,
123 Completer<T?>? completer, 126 Completer<T?>? completer,
  127 + bool? inheritParentPath,
124 }) { 128 }) {
125 return GetPage( 129 return GetPage(
126 key: key ?? this.key, 130 key: key ?? this.key,
@@ -153,6 +157,7 @@ class GetPage<T> extends Page<T> { @@ -153,6 +157,7 @@ class GetPage<T> extends Page<T> {
153 showCupertinoParallax: 157 showCupertinoParallax:
154 showCupertinoParallax ?? this.showCupertinoParallax, 158 showCupertinoParallax ?? this.showCupertinoParallax,
155 completer: completer ?? this.completer, 159 completer: completer ?? this.completer,
  160 + inheritParentPath: inheritParentPath ?? this.inheritParentPath,
156 ); 161 );
157 } 162 }
158 163
@@ -12,6 +12,27 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -12,6 +12,27 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
12 ChangeNotifier, 12 ChangeNotifier,
13 PopNavigatorRouterDelegateMixin<RouteDecoder>, 13 PopNavigatorRouterDelegateMixin<RouteDecoder>,
14 IGetNavigation { 14 IGetNavigation {
  15 + factory GetDelegate.createDelegate({
  16 + GetPage<dynamic>? notFoundRoute,
  17 + List<GetPage> pages = const [],
  18 + List<NavigatorObserver>? navigatorObservers,
  19 + TransitionDelegate<dynamic>? transitionDelegate,
  20 + PopMode backButtonPopMode = PopMode.history,
  21 + PreventDuplicateHandlingMode preventDuplicateHandlingMode =
  22 + PreventDuplicateHandlingMode.reorderRoutes,
  23 + GlobalKey<NavigatorState>? navigatorKey,
  24 + }) {
  25 + return GetDelegate(
  26 + notFoundRoute: notFoundRoute,
  27 + navigatorObservers: navigatorObservers,
  28 + transitionDelegate: transitionDelegate,
  29 + backButtonPopMode: backButtonPopMode,
  30 + preventDuplicateHandlingMode: preventDuplicateHandlingMode,
  31 + pages: pages,
  32 + navigatorKey: navigatorKey,
  33 + );
  34 + }
  35 +
15 final List<RouteDecoder> _activePages = <RouteDecoder>[]; 36 final List<RouteDecoder> _activePages = <RouteDecoder>[];
16 final PopMode backButtonPopMode; 37 final PopMode backButtonPopMode;
17 final PreventDuplicateHandlingMode preventDuplicateHandlingMode; 38 final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
@@ -84,7 +105,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -84,7 +105,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
84 105
85 Future<RouteDecoder?> runMiddleware(RouteDecoder config) async { 106 Future<RouteDecoder?> runMiddleware(RouteDecoder config) async {
86 final middlewares = config.currentTreeBranch.last.middlewares; 107 final middlewares = config.currentTreeBranch.last.middlewares;
87 - if (middlewares == null) { 108 + if (middlewares.isEmpty) {
88 return config; 109 return config;
89 } 110 }
90 var iterator = config; 111 var iterator = config;
@@ -145,10 +166,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -145,10 +166,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
145 return currentConfiguration?.pageSettings; 166 return currentConfiguration?.pageSettings;
146 } 167 }
147 168
148 - Future<T?> _removeHistoryEntry<T>(RouteDecoder entry, T result) async {  
149 - return _unsafeHistoryRemove<T>(entry, result);  
150 - }  
151 -  
152 Future<void> _pushHistory(RouteDecoder config) async { 169 Future<void> _pushHistory(RouteDecoder config) async {
153 if (config.route!.preventDuplicates) { 170 if (config.route!.preventDuplicates) {
154 final originalEntryIndex = _activePages.indexWhere( 171 final originalEntryIndex = _activePages.indexWhere(
@@ -560,7 +577,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -560,7 +577,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
560 _activePages.remove(RouteDecoder.fromRoute(name)); 577 _activePages.remove(RouteDecoder.fromRoute(name));
561 } 578 }
562 579
563 -  
564 bool get canBack { 580 bool get canBack {
565 return _activePages.length > 1; 581 return _activePages.length > 1;
566 } 582 }
@@ -691,7 +707,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -691,7 +707,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
691 decoder.parameters.addAll(parameters); 707 decoder.parameters.addAll(parameters);
692 } 708 }
693 709
694 - decoder.route = decoder.route?.copy( 710 + decoder.route = decoder.route?.copyWith(
695 completer: _activePages.isEmpty ? null : Completer(), 711 completer: _activePages.isEmpty ? null : Completer(),
696 arguments: arguments, 712 arguments: arguments,
697 parameters: parameters, 713 parameters: parameters,
@@ -801,7 +817,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -801,7 +817,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
801 notifyListeners(); 817 notifyListeners();
802 } 818 }
803 819
804 -  
805 bool _onPopVisualRoute(Route<dynamic> route, dynamic result) { 820 bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {
806 final didPop = route.didPop(result); 821 final didPop = route.didPop(result);
807 if (!didPop) { 822 if (!didPop) {
@@ -7,6 +7,7 @@ import 'package:flutter/gestures.dart'; @@ -7,6 +7,7 @@ import 'package:flutter/gestures.dart';
7 import 'package:flutter/material.dart'; 7 import 'package:flutter/material.dart';
8 8
9 import '../../../get.dart'; 9 import '../../../get.dart';
  10 +import '../root/get_root.dart';
10 11
11 const double _kBackGestureWidth = 20.0; 12 const double _kBackGestureWidth = 20.0;
12 13
@@ -716,8 +717,8 @@ Cannot read the previousTitle for a route that has not yet been installed''', @@ -716,8 +717,8 @@ Cannot read the previousTitle for a route that has not yet been installed''',
716 )); 717 ));
717 718
718 default: 719 default:
719 - final customTransition =  
720 - context.get<GetMaterialController>().customTransition; 720 + final customTransition = GetRoot.of(context).config.customTransition;
  721 +
721 if (customTransition != null) { 722 if (customTransition != null) {
722 return customTransition.buildTransition(context, route.curve, 723 return customTransition.buildTransition(context, route.curve,
723 route.alignment, animation, secondaryAnimation, child); 724 route.alignment, animation, secondaryAnimation, child);
  1 +import 'dart:async';
  2 +
  3 +import 'package:flutter/widgets.dart';
  4 +
  5 +import 'get_route.dart';
  6 +
  7 +class RouteMatcher {
  8 + final RouteNode _root = RouteNode('/', '/');
  9 +
  10 + RouteNode addRoute(String path) {
  11 + final segments = _parsePath(path);
  12 + var currentNode = _root;
  13 +
  14 + for (final segment in segments) {
  15 + final existingChild = currentNode.findChild(segment);
  16 + if (existingChild != null) {
  17 + currentNode = existingChild;
  18 + } else {
  19 + final newChild = RouteNode(segment, path);
  20 + currentNode.addChild(newChild);
  21 + currentNode = newChild;
  22 + }
  23 + }
  24 + return currentNode;
  25 + }
  26 +
  27 + void removeRoute(String path) {
  28 + final segments = _parsePath(path);
  29 + var currentNode = _root;
  30 + RouteNode? nodeToDelete;
  31 +
  32 + // Traverse the tree to find the node to delete
  33 + for (final segment in segments) {
  34 + final child = currentNode.findChild(segment);
  35 + if (child == null) {
  36 + return; // Node not found, nothing to delete
  37 + }
  38 + if (child.nodeSegments.length == segments.length) {
  39 + nodeToDelete = child;
  40 + break;
  41 + }
  42 + currentNode = child;
  43 + }
  44 +
  45 + if (nodeToDelete == null) {
  46 + return; // Node not found, nothing to delete
  47 + }
  48 +
  49 + final parent = nodeToDelete.parent!;
  50 + parent.nodeSegments.remove(nodeToDelete);
  51 + }
  52 +
  53 + RouteNode? _findChild(RouteNode currentNode, String segment) {
  54 + return currentNode.nodeSegments
  55 + .firstWhereOrNull((node) => node.matches(segment));
  56 + }
  57 +
  58 + MatchResult? matchRoute(String path) {
  59 + final uri = Uri.parse(path);
  60 + final segments = _parsePath(uri.path);
  61 + var currentNode = _root;
  62 + final parameters = <String, String>{};
  63 + final urlParameters = uri.queryParameters;
  64 +
  65 + for (final segment in segments) {
  66 + if (segment.isEmpty) continue;
  67 + final child = _findChild(currentNode, segment);
  68 + if (child == null) {
  69 + return null;
  70 + } else {
  71 + if (child.path.startsWith(':')) {
  72 + parameters[child.path.substring(1)] = segment;
  73 + }
  74 +
  75 + if (child.nodeSegments.length == segments.length) {
  76 + return null;
  77 + }
  78 +
  79 + currentNode = child;
  80 + }
  81 + }
  82 +
  83 + return MatchResult(
  84 + currentNode,
  85 + parameters,
  86 + path,
  87 + urlParameters: urlParameters,
  88 + );
  89 + }
  90 +
  91 + List<String> _parsePath(String path) {
  92 + return path.split('/').where((segment) => segment.isNotEmpty).toList();
  93 + }
  94 +}
  95 +
  96 +class RouteTreeResult {
  97 + final GetPage? route;
  98 + final MatchResult matchResult;
  99 +
  100 + RouteTreeResult({
  101 + required this.route,
  102 + required this.matchResult,
  103 + });
  104 +
  105 + @override
  106 + String toString() {
  107 + return 'RouteTreeResult(route: $route, matchResult: $matchResult)';
  108 + }
  109 +
  110 + RouteTreeResult configure(String page, Object? arguments) {
  111 + return copyWith(
  112 + route: route?.copyWith(
  113 + key: ValueKey(page),
  114 + settings: RouteSettings(name: page, arguments: arguments),
  115 + completer: Completer(),
  116 + arguments: arguments,
  117 + ));
  118 + }
  119 +
  120 + RouteTreeResult copyWith({
  121 + GetPage? route,
  122 + MatchResult? matchResult,
  123 + }) {
  124 + return RouteTreeResult(
  125 + route: route ?? this.route,
  126 + matchResult: matchResult ?? this.matchResult,
  127 + );
  128 + }
  129 +}
  130 +
  131 +class RouteTree {
  132 + static final instance = RouteTree();
  133 + final Map<String, GetPage> tree = {};
  134 + final RouteMatcher matcher = RouteMatcher();
  135 +
  136 + void addRoute(GetPage route) {
  137 + matcher.addRoute(route.name);
  138 + tree[route.name] = route;
  139 + handleChild(route);
  140 + }
  141 +
  142 + void addRoutes(List<GetPage> routes) {
  143 + for (var route in routes) {
  144 + addRoute(route);
  145 + }
  146 + }
  147 +
  148 + void handleChild(GetPage route) {
  149 + final children = route.children;
  150 + for (var child in children) {
  151 + final middlewares = List.of(route.middlewares);
  152 + final bindings = List.of(route.bindings);
  153 + middlewares.addAll(child.middlewares);
  154 + bindings.addAll(child.bindings);
  155 + child = child.copyWith(middlewares: middlewares, bindings: bindings);
  156 + if (child.inheritParentPath) {
  157 + child = child.copyWith(
  158 + name: ('${route.path}/${child.path}').replaceAll(r'//', '/'));
  159 + }
  160 + addRoute(child);
  161 + }
  162 + }
  163 +
  164 + void removeRoute(GetPage route) {
  165 + matcher.removeRoute(route.name);
  166 + tree.remove(route.path);
  167 + }
  168 +
  169 + void removeRoutes(List<GetPage> routes) {
  170 + for (var route in routes) {
  171 + removeRoute(route);
  172 + }
  173 + }
  174 +
  175 + RouteTreeResult? matchRoute(String path) {
  176 + final matchResult = matcher.matchRoute(path);
  177 + if (matchResult != null) {
  178 + final route = tree[matchResult.node.originalPath];
  179 + return RouteTreeResult(
  180 + route: route,
  181 + matchResult: matchResult,
  182 + );
  183 + }
  184 + return null;
  185 + }
  186 +}
  187 +
  188 +/// A class representing the result of a route matching operation.
  189 +class MatchResult {
  190 + /// The route found that matches the result
  191 + final RouteNode node;
  192 +
  193 + /// The current path of match, eg: adding 'user/:id' the match result for 'user/123' will be: 'user/123'
  194 + final String currentPath;
  195 +
  196 + /// Route parameters eg: adding 'user/:id' the match result for 'user/123' will be: {id: 123}
  197 + final Map<String, String> parameters;
  198 +
  199 + /// Route url parameters eg: adding 'user' the match result for 'user?foo=bar' will be: {foo: bar}
  200 + final Map<String, String> urlParameters;
  201 +
  202 + MatchResult(this.node, this.parameters, this.currentPath,
  203 + {this.urlParameters = const {}});
  204 +
  205 + @override
  206 + String toString() =>
  207 + 'MatchResult(node: $node, currentPath: $currentPath, parameters: $parameters, urlParameters: $urlParameters)';
  208 +}
  209 +
  210 +// A class representing a node in a routing tree.
  211 +class RouteNode {
  212 + String path;
  213 + String originalPath;
  214 + RouteNode? parent;
  215 + List<RouteNode> nodeSegments = [];
  216 +
  217 + RouteNode(this.path, this.originalPath, {this.parent});
  218 +
  219 + bool get isRoot => parent == null;
  220 +
  221 + String get fullPath {
  222 + if (isRoot) {
  223 + return '/';
  224 + } else {
  225 + final parentPath = parent?.fullPath == '/' ? '' : parent?.fullPath;
  226 + return '$parentPath/$path';
  227 + }
  228 + }
  229 +
  230 + bool get hasChildren => nodeSegments.isNotEmpty;
  231 +
  232 + void addChild(RouteNode child) {
  233 + nodeSegments.add(child);
  234 + child.parent = this;
  235 + }
  236 +
  237 + RouteNode? findChild(String name) {
  238 + return nodeSegments.firstWhereOrNull((node) => node.path == name);
  239 + }
  240 +
  241 + bool matches(String name) {
  242 + return name == path || path == '*' || path.startsWith(':');
  243 + }
  244 +
  245 + @override
  246 + String toString() =>
  247 + 'RouteNode(name: $path, nodeSegments: $nodeSegments, fullPath: $fullPath )';
  248 +}
  249 +
  250 +extension Foo<T> on Iterable<T> {
  251 + T? firstWhereOrNull(bool Function(T element) test) {
  252 + for (var element in this) {
  253 + if (test(element)) return element;
  254 + }
  255 + return null;
  256 + }
  257 +}
@@ -14,9 +14,9 @@ class RouteDecoder { @@ -14,9 +14,9 @@ class RouteDecoder {
14 factory RouteDecoder.fromRoute(String location) { 14 factory RouteDecoder.fromRoute(String location) {
15 var uri = Uri.parse(location); 15 var uri = Uri.parse(location);
16 final args = PageSettings(uri); 16 final args = PageSettings(uri);
17 - final decoder = (Get.rootController.routerDelegate as GetDelegate)  
18 - .matchRoute(location, arguments: args);  
19 - decoder.route = decoder.route?.copy( 17 + final decoder =
  18 + (Get.rootController.rootDelegate).matchRoute(location, arguments: args);
  19 + decoder.route = decoder.route?.copyWith(
20 completer: null, 20 completer: null,
21 arguments: args, 21 arguments: args,
22 parameters: args.params, 22 parameters: args.params,
@@ -60,7 +60,7 @@ class RouteDecoder { @@ -60,7 +60,7 @@ class RouteDecoder {
60 final _route = route; 60 final _route = route;
61 if (_route != null) { 61 if (_route != null) {
62 final index = currentTreeBranch.indexOf(_route); 62 final index = currentTreeBranch.indexOf(_route);
63 - currentTreeBranch[index] = _route.copy(arguments: arguments); 63 + currentTreeBranch[index] = _route.copyWith(arguments: arguments);
64 } 64 }
65 } 65 }
66 66
@@ -86,7 +86,6 @@ class ParseRouteTree { @@ -86,7 +86,6 @@ class ParseRouteTree {
86 86
87 RouteDecoder matchRoute(String name, {PageSettings? arguments}) { 87 RouteDecoder matchRoute(String name, {PageSettings? arguments}) {
88 final uri = Uri.parse(name); 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); 89 final split = uri.path.split('/').where((element) => element.isNotEmpty);
91 var curPath = '/'; 90 var curPath = '/';
92 final cumulativePaths = <String>[ 91 final cumulativePaths = <String>[
@@ -106,7 +105,7 @@ class ParseRouteTree { @@ -106,7 +105,7 @@ class ParseRouteTree {
106 .where((element) => element.value != null) 105 .where((element) => element.value != null)
107 106
108 ///Prevent page be disposed 107 ///Prevent page be disposed
109 - .map((e) => MapEntry(e.key, e.value!.copy(key: ValueKey(e.key)))) 108 + .map((e) => MapEntry(e.key, e.value!.copyWith(key: ValueKey(e.key))))
110 .toList(); 109 .toList();
111 110
112 final params = Map<String, String>.from(uri.queryParameters); 111 final params = Map<String, String>.from(uri.queryParameters);
@@ -120,7 +119,7 @@ class ParseRouteTree { @@ -120,7 +119,7 @@ class ParseRouteTree {
120 //copy parameters to all pages. 119 //copy parameters to all pages.
121 final mappedTreeBranch = treeBranch 120 final mappedTreeBranch = treeBranch
122 .map( 121 .map(
123 - (e) => e.value.copy( 122 + (e) => e.value.copyWith(
124 parameters: { 123 parameters: {
125 if (e.value.parameters != null) ...e.value.parameters!, 124 if (e.value.parameters != null) ...e.value.parameters!,
126 ...params, 125 ...params,
@@ -185,8 +184,8 @@ class ParseRouteTree { @@ -185,8 +184,8 @@ class ParseRouteTree {
185 for (var page in route.children) { 184 for (var page in route.children) {
186 // Add Parent middlewares to children 185 // Add Parent middlewares to children
187 final parentMiddlewares = [ 186 final parentMiddlewares = [
188 - if (page.middlewares != null) ...page.middlewares!,  
189 - if (route.middlewares != null) ...route.middlewares! 187 + if (page.middlewares.isNotEmpty) ...page.middlewares,
  188 + if (route.middlewares.isNotEmpty) ...route.middlewares
190 ]; 189 ];
191 result.add( 190 result.add(
192 _addChild( 191 _addChild(
@@ -203,7 +202,7 @@ class ParseRouteTree { @@ -203,7 +202,7 @@ class ParseRouteTree {
203 parentPath, 202 parentPath,
204 [ 203 [
205 ...parentMiddlewares, 204 ...parentMiddlewares,
206 - if (child.middlewares != null) ...child.middlewares!, 205 + if (child.middlewares.isNotEmpty) ...child.middlewares,
207 ], 206 ],
208 )); 207 ));
209 } 208 }
@@ -214,7 +213,7 @@ class ParseRouteTree { @@ -214,7 +213,7 @@ class ParseRouteTree {
214 /// Change the Path for a [GetPage] 213 /// Change the Path for a [GetPage]
215 GetPage _addChild( 214 GetPage _addChild(
216 GetPage origin, String parentPath, List<GetMiddleware> middlewares) { 215 GetPage origin, String parentPath, List<GetMiddleware> middlewares) {
217 - return origin.copy( 216 + return origin.copyWith(
218 middlewares: middlewares, 217 middlewares: middlewares,
219 name: (parentPath + origin.name).replaceAll(r'//', '/'), 218 name: (parentPath + origin.name).replaceAll(r'//', '/'),
220 // key: 219 // key:
@@ -131,7 +131,7 @@ class MiddlewareRunner { @@ -131,7 +131,7 @@ class MiddlewareRunner {
131 131
132 List<GetMiddleware> _getMiddlewares() { 132 List<GetMiddleware> _getMiddlewares() {
133 final _m = _middlewares ?? <GetMiddleware>[]; 133 final _m = _middlewares ?? <GetMiddleware>[];
134 - return _m 134 + return List.of(_m)
135 ..sort( 135 ..sort(
136 (a, b) => (a.priority ?? 0).compareTo(b.priority ?? 0), 136 (a, b) => (a.priority ?? 0).compareTo(b.priority ?? 0),
137 ); 137 );
@@ -248,7 +248,7 @@ class PageRedirect { @@ -248,7 +248,7 @@ class PageRedirect {
248 addPageParameter(route!); 248 addPageParameter(route!);
249 249
250 // No middlewares found return match. 250 // No middlewares found return match.
251 - if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) { 251 + if (match.route!.middlewares.isEmpty) {
252 return false; 252 return false;
253 } 253 }
254 final newSettings = runner.runRedirect(settings!.name); 254 final newSettings = runner.runRedirect(settings!.name);
@@ -4,7 +4,7 @@ version: 5.0.0-beta.52 @@ -4,7 +4,7 @@ version: 5.0.0-beta.52
4 homepage: https://github.com/jonataslaw/getx 4 homepage: https://github.com/jonataslaw/getx
5 5
6 environment: 6 environment:
7 - sdk: '>=2.16.0 <4.0.0' 7 + sdk: '>=2.17.0 <4.0.0'
8 8
9 dependencies: 9 dependencies:
10 flutter: 10 flutter:
@@ -7,7 +7,7 @@ import '../../navigation/utils/wrapper.dart'; @@ -7,7 +7,7 @@ import '../../navigation/utils/wrapper.dart';
7 void main() { 7 void main() {
8 testWidgets("Get.defaultDialog smoke test", (tester) async { 8 testWidgets("Get.defaultDialog smoke test", (tester) async {
9 await tester.pumpWidget(Wrapper(child: Container())); 9 await tester.pumpWidget(Wrapper(child: Container()));
10 - await tester.pump(); 10 + await tester.pumpAndSettle();
11 11
12 final BuildContext context = tester.element(find.byType(Container)); 12 final BuildContext context = tester.element(find.byType(Container));
13 13