Jonny Borges
Committed by GitHub

Merge branch 'master' into master

Showing 82 changed files with 2297 additions and 992 deletions

Too many changes to show.

To preserve performance only 82 of 82+ files are displayed.

No preview for this file type
@@ -23,7 +23,7 @@ jobs: @@ -23,7 +23,7 @@ jobs:
23 # https://github.com/marketplace/actions/flutter-action 23 # https://github.com/marketplace/actions/flutter-action
24 - uses: subosito/flutter-action@v2 24 - uses: subosito/flutter-action@v2
25 with: 25 with:
26 - flutter-version: "3.0.5" 26 + flutter-version: "3.7.3"
27 channel: "stable" 27 channel: "stable"
28 - run: flutter pub get 28 - run: flutter pub get
29 #- run: flutter analyze 29 #- run: flutter analyze
  1 +## [5.0.0-release-candidate-2]
  2 +This version adds built-in support for animation in Flutter in an easy, clear way, and without having to create a StatefulWidget with controllers and animations. All you need to do is call the name of the animation.
  3 +
  4 +If you want to add a "fadeIn" effect to any widget, simply add .fadeIn() to the end of it.
  5 +
  6 +```dart
  7 + Container(
  8 + color: Colors.blue,
  9 + height: 100,
  10 + width: 100,
  11 + ).fadeIn(),
  12 +```
  13 +
  14 +
  15 +https://user-images.githubusercontent.com/35742643/221383556-075a0b71-1617-4a31-a3c7-1acc68732f59.mp4
  16 +
  17 +Maybe you want to merge two or more animations, just concatenate them at the end of the widget.
  18 +
  19 +```dart
  20 + Container(
  21 + color: Colors.blue,
  22 + height: 100,
  23 + width: 100,
  24 + ).fadeIn().bounce(begin: -0.8, end: 0.3),
  25 +```
  26 +
  27 +https://user-images.githubusercontent.com/35742643/221383613-9044c92f-7c6b-48c4-aa79-0a0c20d4068a.mp4
  28 +
  29 +
  30 +Creating animation sequences in Flutter is one of the most painful things to do with the framework. You need to create tons of AnimationControllers. Well, using GetX 5 you just need to tell your animation that it is sequential. Just like that.
  31 +
  32 +```dart
  33 + const FlutterLogo(size: 110)
  34 + .bounce(begin: -0.8, end: 0.4)
  35 + .fadeIn()
  36 + .spin(isSequential: true)
  37 + .wobble(isSequential: true, begin: 0, end: 8)
  38 + .flip(isSequential: true)
  39 + .fadeOut(isSequential: true),
  40 +```
  41 +
  42 +Result:
  43 +
  44 +
  45 +https://user-images.githubusercontent.com/35742643/221393968-20cb2411-516b-44a7-8b85-45090bece532.mp4
  46 +
  47 +
  48 +## [5.0.0-release-candidate]
  49 +Refactor StateManager, RouteManager and InstanceManager from scratch
  50 +Fixed Bugs
  51 +Added a Scopped DI
  52 +Api now uses Navigator 2
  53 +Added new RouteOutlet
  54 +Added a new futurize method to StateMixin, that tracks updates, errors, and states programatically,
  55 +
1 ## [4.6.1] 56 ## [4.6.1]
2 Fix GetConnect on Flutter web 57 Fix GetConnect on Flutter web
3 58
@@ -1274,3 +1274,5 @@ Any contribution is welcome! @@ -1274,3 +1274,5 @@ Any contribution is welcome!
1274 - [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter. 1274 - [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter.
1275 - [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter. 1275 - [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter.
1276 - [A minimal example on dartpad](https://dartpad.dev/2b3d0d6f9d4e312c5fdbefc414c1727e?) - by [Roi Peker](https://github.com/roipeker) 1276 - [A minimal example on dartpad](https://dartpad.dev/2b3d0d6f9d4e312c5fdbefc414c1727e?) - by [Roi Peker](https://github.com/roipeker)
  1277 +- [GetConnect: The best way to perform API operations in Flutter with Get.](https://absyz.com/getconnect-the-best-way-to-perform-api-operations-in-flutter-with-getx/) - by [MD Sarfaraj](https://github.com/socialmad)
  1278 +- [How To Create an App with GetX Architect in Flutter with Get CLI](https://www.youtube.com/watch?v=7mb4qBA7kTk&t=1380s) - by [MD Sarfaraj](https://github.com/socialmad)
1 # Include option is buggy: 1 # Include option is buggy:
2 -include: package:lints/recommended.yaml 2 +include: package:flutter_lints/flutter.yaml
3 # In case the include issue gets fixed, lines below INCLUDE_FIX 3 # In case the include issue gets fixed, lines below INCLUDE_FIX
4 # can be removed 4 # can be removed
@@ -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 + camel_case_types: false
  26 + constant_identifier_names: false
  27 + # avoid_print: false # Uncomment to disable the `avoid_print` rule
  28 + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
  29 +
  30 +# Additional information about this file can be found at
  31 +# https://dart.dev/guides/language/analysis-options
@@ -6,7 +6,7 @@ import 'pt_br.dart'; @@ -6,7 +6,7 @@ import 'pt_br.dart';
6 6
7 class TranslationService extends Translations { 7 class TranslationService extends Translations {
8 static Locale? get locale => Get.deviceLocale; 8 static Locale? get locale => Get.deviceLocale;
9 - static final fallbackLocale = Locale('en', 'US'); 9 + static const fallbackLocale = Locale('en', 'US');
10 @override 10 @override
11 Map<String, Map<String, String>> get keys => { 11 Map<String, Map<String, String>> get keys => {
12 'en_US': en_US, 12 'en_US': en_US,
@@ -6,7 +6,7 @@ import 'routes/app_pages.dart'; @@ -6,7 +6,7 @@ import 'routes/app_pages.dart';
6 import 'shared/logger/logger_utils.dart'; 6 import 'shared/logger/logger_utils.dart';
7 7
8 void main() { 8 void main() {
9 - runApp(MyApp()); 9 + runApp(const MyApp());
10 } 10 }
11 11
12 class MyApp extends StatelessWidget { 12 class MyApp extends StatelessWidget {
@@ -10,7 +10,7 @@ class CountryView extends GetView<HomeController> { @@ -10,7 +10,7 @@ class CountryView extends GetView<HomeController> {
10 @override 10 @override
11 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
12 return Container( 12 return Container(
13 - decoration: BoxDecoration( 13 + decoration: const BoxDecoration(
14 image: DecorationImage( 14 image: DecorationImage(
15 fit: BoxFit.cover, 15 fit: BoxFit.cover,
16 colorFilter: ColorFilter.linearToSrgbGamma(), 16 colorFilter: ColorFilter.linearToSrgbGamma(),
@@ -18,38 +18,36 @@ class CountryView extends GetView<HomeController> { @@ -18,38 +18,36 @@ class CountryView extends GetView<HomeController> {
18 "https://images.pexels.com/photos/3902882/pexels-photo-3902882.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"))), 18 "https://images.pexels.com/photos/3902882/pexels-photo-3902882.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"))),
19 child: BackdropFilter( 19 child: BackdropFilter(
20 filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0), 20 filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
21 - child: Container(  
22 - child: Scaffold( 21 + child: Scaffold(
  22 + backgroundColor: Colors.transparent,
  23 + appBar: AppBar(
  24 + title: Text('corona_by_country'.tr),
23 backgroundColor: Colors.transparent, 25 backgroundColor: Colors.transparent,
24 - appBar: AppBar(  
25 - title: Text('corona_by_country'.tr),  
26 - backgroundColor: Colors.transparent,  
27 - elevation: 0,  
28 - centerTitle: true,  
29 - ),  
30 - body: Center(  
31 - child: ListView.builder(  
32 - itemCount: controller.state.countries.length,  
33 - itemBuilder: (context, index) {  
34 - final country = controller.state.countries[index];  
35 - return ListTile(  
36 - onTap: () async {  
37 - //Get.rootDelegate.toNamed('/home/country');  
38 - final data = await Get.toNamed(  
39 - '/home/country/details?id=$index');  
40 - print(data);  
41 - },  
42 - trailing: CircleAvatar(  
43 - backgroundImage: NetworkImage(  
44 - "https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),  
45 - ),  
46 - title: Text(country.country),  
47 - subtitle: Text(  
48 - // ignore: lines_longer_than_80_chars  
49 - '${'total_infecteds'.tr}${' ${country.totalConfirmed}'}'),  
50 - );  
51 - }),  
52 - ), 26 + elevation: 0,
  27 + centerTitle: true,
  28 + ),
  29 + body: Center(
  30 + child: ListView.builder(
  31 + itemCount: controller.state.countries.length,
  32 + itemBuilder: (context, index) {
  33 + final country = controller.state.countries[index];
  34 + return ListTile(
  35 + onTap: () async {
  36 + //Get.rootDelegate.toNamed('/home/country');
  37 + final data =
  38 + await Get.toNamed('/home/country/details?id=$index');
  39 + Get.log(data);
  40 + },
  41 + trailing: CircleAvatar(
  42 + backgroundImage: NetworkImage(
  43 + "https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),
  44 + ),
  45 + title: Text(country.country),
  46 + subtitle: Text(
  47 + // ignore: lines_longer_than_80_chars
  48 + '${'total_infecteds'.tr}${' ${country.totalConfirmed}'}'),
  49 + );
  50 + }),
53 ), 51 ),
54 ), 52 ),
55 ), 53 ),
@@ -15,77 +15,79 @@ class DetailsView extends GetView<HomeController> { @@ -15,77 +15,79 @@ class DetailsView extends GetView<HomeController> {
15 decoration: BoxDecoration( 15 decoration: BoxDecoration(
16 image: DecorationImage( 16 image: DecorationImage(
17 fit: BoxFit.cover, 17 fit: BoxFit.cover,
18 - colorFilter: ColorFilter.linearToSrgbGamma(), 18 + colorFilter: const ColorFilter.linearToSrgbGamma(),
19 image: NetworkImage( 19 image: NetworkImage(
20 "https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"), 20 "https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),
21 ), 21 ),
22 ), 22 ),
23 child: BackdropFilter( 23 child: BackdropFilter(
24 filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0), 24 filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
25 - child: Container(  
26 - child: Scaffold(  
27 - backgroundColor: Colors.transparent,  
28 - appBar: AppBar(  
29 - title: Text('details'.tr),  
30 - backgroundColor: Colors.black12,  
31 - elevation: 0,  
32 - centerTitle: true,  
33 - ),  
34 - body: Center(  
35 - child: Column(  
36 - mainAxisAlignment: MainAxisAlignment.center,  
37 - children: [  
38 - Text(  
39 - '${country.country}',  
40 - style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),  
41 - ),  
42 - SizedBox(  
43 - height: 35,  
44 - ),  
45 - Text(  
46 - 'total_confirmed'.tr,  
47 - style: TextStyle(  
48 - fontSize: 25,  
49 - ),  
50 - ),  
51 - Text(  
52 - '${country.totalConfirmed}',  
53 - style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),  
54 - ),  
55 - SizedBox(  
56 - height: 10,  
57 - ),  
58 - Text(  
59 - 'total_deaths'.tr,  
60 - style: TextStyle(  
61 - fontSize: 25,  
62 - ),  
63 - ),  
64 - Text(  
65 - '${country.totalDeaths}',  
66 - style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),  
67 - ),  
68 - SizedBox(  
69 - height: 10, 25 + child: Scaffold(
  26 + backgroundColor: Colors.transparent,
  27 + appBar: AppBar(
  28 + title: Text('details'.tr),
  29 + backgroundColor: Colors.black12,
  30 + elevation: 0,
  31 + centerTitle: true,
  32 + ),
  33 + body: Center(
  34 + child: Column(
  35 + mainAxisAlignment: MainAxisAlignment.center,
  36 + children: [
  37 + Text(
  38 + country.country,
  39 + style:
  40 + const TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
  41 + ),
  42 + const SizedBox(
  43 + height: 35,
  44 + ),
  45 + Text(
  46 + 'total_confirmed'.tr,
  47 + style: const TextStyle(
  48 + fontSize: 25,
70 ), 49 ),
71 - Text(  
72 - 'total_recovered'.tr,  
73 - style: TextStyle(  
74 - fontSize: 25,  
75 - ), 50 + ),
  51 + Text(
  52 + '${country.totalConfirmed}',
  53 + style:
  54 + const TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
  55 + ),
  56 + const SizedBox(
  57 + height: 10,
  58 + ),
  59 + Text(
  60 + 'total_deaths'.tr,
  61 + style: const TextStyle(
  62 + fontSize: 25,
76 ), 63 ),
77 - Text(  
78 - '${country.totalRecovered}',  
79 - style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold), 64 + ),
  65 + Text(
  66 + '${country.totalDeaths}',
  67 + style:
  68 + const TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
  69 + ),
  70 + const SizedBox(
  71 + height: 10,
  72 + ),
  73 + Text(
  74 + 'total_recovered'.tr,
  75 + style: const TextStyle(
  76 + fontSize: 25,
80 ), 77 ),
81 - TextButton(  
82 - onPressed: () {  
83 - Get.back(result: 'djsoidjsoidj');  
84 - },  
85 - child: Text('back'))  
86 - ],  
87 - )),  
88 - ), 78 + ),
  79 + Text(
  80 + '${country.totalRecovered}',
  81 + style:
  82 + const TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
  83 + ),
  84 + TextButton(
  85 + onPressed: () {
  86 + Get.back(result: 'djsoidjsoidj');
  87 + },
  88 + child: const Text('back'))
  89 + ],
  90 + )),
89 ), 91 ),
90 ), 92 ),
91 ); 93 );
@@ -9,7 +9,7 @@ class HomeView extends GetView<HomeController> { @@ -9,7 +9,7 @@ class HomeView extends GetView<HomeController> {
9 @override 9 @override
10 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
11 return Container( 11 return Container(
12 - decoration: BoxDecoration( 12 + decoration: const BoxDecoration(
13 color: Colors.white, 13 color: Colors.white,
14 image: DecorationImage( 14 image: DecorationImage(
15 fit: BoxFit.cover, 15 fit: BoxFit.cover,
@@ -22,7 +22,7 @@ class HomeView extends GetView<HomeController> { @@ -22,7 +22,7 @@ class HomeView extends GetView<HomeController> {
22 backgroundColor: Colors.transparent, 22 backgroundColor: Colors.transparent,
23 appBar: AppBar( 23 appBar: AppBar(
24 leading: IconButton( 24 leading: IconButton(
25 - icon: Icon(Icons.add), 25 + icon: const Icon(Icons.add),
26 onPressed: () { 26 onPressed: () {
27 Get.snackbar('title', 'message'); 27 Get.snackbar('title', 'message');
28 }, 28 },
@@ -38,43 +38,45 @@ class HomeView extends GetView<HomeController> { @@ -38,43 +38,45 @@ class HomeView extends GetView<HomeController> {
38 return Column( 38 return Column(
39 mainAxisAlignment: MainAxisAlignment.center, 39 mainAxisAlignment: MainAxisAlignment.center,
40 children: [ 40 children: [
41 - SizedBox( 41 + const SizedBox(
42 height: 100, 42 height: 100,
43 ), 43 ),
44 Text( 44 Text(
45 'total_confirmed'.tr, 45 'total_confirmed'.tr,
46 - style: TextStyle( 46 + style: const TextStyle(
47 fontSize: 30, 47 fontSize: 30,
48 ), 48 ),
49 ), 49 ),
50 Text( 50 Text(
51 '${state!.global.totalConfirmed}', 51 '${state!.global.totalConfirmed}',
52 - style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 52 + style: const TextStyle(
  53 + fontSize: 45, fontWeight: FontWeight.bold),
53 ), 54 ),
54 - SizedBox( 55 + const SizedBox(
55 height: 10, 56 height: 10,
56 ), 57 ),
57 Text( 58 Text(
58 'total_deaths'.tr, 59 'total_deaths'.tr,
59 - style: TextStyle( 60 + style: const TextStyle(
60 fontSize: 30, 61 fontSize: 30,
61 ), 62 ),
62 ), 63 ),
63 Text( 64 Text(
64 '${state.global.totalDeaths}', 65 '${state.global.totalDeaths}',
65 - style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 66 + style: const TextStyle(
  67 + fontSize: 45, fontWeight: FontWeight.bold),
66 ), 68 ),
67 - SizedBox( 69 + const SizedBox(
68 height: 10, 70 height: 10,
69 ), 71 ),
70 OutlinedButton( 72 OutlinedButton(
71 style: OutlinedButton.styleFrom( 73 style: OutlinedButton.styleFrom(
72 - textStyle: TextStyle(color: Colors.black),  
73 - side: BorderSide( 74 + textStyle: const TextStyle(color: Colors.black),
  75 + side: const BorderSide(
74 color: Colors.deepPurple, 76 color: Colors.deepPurple,
75 width: 3, 77 width: 3,
76 ), 78 ),
77 - shape: StadiumBorder(), 79 + shape: const StadiumBorder(),
78 ), 80 ),
79 onPressed: () async { 81 onPressed: () async {
80 //await Navigation Get.rootDelegate.toNamed('/home/country'); 82 //await Navigation Get.rootDelegate.toNamed('/home/country');
@@ -82,7 +84,7 @@ class HomeView extends GetView<HomeController> { @@ -82,7 +84,7 @@ class HomeView extends GetView<HomeController> {
82 }, 84 },
83 child: Text( 85 child: Text(
84 'fetch_country'.tr, 86 'fetch_country'.tr,
85 - style: TextStyle( 87 + style: const TextStyle(
86 fontWeight: FontWeight.bold, 88 fontWeight: FontWeight.bold,
87 color: Colors.black, 89 color: Colors.black,
88 ), 90 ),
@@ -90,17 +92,17 @@ class HomeView extends GetView<HomeController> { @@ -90,17 +92,17 @@ class HomeView extends GetView<HomeController> {
90 ), 92 ),
91 OutlinedButton( 93 OutlinedButton(
92 style: OutlinedButton.styleFrom( 94 style: OutlinedButton.styleFrom(
93 - textStyle: TextStyle(color: Colors.black),  
94 - side: BorderSide( 95 + textStyle: const TextStyle(color: Colors.black),
  96 + side: const BorderSide(
95 color: Colors.deepPurple, 97 color: Colors.deepPurple,
96 width: 3, 98 width: 3,
97 ), 99 ),
98 - shape: StadiumBorder(), 100 + shape: const StadiumBorder(),
99 ), 101 ),
100 onPressed: () { 102 onPressed: () {
101 - Get.updateLocale(Locale('pt', 'BR')); 103 + Get.updateLocale(const Locale('pt', 'BR'));
102 }, 104 },
103 - child: Text( 105 + child: const Text(
104 'Update language to Portuguese', 106 'Update language to Portuguese',
105 style: TextStyle( 107 style: TextStyle(
106 fontWeight: FontWeight.bold, 108 fontWeight: FontWeight.bold,
@@ -14,16 +14,16 @@ class AppPages { @@ -14,16 +14,16 @@ class AppPages {
14 static final routes = [ 14 static final routes = [
15 GetPage( 15 GetPage(
16 name: Routes.HOME, 16 name: Routes.HOME,
17 - page: () => HomeView(), 17 + page: () => const HomeView(),
18 binding: HomeBinding(), 18 binding: HomeBinding(),
19 children: [ 19 children: [
20 GetPage( 20 GetPage(
21 name: Routes.COUNTRY, 21 name: Routes.COUNTRY,
22 - page: () => CountryView(), 22 + page: () => const CountryView(),
23 children: [ 23 children: [
24 GetPage( 24 GetPage(
25 name: Routes.DETAILS, 25 name: Routes.DETAILS,
26 - page: () => DetailsView(), 26 + page: () => const DetailsView(),
27 ), 27 ),
28 ], 28 ],
29 ), 29 ),
1 mixin Logger { 1 mixin Logger {
2 // Sample of abstract logging function 2 // Sample of abstract logging function
3 static void write(String text, {bool isError = false}) { 3 static void write(String text, {bool isError = false}) {
  4 + // ignore: avoid_print
4 Future.microtask(() => print('** $text. isError: [$isError]')); 5 Future.microtask(() => print('** $text. isError: [$isError]'));
5 } 6 }
6 } 7 }
@@ -38,6 +38,7 @@ dev_dependencies: @@ -38,6 +38,7 @@ dev_dependencies:
38 flutter_test: 38 flutter_test:
39 sdk: flutter 39 sdk: flutter
40 get_test: 4.0.1 40 get_test: 4.0.1
  41 + flutter_lints: ^2.0.1
41 42
42 # For information on the generic Dart part of this file, see the 43 # For information on the generic Dart part of this file, see the
43 # following page: https://dart.dev/tools/pub/pubspec 44 # following page: https://dart.dev/tools/pub/pubspec
@@ -3,13 +3,11 @@ import 'dart:io'; @@ -3,13 +3,11 @@ import 'dart:io';
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:flutter_test/flutter_test.dart'; 4 import 'package:flutter_test/flutter_test.dart';
5 import 'package:get/get.dart'; 5 import 'package:get/get.dart';
  6 +import 'package:get_demo/pages/home/domain/adapters/repository_adapter.dart';
  7 +import 'package:get_demo/pages/home/domain/entity/cases_model.dart';
  8 +import 'package:get_demo/pages/home/presentation/controllers/home_controller.dart';
6 // import 'package:get_demo/routes/app_pages.dart'; 9 // import 'package:get_demo/routes/app_pages.dart';
7 // import 'package:get_test/get_test.dart'; 10 // import 'package:get_test/get_test.dart';
8 -import 'package:matcher/matcher.dart' as m;  
9 -  
10 -import '../lib/pages/home/domain/adapters/repository_adapter.dart';  
11 -import '../lib/pages/home/domain/entity/cases_model.dart';  
12 -import '../lib/pages/home/presentation/controllers/home_controller.dart';  
13 11
14 class MockRepositorySuccess implements IHomeRepository { 12 class MockRepositorySuccess implements IHomeRepository {
15 @override 13 @override
@@ -57,7 +55,7 @@ void main() { @@ -57,7 +55,7 @@ void main() {
57 test('Test Controller', () async { 55 test('Test Controller', () async {
58 /// Controller can't be on memory 56 /// Controller can't be on memory
59 expect(() => Get.find<HomeController>(tag: 'success'), 57 expect(() => Get.find<HomeController>(tag: 'success'),
60 - throwsA(m.TypeMatcher<String>())); 58 + throwsA(const TypeMatcher<String>()));
61 59
62 /// binding will put the controller on memory 60 /// binding will put the controller on memory
63 binding.dependencies(); 61 binding.dependencies();
@@ -72,7 +70,7 @@ void main() { @@ -72,7 +70,7 @@ void main() {
72 expect(controller.status.isLoading, true); 70 expect(controller.status.isLoading, true);
73 71
74 /// await time request 72 /// await time request
75 - await Future.delayed(Duration(milliseconds: 100)); 73 + await Future.delayed(const Duration(milliseconds: 100));
76 74
77 /// test if status is success 75 /// test if status is success
78 expect(controller.status.isSuccess, true); 76 expect(controller.status.isSuccess, true);
1 // This is a generated file; do not edit or check into version control. 1 // This is a generated file; do not edit or check into version control.
2 FLUTTER_ROOT=/Users/jonatasborges/flutter 2 FLUTTER_ROOT=/Users/jonatasborges/flutter
3 -FLUTTER_APPLICATION_PATH=/Users/jonatasborges/consertar/getx/example_nav2 3 +FLUTTER_APPLICATION_PATH=/Users/jonatasborges/getx-parse/getx/example_nav2
4 COCOAPODS_PARALLEL_CODE_SIGN=true 4 COCOAPODS_PARALLEL_CODE_SIGN=true
5 -FLUTTER_TARGET=/Users/jonatasborges/consertar/getx/example_nav2/lib/main.dart 5 +FLUTTER_TARGET=lib/main.dart
6 FLUTTER_BUILD_DIR=build 6 FLUTTER_BUILD_DIR=build
7 FLUTTER_BUILD_NAME=1.0.0 7 FLUTTER_BUILD_NAME=1.0.0
8 FLUTTER_BUILD_NUMBER=1 8 FLUTTER_BUILD_NUMBER=1
9 EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 9 EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
10 EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 10 EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
11 -DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==  
12 DART_OBFUSCATION=false 11 DART_OBFUSCATION=false
13 TRACK_WIDGET_CREATION=true 12 TRACK_WIDGET_CREATION=true
14 TREE_SHAKE_ICONS=false 13 TREE_SHAKE_ICONS=false
15 -PACKAGE_CONFIG=/Users/jonatasborges/consertar/getx/example_nav2/.dart_tool/package_config.json 14 +PACKAGE_CONFIG=.dart_tool/package_config.json
1 #!/bin/sh 1 #!/bin/sh
2 # This is a generated file; do not edit or check into version control. 2 # This is a generated file; do not edit or check into version control.
3 export "FLUTTER_ROOT=/Users/jonatasborges/flutter" 3 export "FLUTTER_ROOT=/Users/jonatasborges/flutter"
4 -export "FLUTTER_APPLICATION_PATH=/Users/jonatasborges/consertar/getx/example_nav2" 4 +export "FLUTTER_APPLICATION_PATH=/Users/jonatasborges/getx-parse/getx/example_nav2"
5 export "COCOAPODS_PARALLEL_CODE_SIGN=true" 5 export "COCOAPODS_PARALLEL_CODE_SIGN=true"
6 -export "FLUTTER_TARGET=/Users/jonatasborges/consertar/getx/example_nav2/lib/main.dart" 6 +export "FLUTTER_TARGET=lib/main.dart"
7 export "FLUTTER_BUILD_DIR=build" 7 export "FLUTTER_BUILD_DIR=build"
8 export "FLUTTER_BUILD_NAME=1.0.0" 8 export "FLUTTER_BUILD_NAME=1.0.0"
9 export "FLUTTER_BUILD_NUMBER=1" 9 export "FLUTTER_BUILD_NUMBER=1"
10 -export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="  
11 export "DART_OBFUSCATION=false" 10 export "DART_OBFUSCATION=false"
12 export "TRACK_WIDGET_CREATION=true" 11 export "TRACK_WIDGET_CREATION=true"
13 export "TREE_SHAKE_ICONS=false" 12 export "TREE_SHAKE_ICONS=false"
14 -export "PACKAGE_CONFIG=/Users/jonatasborges/consertar/getx/example_nav2/.dart_tool/package_config.json" 13 +export "PACKAGE_CONFIG=.dart_tool/package_config.json"
@@ -8,7 +8,7 @@ class DashboardController extends GetxController { @@ -8,7 +8,7 @@ class DashboardController extends GetxController {
8 void onReady() { 8 void onReady() {
9 super.onReady(); 9 super.onReady();
10 Timer.periodic( 10 Timer.periodic(
11 - Duration(seconds: 1), 11 + const Duration(seconds: 1),
12 (timer) { 12 (timer) {
13 now.value = DateTime.now(); 13 now.value = DateTime.now();
14 }, 14 },
@@ -4,6 +4,8 @@ import 'package:get/get.dart'; @@ -4,6 +4,8 @@ import 'package:get/get.dart';
4 import '../controllers/dashboard_controller.dart'; 4 import '../controllers/dashboard_controller.dart';
5 5
6 class DashboardView extends GetView<DashboardController> { 6 class DashboardView extends GetView<DashboardController> {
  7 + const DashboardView({super.key});
  8 +
7 @override 9 @override
8 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
9 return Scaffold( 11 return Scaffold(
@@ -12,7 +14,7 @@ class DashboardView extends GetView<DashboardController> { @@ -12,7 +14,7 @@ class DashboardView extends GetView<DashboardController> {
12 () => Column( 14 () => Column(
13 mainAxisSize: MainAxisSize.min, 15 mainAxisSize: MainAxisSize.min,
14 children: [ 16 children: [
15 - Text( 17 + const Text(
16 'DashboardView is working', 18 'DashboardView is working',
17 style: TextStyle(fontSize: 20), 19 style: TextStyle(fontSize: 20),
18 ), 20 ),
@@ -14,7 +14,6 @@ class HomeView extends GetView<HomeController> { @@ -14,7 +14,6 @@ class HomeView extends GetView<HomeController> {
14 final delegate = context.navigation; 14 final delegate = context.navigation;
15 //This router outlet handles the appbar and the bottom navigation bar 15 //This router outlet handles the appbar and the bottom navigation bar
16 final currentLocation = context.location; 16 final currentLocation = context.location;
17 - print(currentLocation);  
18 var currentIndex = 0; 17 var currentIndex = 0;
19 if (currentLocation.startsWith(Routes.products) == true) { 18 if (currentLocation.startsWith(Routes.products) == true) {
20 currentIndex = 2; 19 currentIndex = 2;
@@ -46,7 +45,7 @@ class HomeView extends GetView<HomeController> { @@ -46,7 +45,7 @@ class HomeView extends GetView<HomeController> {
46 default: 45 default:
47 } 46 }
48 }, 47 },
49 - items: [ 48 + items: const [
50 // _Paths.HOME + [Empty] 49 // _Paths.HOME + [Empty]
51 BottomNavigationBarItem( 50 BottomNavigationBarItem(
52 icon: Icon(Icons.home), 51 icon: Icon(Icons.home),
@@ -6,6 +6,8 @@ import '../../../routes/app_pages.dart'; @@ -6,6 +6,8 @@ import '../../../routes/app_pages.dart';
6 import '../controllers/login_controller.dart'; 6 import '../controllers/login_controller.dart';
7 7
8 class LoginView extends GetView<LoginController> { 8 class LoginView extends GetView<LoginController> {
  9 + const LoginView({super.key});
  10 +
9 @override 11 @override
10 Widget build(BuildContext context) { 12 Widget build(BuildContext context) {
11 return Scaffold( 13 return Scaffold(
@@ -25,7 +27,7 @@ class LoginView extends GetView<LoginController> { @@ -25,7 +27,7 @@ class LoginView extends GetView<LoginController> {
25 }, 27 },
26 ), 28 ),
27 MaterialButton( 29 MaterialButton(
28 - child: Text( 30 + child: const Text(
29 'Do LOGIN !!', 31 'Do LOGIN !!',
30 style: TextStyle(color: Colors.blue, fontSize: 20), 32 style: TextStyle(color: Colors.blue, fontSize: 20),
31 ), 33 ),
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 -  
3 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
4 3
5 import '../controllers/product_details_controller.dart'; 4 import '../controllers/product_details_controller.dart';
6 5
7 class ProductDetailsView extends GetWidget<ProductDetailsController> { 6 class ProductDetailsView extends GetWidget<ProductDetailsController> {
  7 + const ProductDetailsView({super.key});
  8 +
8 @override 9 @override
9 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
10 return Scaffold( 11 return Scaffold(
@@ -12,7 +13,7 @@ class ProductDetailsView extends GetWidget<ProductDetailsController> { @@ -12,7 +13,7 @@ class ProductDetailsView extends GetWidget<ProductDetailsController> {
12 child: Column( 13 child: Column(
13 mainAxisSize: MainAxisSize.min, 14 mainAxisSize: MainAxisSize.min,
14 children: [ 15 children: [
15 - Text( 16 + const Text(
16 'ProductDetailsView is working', 17 'ProductDetailsView is working',
17 style: TextStyle(fontSize: 20), 18 style: TextStyle(fontSize: 20),
18 ), 19 ),
@@ -11,13 +11,13 @@ class ProductsView extends GetView<ProductsController> { @@ -11,13 +11,13 @@ class ProductsView extends GetView<ProductsController> {
11 return Scaffold( 11 return Scaffold(
12 floatingActionButton: FloatingActionButton.extended( 12 floatingActionButton: FloatingActionButton.extended(
13 onPressed: () => controller.loadDemoProductsFromSomeWhere(), 13 onPressed: () => controller.loadDemoProductsFromSomeWhere(),
14 - label: Text('Add'), 14 + label: const Text('Add'),
15 ), 15 ),
16 body: Column( 16 body: Column(
17 children: [ 17 children: [
18 - Hero( 18 + const Hero(
19 tag: 'heroLogo', 19 tag: 'heroLogo',
20 - child: const FlutterLogo(), 20 + child: FlutterLogo(),
21 ), 21 ),
22 Expanded( 22 Expanded(
23 child: Obx( 23 child: Obx(
@@ -5,6 +5,8 @@ import '../../../routes/app_pages.dart'; @@ -5,6 +5,8 @@ import '../../../routes/app_pages.dart';
5 import '../controllers/profile_controller.dart'; 5 import '../controllers/profile_controller.dart';
6 6
7 class ProfileView extends GetView<ProfileController> { 7 class ProfileView extends GetView<ProfileController> {
  8 + const ProfileView({super.key});
  9 +
8 @override 10 @override
9 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
10 return Scaffold( 12 return Scaffold(
@@ -13,16 +15,16 @@ class ProfileView extends GetView<ProfileController> { @@ -13,16 +15,16 @@ class ProfileView extends GetView<ProfileController> {
13 child: Column( 15 child: Column(
14 mainAxisSize: MainAxisSize.min, 16 mainAxisSize: MainAxisSize.min,
15 children: [ 17 children: [
16 - Text( 18 + const Text(
17 'ProfileView is working', 19 'ProfileView is working',
18 style: TextStyle(fontSize: 20), 20 style: TextStyle(fontSize: 20),
19 ), 21 ),
20 - Hero( 22 + const Hero(
21 tag: 'heroLogo', 23 tag: 'heroLogo',
22 - child: const FlutterLogo(), 24 + child: FlutterLogo(),
23 ), 25 ),
24 MaterialButton( 26 MaterialButton(
25 - child: Text('Show a test dialog'), 27 + child: const Text('Show a test dialog'),
26 onPressed: () { 28 onPressed: () {
27 //shows a dialog 29 //shows a dialog
28 Get.defaultDialog( 30 Get.defaultDialog(
@@ -32,7 +34,7 @@ class ProfileView extends GetView<ProfileController> { @@ -32,7 +34,7 @@ class ProfileView extends GetView<ProfileController> {
32 }, 34 },
33 ), 35 ),
34 MaterialButton( 36 MaterialButton(
35 - child: Text('Show a test dialog in Home router outlet'), 37 + child: const Text('Show a test dialog in Home router outlet'),
36 onPressed: () { 38 onPressed: () {
37 //shows a dialog 39 //shows a dialog
38 40
@@ -10,11 +10,6 @@ class RootController extends GetxController { @@ -10,11 +10,6 @@ class RootController extends GetxController {
10 } 10 }
11 11
12 @override 12 @override
13 - void onReady() {  
14 - super.onReady();  
15 - }  
16 -  
17 - @override  
18 void onClose() {} 13 void onClose() {}
19 void increment() => count.value++; 14 void increment() => count.value++;
20 } 15 }
@@ -19,7 +19,7 @@ class DrawerWidget extends StatelessWidget { @@ -19,7 +19,7 @@ class DrawerWidget extends StatelessWidget {
19 color: Colors.red, 19 color: Colors.red,
20 ), 20 ),
21 ListTile( 21 ListTile(
22 - title: Text('Home'), 22 + title: const Text('Home'),
23 onTap: () { 23 onTap: () {
24 Get.toNamed(Routes.home); 24 Get.toNamed(Routes.home);
25 //to close the drawer 25 //to close the drawer
@@ -28,7 +28,7 @@ class DrawerWidget extends StatelessWidget { @@ -28,7 +28,7 @@ class DrawerWidget extends StatelessWidget {
28 }, 28 },
29 ), 29 ),
30 ListTile( 30 ListTile(
31 - title: Text('Settings'), 31 + title: const Text('Settings'),
32 onTap: () { 32 onTap: () {
33 Get.toNamed(Routes.settings); 33 Get.toNamed(Routes.settings);
34 //to close the drawer 34 //to close the drawer
@@ -38,7 +38,7 @@ class DrawerWidget extends StatelessWidget { @@ -38,7 +38,7 @@ class DrawerWidget extends StatelessWidget {
38 ), 38 ),
39 if (AuthService.to.isLoggedInValue) 39 if (AuthService.to.isLoggedInValue)
40 ListTile( 40 ListTile(
41 - title: Text( 41 + title: const Text(
42 'Logout', 42 'Logout',
43 style: TextStyle( 43 style: TextStyle(
44 color: Colors.red, 44 color: Colors.red,
@@ -54,7 +54,7 @@ class DrawerWidget extends StatelessWidget { @@ -54,7 +54,7 @@ class DrawerWidget extends StatelessWidget {
54 ), 54 ),
55 if (!AuthService.to.isLoggedInValue) 55 if (!AuthService.to.isLoggedInValue)
56 ListTile( 56 ListTile(
57 - title: Text( 57 + title: const Text(
58 'Login', 58 'Login',
59 style: TextStyle( 59 style: TextStyle(
60 color: Colors.blue, 60 color: Colors.blue,
@@ -6,6 +6,8 @@ import '../controllers/root_controller.dart'; @@ -6,6 +6,8 @@ import '../controllers/root_controller.dart';
6 import 'drawer.dart'; 6 import 'drawer.dart';
7 7
8 class RootView extends GetView<RootController> { 8 class RootView extends GetView<RootController> {
  9 + const RootView({super.key});
  10 +
9 @override 11 @override
10 Widget build(BuildContext context) { 12 Widget build(BuildContext context) {
11 return RouterOutlet.builder( 13 return RouterOutlet.builder(
@@ -13,7 +15,7 @@ class RootView extends GetView<RootController> { @@ -13,7 +15,7 @@ class RootView extends GetView<RootController> {
13 builder: (context) { 15 builder: (context) {
14 final title = context.location; 16 final title = context.location;
15 return Scaffold( 17 return Scaffold(
16 - drawer: DrawerWidget(), 18 + drawer: const DrawerWidget(),
17 appBar: AppBar( 19 appBar: AppBar(
18 title: Text(title), 20 title: Text(title),
19 centerTitle: true, 21 centerTitle: true,
@@ -10,11 +10,6 @@ class SettingsController extends GetxController { @@ -10,11 +10,6 @@ class SettingsController extends GetxController {
10 } 10 }
11 11
12 @override 12 @override
13 - void onReady() {  
14 - super.onReady();  
15 - }  
16 -  
17 - @override  
18 void onClose() {} 13 void onClose() {}
19 void increment() => count.value++; 14 void increment() => count.value++;
20 } 15 }
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 -  
3 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
4 3
5 import '../controllers/settings_controller.dart'; 4 import '../controllers/settings_controller.dart';
6 5
7 class SettingsView extends GetView<SettingsController> { 6 class SettingsView extends GetView<SettingsController> {
  7 + const SettingsView({super.key});
  8 +
8 @override 9 @override
9 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
10 - return Scaffold( 11 + return const Scaffold(
11 body: Center( 12 body: Center(
12 child: Text( 13 child: Text(
13 'SettingsView is working', 14 'SettingsView is working',
@@ -18,11 +18,11 @@ class SplashService extends GetxService { @@ -18,11 +18,11 @@ class SplashService extends GetxService {
18 18
19 Future<void> _initFunction() async { 19 Future<void> _initFunction() async {
20 final t = Timer.periodic( 20 final t = Timer.periodic(
21 - Duration(milliseconds: 500), 21 + const Duration(milliseconds: 500),
22 (t) => _changeActiveString(), 22 (t) => _changeActiveString(),
23 ); 23 );
24 //simulate some long running operation 24 //simulate some long running operation
25 - await Future.delayed(Duration(seconds: 5)); 25 + await Future.delayed(const Duration(seconds: 5));
26 //cancel the timer once we are done 26 //cancel the timer once we are done
27 t.cancel(); 27 t.cancel();
28 } 28 }
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 -  
3 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
4 3
5 import '../controllers/splash_service.dart'; 4 import '../controllers/splash_service.dart';
6 5
7 class SplashView extends GetView<SplashService> { 6 class SplashView extends GetView<SplashService> {
  7 + const SplashView({super.key});
  8 +
8 @override 9 @override
9 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
10 return Scaffold( 11 return Scaffold(
@@ -15,10 +16,10 @@ class SplashView extends GetView<SplashService> { @@ -15,10 +16,10 @@ class SplashView extends GetView<SplashService> {
15 Obx( 16 Obx(
16 () => Text( 17 () => Text(
17 controller.welcomeStr[controller.activeStr.value], 18 controller.welcomeStr[controller.activeStr.value],
18 - style: TextStyle(fontSize: 20), 19 + style: const TextStyle(fontSize: 20),
19 ), 20 ),
20 ), 21 ),
21 - CircularProgressIndicator(), 22 + const CircularProgressIndicator(),
22 ], 23 ],
23 ), 24 ),
24 ), 25 ),
@@ -28,7 +28,7 @@ class AppPages { @@ -28,7 +28,7 @@ class AppPages {
28 static final routes = [ 28 static final routes = [
29 GetPage( 29 GetPage(
30 name: '/', 30 name: '/',
31 - page: () => RootView(), 31 + page: () => const RootView(),
32 bindings: [RootBinding()], 32 bindings: [RootBinding()],
33 participatesInRootNavigator: true, 33 participatesInRootNavigator: true,
34 preventDuplicates: true, 34 preventDuplicates: true,
@@ -39,7 +39,7 @@ class AppPages { @@ -39,7 +39,7 @@ class AppPages {
39 EnsureNotAuthedMiddleware(), 39 EnsureNotAuthedMiddleware(),
40 ], 40 ],
41 name: _Paths.login, 41 name: _Paths.login,
42 - page: () => LoginView(), 42 + page: () => const LoginView(),
43 bindings: [LoginBinding()], 43 bindings: [LoginBinding()],
44 ), 44 ),
45 GetPage( 45 GetPage(
@@ -53,7 +53,7 @@ class AppPages { @@ -53,7 +53,7 @@ class AppPages {
53 children: [ 53 children: [
54 GetPage( 54 GetPage(
55 name: _Paths.dashboard, 55 name: _Paths.dashboard,
56 - page: () => DashboardView(), 56 + page: () => const DashboardView(),
57 bindings: [ 57 bindings: [
58 DashboardBinding(), 58 DashboardBinding(),
59 ], 59 ],
@@ -64,7 +64,7 @@ class AppPages { @@ -64,7 +64,7 @@ class AppPages {
64 EnsureAuthMiddleware(), 64 EnsureAuthMiddleware(),
65 ], 65 ],
66 name: _Paths.profile, 66 name: _Paths.profile,
67 - page: () => ProfileView(), 67 + page: () => const ProfileView(),
68 title: 'Profile', 68 title: 'Profile',
69 transition: Transition.size, 69 transition: Transition.size,
70 bindings: [ProfileBinding()], 70 bindings: [ProfileBinding()],
@@ -82,8 +82,8 @@ class AppPages { @@ -82,8 +82,8 @@ class AppPages {
82 name: _Paths.productDetails, 82 name: _Paths.productDetails,
83 transition: Transition.cupertino, 83 transition: Transition.cupertino,
84 showCupertinoParallax: true, 84 showCupertinoParallax: true,
85 - page: () => ProductDetailsView(),  
86 - bindings: [], 85 + page: () => const ProductDetailsView(),
  86 + bindings: const [],
87 middlewares: [ 87 middlewares: [
88 //only enter this route when authed 88 //only enter this route when authed
89 EnsureAuthMiddleware(), 89 EnsureAuthMiddleware(),
@@ -95,7 +95,7 @@ class AppPages { @@ -95,7 +95,7 @@ class AppPages {
95 ), 95 ),
96 GetPage( 96 GetPage(
97 name: _Paths.settings, 97 name: _Paths.settings,
98 - page: () => SettingsView(), 98 + page: () => const SettingsView(),
99 bindings: [ 99 bindings: [
100 SettingsBinding(), 100 SettingsBinding(),
101 ], 101 ],
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 /// injection, and route management in a quick and practical way. 3 /// injection, and route management in a quick and practical way.
4 library get; 4 library get;
5 5
  6 +export 'get_animations/index.dart';
6 export 'get_common/get_reset.dart'; 7 export 'get_common/get_reset.dart';
7 export 'get_connect/connect.dart'; 8 export 'get_connect/connect.dart';
8 export 'get_core/get_core.dart'; 9 export 'get_core/get_core.dart';
  1 +import 'dart:math';
  2 +import 'dart:ui';
  3 +
  4 +import 'package:flutter/widgets.dart';
  5 +
  6 +import 'get_animated_builder.dart';
  7 +
  8 +typedef OffsetBuilder = Offset Function(BuildContext, double);
  9 +
  10 +class FadeInAnimation extends OpacityAnimation {
  11 + FadeInAnimation({
  12 + super.key,
  13 + required super.duration,
  14 + required super.delay,
  15 + required super.child,
  16 + super.onComplete,
  17 + super.begin = 0,
  18 + super.end = 1,
  19 + super.idleValue = 0,
  20 + });
  21 +}
  22 +
  23 +class FadeOutAnimation extends OpacityAnimation {
  24 + FadeOutAnimation({
  25 + super.key,
  26 + required super.duration,
  27 + required super.delay,
  28 + required super.child,
  29 + super.onComplete,
  30 + super.begin = 1,
  31 + super.end = 0,
  32 + super.idleValue = 1,
  33 + });
  34 +}
  35 +
  36 +class OpacityAnimation extends GetAnimatedBuilder<double> {
  37 + OpacityAnimation({
  38 + super.key,
  39 + required super.duration,
  40 + required super.delay,
  41 + required super.child,
  42 + required super.onComplete,
  43 + required double begin,
  44 + required double end,
  45 + required super.idleValue,
  46 + }) : super(
  47 + tween: Tween<double>(begin: begin, end: end),
  48 + builder: (context, value, child) {
  49 + return Opacity(
  50 + opacity: value,
  51 + child: child!,
  52 + );
  53 + },
  54 + );
  55 +}
  56 +
  57 +class RotateAnimation extends GetAnimatedBuilder<double> {
  58 + RotateAnimation({
  59 + super.key,
  60 + required super.duration,
  61 + required super.delay,
  62 + required super.child,
  63 + super.onComplete,
  64 + required double begin,
  65 + required double end,
  66 + super.idleValue = 0,
  67 + }) : super(
  68 + builder: (context, value, child) => Transform.rotate(
  69 + angle: value,
  70 + child: child,
  71 + ),
  72 + tween: Tween<double>(begin: begin, end: end),
  73 + );
  74 +}
  75 +
  76 +class ScaleAnimation extends GetAnimatedBuilder<double> {
  77 + ScaleAnimation({
  78 + super.key,
  79 + required super.duration,
  80 + required super.delay,
  81 + required super.child,
  82 + super.onComplete,
  83 + required double begin,
  84 + required double end,
  85 + super.idleValue = 0,
  86 + }) : super(
  87 + builder: (context, value, child) => Transform.scale(
  88 + scale: value,
  89 + child: child,
  90 + ),
  91 + tween: Tween<double>(begin: begin, end: end),
  92 + );
  93 +}
  94 +
  95 +// class SlideAnimation extends GetAnimatedBuilder<Offset> {
  96 +// SlideAnimation({
  97 +// super.key,
  98 +// required super.duration,
  99 +// required super.delay,
  100 +// required super.child,
  101 +// super.onComplete,
  102 +// required Offset begin,
  103 +// required Offset end,
  104 +// super.idleValue = const Offset(0, 0),
  105 +// }) : super(
  106 +// builder: (context, value, child) => Transform.translate(
  107 +// offset: value,
  108 +// child: child,
  109 +// ),
  110 +// tween: Tween(begin: begin, end: end),
  111 +// );
  112 +// }
  113 +
  114 +class BounceAnimation extends GetAnimatedBuilder<double> {
  115 + BounceAnimation({
  116 + super.key,
  117 + required super.duration,
  118 + required super.delay,
  119 + required super.child,
  120 + super.onComplete,
  121 + super.curve = Curves.bounceOut,
  122 + required double begin,
  123 + required double end,
  124 + super.idleValue = 0,
  125 + }) : super(
  126 + builder: (context, value, child) => Transform.scale(
  127 + scale: 1 + value.abs(),
  128 + child: child,
  129 + ),
  130 + tween: Tween<double>(begin: begin, end: end),
  131 + );
  132 +}
  133 +
  134 +class SpinAnimation extends GetAnimatedBuilder<double> {
  135 + SpinAnimation({
  136 + super.key,
  137 + required super.duration,
  138 + required super.delay,
  139 + required super.child,
  140 + super.onComplete,
  141 + super.idleValue = 0,
  142 + }) : super(
  143 + builder: (context, value, child) => Transform.rotate(
  144 + angle: value * pi / 180.0,
  145 + child: child,
  146 + ),
  147 + tween: Tween<double>(begin: 0, end: 360),
  148 + );
  149 +}
  150 +
  151 +class SizeAnimation extends GetAnimatedBuilder<double> {
  152 + SizeAnimation({
  153 + super.key,
  154 + required super.duration,
  155 + required super.delay,
  156 + required super.child,
  157 + super.onComplete,
  158 + super.idleValue = 0,
  159 + required double begin,
  160 + required double end,
  161 + }) : super(
  162 + builder: (context, value, child) => Transform.scale(
  163 + scale: value,
  164 + child: child,
  165 + ),
  166 + tween: Tween<double>(begin: begin, end: end),
  167 + );
  168 +}
  169 +
  170 +class BlurAnimation extends GetAnimatedBuilder<double> {
  171 + BlurAnimation({
  172 + super.key,
  173 + required super.duration,
  174 + required super.delay,
  175 + required super.child,
  176 + super.onComplete,
  177 + required double begin,
  178 + required double end,
  179 + super.idleValue = 0,
  180 + }) : super(
  181 + builder: (context, value, child) => BackdropFilter(
  182 + filter: ImageFilter.blur(
  183 + sigmaX: value,
  184 + sigmaY: value,
  185 + ),
  186 + child: child,
  187 + ),
  188 + tween: Tween<double>(begin: begin, end: end),
  189 + );
  190 +}
  191 +
  192 +class FlipAnimation extends GetAnimatedBuilder<double> {
  193 + FlipAnimation({
  194 + super.key,
  195 + required super.duration,
  196 + required super.delay,
  197 + required super.child,
  198 + super.onComplete,
  199 + required double begin,
  200 + required double end,
  201 + super.idleValue = 0,
  202 + }) : super(
  203 + builder: (context, value, child) {
  204 + final radians = value * pi;
  205 + return Transform(
  206 + transform: Matrix4.rotationY(radians),
  207 + alignment: Alignment.center,
  208 + child: child,
  209 + );
  210 + },
  211 + tween: Tween<double>(begin: begin, end: end),
  212 + );
  213 +}
  214 +
  215 +class WaveAnimation extends GetAnimatedBuilder<double> {
  216 + WaveAnimation({
  217 + super.key,
  218 + required super.duration,
  219 + required super.delay,
  220 + required super.child,
  221 + super.onComplete,
  222 + required double begin,
  223 + required double end,
  224 + super.idleValue = 0,
  225 + }) : super(
  226 + builder: (context, value, child) => Transform(
  227 + transform: Matrix4.translationValues(
  228 + 0.0,
  229 + 20.0 * sin(value * pi * 2),
  230 + 0.0,
  231 + ),
  232 + child: child,
  233 + ),
  234 + tween: Tween<double>(begin: begin, end: end),
  235 + );
  236 +}
  237 +
  238 +class WobbleAnimation extends GetAnimatedBuilder<double> {
  239 + WobbleAnimation({
  240 + super.key,
  241 + required super.duration,
  242 + required super.delay,
  243 + required super.child,
  244 + super.onComplete,
  245 + required double begin,
  246 + required double end,
  247 + super.idleValue = 0,
  248 + }) : super(
  249 + builder: (context, value, child) => Transform(
  250 + transform: Matrix4.identity()
  251 + ..setEntry(3, 2, 0.001)
  252 + ..rotateZ(sin(value * pi * 2) * 0.1),
  253 + alignment: Alignment.center,
  254 + child: child,
  255 + ),
  256 + tween: Tween<double>(begin: begin, end: end),
  257 + );
  258 +}
  259 +
  260 +class SlideInLeftAnimation extends SlideAnimation {
  261 + SlideInLeftAnimation({
  262 + super.key,
  263 + required super.duration,
  264 + required super.delay,
  265 + required super.child,
  266 + super.onComplete,
  267 + required super.begin,
  268 + required super.end,
  269 + super.idleValue = 0,
  270 + }) : super(
  271 + offsetBuild: (context, value) =>
  272 + Offset(value * MediaQuery.of(context).size.width, 0),
  273 + );
  274 +}
  275 +
  276 +class SlideInRightAnimation extends SlideAnimation {
  277 + SlideInRightAnimation({
  278 + super.key,
  279 + required super.duration,
  280 + required super.delay,
  281 + required super.child,
  282 + super.onComplete,
  283 + required super.begin,
  284 + required super.end,
  285 + super.idleValue = 0,
  286 + }) : super(
  287 + offsetBuild: (context, value) =>
  288 + Offset((1 - value) * MediaQuery.of(context).size.width, 0),
  289 + );
  290 +}
  291 +
  292 +class SlideInUpAnimation extends SlideAnimation {
  293 + SlideInUpAnimation({
  294 + super.key,
  295 + required super.duration,
  296 + required super.delay,
  297 + required super.child,
  298 + super.onComplete,
  299 + required super.begin,
  300 + required super.end,
  301 + super.idleValue = 0,
  302 + }) : super(
  303 + offsetBuild: (context, value) =>
  304 + Offset(0, value * MediaQuery.of(context).size.height),
  305 + );
  306 +}
  307 +
  308 +class SlideInDownAnimation extends SlideAnimation {
  309 + SlideInDownAnimation({
  310 + super.key,
  311 + required super.duration,
  312 + required super.delay,
  313 + required super.child,
  314 + super.onComplete,
  315 + required super.begin,
  316 + required super.end,
  317 + super.idleValue = 0,
  318 + }) : super(
  319 + offsetBuild: (context, value) =>
  320 + Offset(0, (1 - value) * MediaQuery.of(context).size.height),
  321 + );
  322 +}
  323 +
  324 +class SlideAnimation extends GetAnimatedBuilder<double> {
  325 + SlideAnimation({
  326 + super.key,
  327 + required super.duration,
  328 + required super.delay,
  329 + required super.child,
  330 + required double begin,
  331 + required double end,
  332 + required OffsetBuilder offsetBuild,
  333 + super.onComplete,
  334 + super.idleValue = 0,
  335 + }) : super(
  336 + builder: (context, value, child) => Transform.translate(
  337 + offset: offsetBuild(context, value),
  338 + child: child,
  339 + ),
  340 + tween: Tween<double>(begin: begin, end: end),
  341 + );
  342 +}
  343 +
  344 +// class ZoomAnimation extends GetAnimatedBuilder<double> {
  345 +// ZoomAnimation({
  346 +// super.key,
  347 +// required super.duration,
  348 +// required super.delay,
  349 +// required super.child,
  350 +// super.onComplete,
  351 +// required double begin,
  352 +// required double end,
  353 +// super.idleValue = 0,
  354 +// }) : super(
  355 +// builder: (context, value, child) => Transform.scale(
  356 +// scale: lerpDouble(1, end, value)!,
  357 +// child: child,
  358 +// ),
  359 +// tween: Tween<double>(begin: begin, end: end),
  360 +// );
  361 +// }
  362 +
  363 +class ColorAnimation extends GetAnimatedBuilder<Color?> {
  364 + ColorAnimation({
  365 + super.key,
  366 + required super.duration,
  367 + required super.delay,
  368 + required super.child,
  369 + super.onComplete,
  370 + required Color begin,
  371 + required Color end,
  372 + Color? idleColor,
  373 + }) : super(
  374 + builder: (context, value, child) => ColorFiltered(
  375 + colorFilter: ColorFilter.mode(
  376 + Color.lerp(begin, end, value!.value.toDouble())!,
  377 + BlendMode.srcIn,
  378 + ),
  379 + child: child,
  380 + ),
  381 + idleValue: idleColor ?? begin,
  382 + tween: ColorTween(begin: begin, end: end),
  383 + );
  384 +}
  1 +import 'package:flutter/material.dart';
  2 +
  3 +import 'animations.dart';
  4 +import 'get_animated_builder.dart';
  5 +
  6 +const _defaultDuration = Duration(seconds: 2);
  7 +const _defaultDelay = Duration.zero;
  8 +
  9 +extension AnimationExtension on Widget {
  10 + GetAnimatedBuilder? get _currentAnimation =>
  11 + (this is GetAnimatedBuilder) ? this as GetAnimatedBuilder : null;
  12 +
  13 + GetAnimatedBuilder fadeIn({
  14 + Duration duration = _defaultDuration,
  15 + Duration delay = _defaultDelay,
  16 + ValueSetter<AnimationController>? onComplete,
  17 + bool isSequential = false,
  18 + }) {
  19 + assert(isSequential || this is! FadeOutAnimation,
  20 + 'Can not use fadeOut + fadeIn when isSequential is false');
  21 +
  22 + return FadeInAnimation(
  23 + duration: duration,
  24 + delay: _getDelay(isSequential, delay),
  25 + onComplete: onComplete,
  26 + child: this,
  27 + );
  28 + }
  29 +
  30 + GetAnimatedBuilder fadeOut({
  31 + Duration duration = _defaultDuration,
  32 + Duration delay = _defaultDelay,
  33 + ValueSetter<AnimationController>? onComplete,
  34 + bool isSequential = false,
  35 + }) {
  36 + assert(isSequential || this is! FadeInAnimation,
  37 + 'Can not use fadeOut() + fadeIn when isSequential is false');
  38 +
  39 + return FadeOutAnimation(
  40 + duration: duration,
  41 + delay: _getDelay(isSequential, delay),
  42 + onComplete: onComplete,
  43 + child: this,
  44 + );
  45 + }
  46 +
  47 + GetAnimatedBuilder rotate({
  48 + required double begin,
  49 + required double end,
  50 + Duration duration = _defaultDuration,
  51 + Duration delay = _defaultDelay,
  52 + ValueSetter<AnimationController>? onComplete,
  53 + bool isSequential = false,
  54 + }) {
  55 + return RotateAnimation(
  56 + duration: duration,
  57 + delay: _getDelay(isSequential, delay),
  58 + begin: begin,
  59 + end: end,
  60 + onComplete: onComplete,
  61 + child: this,
  62 + );
  63 + }
  64 +
  65 + GetAnimatedBuilder scale({
  66 + required double begin,
  67 + required double end,
  68 + Duration duration = _defaultDuration,
  69 + Duration delay = _defaultDelay,
  70 + ValueSetter<AnimationController>? onComplete,
  71 + bool isSequential = false,
  72 + }) {
  73 + return ScaleAnimation(
  74 + duration: duration,
  75 + delay: _getDelay(isSequential, delay),
  76 + begin: begin,
  77 + end: end,
  78 + onComplete: onComplete,
  79 + child: this,
  80 + );
  81 + }
  82 +
  83 + GetAnimatedBuilder slide({
  84 + required OffsetBuilder offset,
  85 + double begin = 0,
  86 + double end = 1,
  87 + Duration duration = _defaultDuration,
  88 + Duration delay = _defaultDelay,
  89 + ValueSetter<AnimationController>? onComplete,
  90 + bool isSequential = false,
  91 + }) {
  92 + return SlideAnimation(
  93 + duration: duration,
  94 + delay: _getDelay(isSequential, delay),
  95 + begin: begin,
  96 + end: end,
  97 + onComplete: onComplete,
  98 + offsetBuild: offset,
  99 + child: this,
  100 + );
  101 + }
  102 +
  103 + GetAnimatedBuilder bounce({
  104 + required double begin,
  105 + required double end,
  106 + Duration duration = _defaultDuration,
  107 + Duration delay = _defaultDelay,
  108 + ValueSetter<AnimationController>? onComplete,
  109 + bool isSequential = false,
  110 + }) {
  111 + return BounceAnimation(
  112 + duration: duration,
  113 + delay: _getDelay(isSequential, delay),
  114 + begin: begin,
  115 + end: end,
  116 + onComplete: onComplete,
  117 + child: this,
  118 + );
  119 + }
  120 +
  121 + GetAnimatedBuilder spin({
  122 + Duration duration = _defaultDuration,
  123 + Duration delay = _defaultDelay,
  124 + ValueSetter<AnimationController>? onComplete,
  125 + bool isSequential = false,
  126 + }) {
  127 + return SpinAnimation(
  128 + duration: duration,
  129 + delay: _getDelay(isSequential, delay),
  130 + onComplete: onComplete,
  131 + child: this,
  132 + );
  133 + }
  134 +
  135 + GetAnimatedBuilder size({
  136 + required double begin,
  137 + required double end,
  138 + Duration duration = _defaultDuration,
  139 + Duration delay = _defaultDelay,
  140 + ValueSetter<AnimationController>? onComplete,
  141 + bool isSequential = false,
  142 + }) {
  143 + return SizeAnimation(
  144 + duration: duration,
  145 + delay: _getDelay(isSequential, delay),
  146 + begin: begin,
  147 + end: end,
  148 + onComplete: onComplete,
  149 + child: this,
  150 + );
  151 + }
  152 +
  153 + GetAnimatedBuilder blur({
  154 + double begin = 0,
  155 + double end = 15,
  156 + Duration duration = _defaultDuration,
  157 + Duration delay = _defaultDelay,
  158 + ValueSetter<AnimationController>? onComplete,
  159 + bool isSequential = false,
  160 + }) {
  161 + return BlurAnimation(
  162 + duration: duration,
  163 + delay: _getDelay(isSequential, delay),
  164 + begin: begin,
  165 + end: end,
  166 + onComplete: onComplete,
  167 + child: this,
  168 + );
  169 + }
  170 +
  171 + GetAnimatedBuilder flip({
  172 + double begin = 0,
  173 + double end = 1,
  174 + Duration duration = _defaultDuration,
  175 + Duration delay = _defaultDelay,
  176 + ValueSetter<AnimationController>? onComplete,
  177 + bool isSequential = false,
  178 + }) {
  179 + return FlipAnimation(
  180 + duration: duration,
  181 + delay: _getDelay(isSequential, delay),
  182 + begin: begin,
  183 + end: end,
  184 + onComplete: onComplete,
  185 + child: this,
  186 + );
  187 + }
  188 +
  189 + GetAnimatedBuilder wave({
  190 + double begin = 0,
  191 + double end = 1,
  192 + Duration duration = _defaultDuration,
  193 + Duration delay = _defaultDelay,
  194 + ValueSetter<AnimationController>? onComplete,
  195 + bool isSequential = false,
  196 + }) {
  197 + return WaveAnimation(
  198 + duration: duration,
  199 + delay: _getDelay(isSequential, delay),
  200 + begin: begin,
  201 + end: end,
  202 + onComplete: onComplete,
  203 + child: this,
  204 + );
  205 + }
  206 +
  207 + Duration _getDelay(bool isSequential, Duration delay) {
  208 + assert(!(isSequential && delay != Duration.zero),
  209 + "Error: When isSequential is true, delay must be non-zero. Context: isSequential: $isSequential delay: $delay");
  210 +
  211 + return isSequential
  212 + ? (_currentAnimation?.totalDuration ?? Duration.zero)
  213 + : delay;
  214 + }
  215 +}
  1 +import 'package:flutter/material.dart';
  2 +
  3 +import 'animations.dart';
  4 +
  5 +class GetAnimatedBuilder<T> extends StatefulWidget {
  6 + final Duration duration;
  7 + final Duration delay;
  8 + final Widget child;
  9 + final ValueSetter<AnimationController>? onComplete;
  10 + final ValueSetter<AnimationController>? onStart;
  11 + final Tween<T> tween;
  12 + final T idleValue;
  13 + final ValueWidgetBuilder<T> builder;
  14 + final Curve curve;
  15 +
  16 + Duration get totalDuration => duration + delay;
  17 +
  18 + const GetAnimatedBuilder({
  19 + super.key,
  20 + this.curve = Curves.linear,
  21 + this.onComplete,
  22 + this.onStart,
  23 + required this.duration,
  24 + required this.tween,
  25 + required this.idleValue,
  26 + required this.builder,
  27 + required this.child,
  28 + required this.delay,
  29 + });
  30 + @override
  31 + GetAnimatedBuilderState<T> createState() => GetAnimatedBuilderState<T>();
  32 +}
  33 +
  34 +class GetAnimatedBuilderState<T> extends State<GetAnimatedBuilder<T>>
  35 + with SingleTickerProviderStateMixin {
  36 + late final AnimationController _controller;
  37 + late final Animation<T> _animation;
  38 +
  39 + // AnimationController get controller => _controller;
  40 + // Animation<T> get animation => _animation;
  41 +
  42 + bool _wasStarted = false;
  43 + // bool get wasStarted => _wasStarted;
  44 +
  45 + late T _idleValue;
  46 +
  47 + bool _willResetOnDispose = false;
  48 +
  49 + bool get willResetOnDispose => _willResetOnDispose;
  50 +
  51 + void _listener(AnimationStatus status) {
  52 + switch (status) {
  53 + case AnimationStatus.completed:
  54 + widget.onComplete?.call(_controller);
  55 + if (_willResetOnDispose) {
  56 + _controller.reset();
  57 + }
  58 + break;
  59 + // case AnimationStatus.dismissed:
  60 + case AnimationStatus.forward:
  61 + widget.onStart?.call(_controller);
  62 + break;
  63 + // case AnimationStatus.reverse:
  64 + default:
  65 + break;
  66 + }
  67 + }
  68 +
  69 + @override
  70 + void initState() {
  71 + super.initState();
  72 +
  73 + if (widget is OpacityAnimation) {
  74 + final current =
  75 + context.findRootAncestorStateOfType<GetAnimatedBuilderState>();
  76 + final isLast = current == null;
  77 +
  78 + if (widget is FadeInAnimation) {
  79 + _idleValue = 1.0 as dynamic;
  80 + } else {
  81 + if (isLast) {
  82 + _willResetOnDispose = false;
  83 + } else {
  84 + _willResetOnDispose = true;
  85 + }
  86 + _idleValue = widget.idleValue;
  87 + }
  88 + } else {
  89 + _idleValue = widget.idleValue;
  90 + }
  91 +
  92 + _controller = AnimationController(
  93 + vsync: this,
  94 + duration: widget.duration,
  95 + );
  96 +
  97 + _controller.addStatusListener(_listener);
  98 +
  99 + _animation = widget.tween.animate(
  100 + CurvedAnimation(
  101 + parent: _controller,
  102 + curve: widget.curve,
  103 + ),
  104 + );
  105 +
  106 + Future.delayed(widget.delay, () {
  107 + if (mounted) {
  108 + setState(() {
  109 + _wasStarted = true;
  110 + _controller.forward();
  111 + });
  112 + }
  113 + });
  114 + }
  115 +
  116 + @override
  117 + void dispose() {
  118 + _controller.removeStatusListener(_listener);
  119 + _controller.dispose();
  120 + super.dispose();
  121 + }
  122 +
  123 + @override
  124 + Widget build(BuildContext context) {
  125 + return AnimatedBuilder(
  126 + animation: _animation,
  127 + builder: (context, child) {
  128 + final value = _wasStarted ? _animation.value : _idleValue;
  129 + return widget.builder(context, value, child);
  130 + },
  131 + child: widget.child,
  132 + );
  133 + }
  134 +}
  1 +export './animations.dart';
  2 +export './extensions.dart';
  3 +export './get_animated_builder.dart';
@@ -268,9 +268,9 @@ class GetConnect extends GetConnectInterface { @@ -268,9 +268,9 @@ class GetConnect extends GetConnectInterface {
268 }) { 268 }) {
269 _checkIfDisposed(isHttp: false); 269 _checkIfDisposed(isHttp: false);
270 270
271 - final _socket = GetSocket(_concatUrl(url)!, ping: ping);  
272 - sockets.add(_socket);  
273 - return _socket; 271 + final newSocket = GetSocket(_concatUrl(url)!, ping: ping);
  272 + sockets.add(newSocket);
  273 + return newSocket;
274 } 274 }
275 275
276 String? _concatUrl(String? url) { 276 String? _concatUrl(String? url) {
@@ -16,7 +16,8 @@ typedef Decoder<T> = T Function(dynamic data); @@ -16,7 +16,8 @@ typedef Decoder<T> = T Function(dynamic data);
16 16
17 typedef Progress = Function(double percent); 17 typedef Progress = Function(double percent);
18 18
19 -typedef ResponseInterceptor<T> = Future<Response<T>?> Function(Request<T> request, Type targetType, HttpClientResponse response); 19 +typedef ResponseInterceptor<T> = Future<Response<T>?> Function(
  20 + Request<T> request, Type targetType, HttpClientResponse response);
20 21
21 class GetHttpClient { 22 class GetHttpClient {
22 String userAgent; 23 String userAgent;
@@ -38,7 +39,7 @@ class GetHttpClient { @@ -38,7 +39,7 @@ class GetHttpClient {
38 39
39 bool errorSafety = true; 40 bool errorSafety = true;
40 41
41 - final HttpRequestBase _httpClient; 42 + final IClient _httpClient;
42 43
43 final GetModifier _modifier; 44 final GetModifier _modifier;
44 45
@@ -57,12 +58,14 @@ class GetHttpClient { @@ -57,12 +58,14 @@ class GetHttpClient {
57 List<TrustedCertificate>? trustedCertificates, 58 List<TrustedCertificate>? trustedCertificates,
58 bool withCredentials = false, 59 bool withCredentials = false,
59 String Function(Uri url)? findProxy, 60 String Function(Uri url)? findProxy,
60 - }) : _httpClient = createHttp(  
61 - allowAutoSignedCert: allowAutoSignedCert,  
62 - trustedCertificates: trustedCertificates,  
63 - withCredentials: withCredentials,  
64 - findProxy: findProxy,  
65 - ), 61 + IClient? customClient,
  62 + }) : _httpClient = customClient ??
  63 + createHttp(
  64 + allowAutoSignedCert: allowAutoSignedCert,
  65 + trustedCertificates: trustedCertificates,
  66 + withCredentials: withCredentials,
  67 + findProxy: findProxy,
  68 + ),
66 _modifier = GetModifier(); 69 _modifier = GetModifier();
67 70
68 void addAuthenticator<T>(RequestModifier<T> auth) { 71 void addAuthenticator<T>(RequestModifier<T> auth) {
@@ -85,7 +88,7 @@ class GetHttpClient { @@ -85,7 +88,7 @@ class GetHttpClient {
85 _modifier.removeResponseModifier<T>(interceptor); 88 _modifier.removeResponseModifier<T>(interceptor);
86 } 89 }
87 90
88 - Uri _createUri(String? url, Map<String, dynamic>? query) { 91 + Uri createUri(String? url, Map<String, dynamic>? query) {
89 if (baseUrl != null) { 92 if (baseUrl != null) {
90 url = baseUrl! + url!; 93 url = baseUrl! + url!;
91 } 94 }
@@ -154,18 +157,17 @@ class GetHttpClient { @@ -154,18 +157,17 @@ class GetHttpClient {
154 bodyStream = _trackProgress(bodyBytes, uploadProgress); 157 bodyStream = _trackProgress(bodyBytes, uploadProgress);
155 } 158 }
156 159
157 - final uri = _createUri(url, query); 160 + final uri = createUri(url, query);
158 return Request<T>( 161 return Request<T>(
159 - method: method,  
160 - url: uri,  
161 - headers: headers,  
162 - bodyBytes: bodyStream,  
163 - contentLength: bodyBytes?.length ?? 0,  
164 - followRedirects: followRedirects,  
165 - maxRedirects: maxRedirects,  
166 - decoder: decoder,  
167 - responseInterceptor: responseInterceptor  
168 - ); 162 + method: method,
  163 + url: uri,
  164 + headers: headers,
  165 + bodyBytes: bodyStream,
  166 + contentLength: bodyBytes?.length ?? 0,
  167 + followRedirects: followRedirects,
  168 + maxRedirects: maxRedirects,
  169 + decoder: decoder,
  170 + responseInterceptor: responseInterceptor);
169 } 171 }
170 172
171 void _setContentLenght(Map<String, String> headers, int contentLength) { 173 void _setContentLenght(Map<String, String> headers, int contentLength) {
@@ -277,7 +279,7 @@ class GetHttpClient { @@ -277,7 +279,7 @@ class GetHttpClient {
277 ) { 279 ) {
278 final headers = <String, String>{}; 280 final headers = <String, String>{};
279 _setSimpleHeaders(headers, contentType); 281 _setSimpleHeaders(headers, contentType);
280 - final uri = _createUri(url, query); 282 + final uri = createUri(url, query);
281 283
282 return Future.value(Request<T>( 284 return Future.value(Request<T>(
283 method: 'get', 285 method: 'get',
@@ -291,11 +293,14 @@ class GetHttpClient { @@ -291,11 +293,14 @@ class GetHttpClient {
291 )); 293 ));
292 } 294 }
293 295
294 - ResponseInterceptor<T>? _responseInterceptor<T>(ResponseInterceptor<T>? actual) {  
295 - if(actual != null) return actual; 296 + ResponseInterceptor<T>? _responseInterceptor<T>(
  297 + ResponseInterceptor<T>? actual) {
  298 + if (actual != null) return actual;
296 final defaultInterceptor = defaultResponseInterceptor; 299 final defaultInterceptor = defaultResponseInterceptor;
297 return defaultInterceptor != null 300 return defaultInterceptor != null
298 - ? (request, targetType, response) async => await defaultInterceptor(request, targetType, response) as Response<T>? 301 + ? (request, targetType, response) async =>
  302 + await defaultInterceptor(request, targetType, response)
  303 + as Response<T>?
299 : null; 304 : null;
300 } 305 }
301 306
@@ -330,7 +335,7 @@ class GetHttpClient { @@ -330,7 +335,7 @@ class GetHttpClient {
330 ) { 335 ) {
331 final headers = <String, String>{}; 336 final headers = <String, String>{};
332 _setSimpleHeaders(headers, contentType); 337 _setSimpleHeaders(headers, contentType);
333 - final uri = _createUri(url, query); 338 + final uri = createUri(url, query);
334 339
335 return Request<T>( 340 return Request<T>(
336 method: 'delete', 341 method: 'delete',
@@ -340,6 +345,7 @@ class GetHttpClient { @@ -340,6 +345,7 @@ class GetHttpClient {
340 responseInterceptor: _responseInterceptor(responseInterceptor), 345 responseInterceptor: _responseInterceptor(responseInterceptor),
341 ); 346 );
342 } 347 }
  348 +
343 Future<Response<T>> send<T>(Request<T> request) async { 349 Future<Response<T>> send<T>(Request<T> request) async {
344 try { 350 try {
345 var response = await _performRequest<T>(() => Future.value(request)); 351 var response = await _performRequest<T>(() => Future.value(request));
@@ -521,78 +527,16 @@ class GetHttpClient { @@ -521,78 +527,16 @@ class GetHttpClient {
521 } 527 }
522 } 528 }
523 529
524 - // Future<Response<T>> download<T>(  
525 - // String url,  
526 - // String path, {  
527 - // Map<String, String> headers,  
528 - // String contentType = 'application/octet-stream',  
529 - // Map<String, dynamic> query,  
530 - // }) async {  
531 - // try {  
532 - // var response = await _performRequest<T>(  
533 - // () => _get<T>(url, contentType, query, null),  
534 - // headers: headers,  
535 - // );  
536 - // response.bodyBytes.listen((value) {});  
537 - // return response;  
538 - // } on Exception catch (e) {  
539 - // if (!errorSafety) {  
540 - // throw GetHttpException(e.toString());  
541 - // }  
542 - // return Future.value(Response<T>(  
543 - // statusText: 'Can not connect to server. Reason: $e',  
544 - // ));  
545 - // }  
546 -  
547 - // int byteCount = 0;  
548 - // int totalBytes = httpResponse.contentLength;  
549 -  
550 - // Directory appDocDir = await getApplicationDocumentsDirectory();  
551 - // String appDocPath = appDocDir.path;  
552 -  
553 - // File file = File(path);  
554 -  
555 - // var raf = file.openSync(mode: FileMode.write);  
556 -  
557 - // Completer completer = Completer<String>();  
558 -  
559 - // httpResponse.listen(  
560 - // (data) {  
561 - // byteCount += data.length;  
562 -  
563 - // raf.writeFromSync(data);  
564 -  
565 - // if (onDownloadProgress != null) {  
566 - // onDownloadProgress(byteCount, totalBytes);  
567 - // }  
568 - // },  
569 - // onDone: () {  
570 - // raf.closeSync();  
571 -  
572 - // completer.complete(file.path);  
573 - // },  
574 - // onError: (e) {  
575 - // raf.closeSync();  
576 - // file.deleteSync();  
577 - // completer.completeError(e);  
578 - // },  
579 - // cancelOnError: true,  
580 - // );  
581 -  
582 - // return completer.future;  
583 - // }  
584 -  
585 - Future<Response<T>> delete<T>(  
586 - String url, {  
587 - Map<String, String>? headers,  
588 - String? contentType,  
589 - Map<String, dynamic>? query,  
590 - Decoder<T>? decoder,  
591 - ResponseInterceptor<T>? responseInterceptor  
592 - }) async { 530 + Future<Response<T>> delete<T>(String url,
  531 + {Map<String, String>? headers,
  532 + String? contentType,
  533 + Map<String, dynamic>? query,
  534 + Decoder<T>? decoder,
  535 + ResponseInterceptor<T>? responseInterceptor}) async {
593 try { 536 try {
594 var response = await _performRequest<T>( 537 var response = await _performRequest<T>(
595 - () async => _delete<T>(url, contentType, query, decoder, responseInterceptor), 538 + () async =>
  539 + _delete<T>(url, contentType, query, decoder, responseInterceptor),
596 headers: headers, 540 headers: headers,
597 ); 541 );
598 return response; 542 return response;
@@ -4,7 +4,8 @@ List<int> fileToBytes(dynamic data) { @@ -4,7 +4,8 @@ List<int> fileToBytes(dynamic data) {
4 if (data is List<int>) { 4 if (data is List<int>) {
5 return data; 5 return data;
6 } else { 6 } else {
7 - throw FormatException('File is not "File" or "String" or "List<int>"'); 7 + throw const FormatException(
  8 + 'File is not "File" or "String" or "List<int>"');
8 } 9 }
9 } 10 }
10 11
@@ -9,8 +9,8 @@ import '../../response/response.dart'; @@ -9,8 +9,8 @@ import '../../response/response.dart';
9 import '../interface/request_base.dart'; 9 import '../interface/request_base.dart';
10 import '../utils/body_decoder.dart'; 10 import '../utils/body_decoder.dart';
11 11
12 -/// A `dart:html` implementation of `HttpRequestBase`.  
13 -class HttpRequestImpl implements HttpRequestBase { 12 +/// A `dart:html` implementation of `IClient`.
  13 +class HttpRequestImpl implements IClient {
14 HttpRequestImpl({ 14 HttpRequestImpl({
15 bool allowAutoSignedCert = true, 15 bool allowAutoSignedCert = true,
16 List<TrustedCertificate>? trustedCertificates, 16 List<TrustedCertificate>? trustedCertificates,
@@ -51,7 +51,7 @@ class HttpRequestImpl implements HttpRequestBase { @@ -51,7 +51,7 @@ class HttpRequestImpl implements HttpRequestBase {
51 var reader = FileReader(); 51 var reader = FileReader();
52 52
53 reader.onLoad.first.then((_) async { 53 reader.onLoad.first.then((_) async {
54 - var bodyBytes = BodyBytesStream.fromBytes(reader.result as List<int>); 54 + var bodyBytes = (reader.result as List<int>).toStream();
55 55
56 final stringBody = 56 final stringBody =
57 await bodyBytesToString(bodyBytes, xhr.responseHeaders); 57 await bodyBytesToString(bodyBytes, xhr.responseHeaders);
@@ -2,7 +2,7 @@ import '../../request/request.dart'; @@ -2,7 +2,7 @@ import '../../request/request.dart';
2 import '../../response/response.dart'; 2 import '../../response/response.dart';
3 3
4 /// Abstract interface of [HttpRequestImpl]. 4 /// Abstract interface of [HttpRequestImpl].
5 -abstract class HttpRequestBase { 5 +abstract class IClient {
6 /// Sends an HTTP [Request]. 6 /// Sends an HTTP [Request].
7 Future<Response<T>> send<T>(Request<T> request); 7 Future<Response<T>> send<T>(Request<T> request);
8 8
@@ -12,7 +12,8 @@ List<int> fileToBytes(dynamic data) { @@ -12,7 +12,8 @@ List<int> fileToBytes(dynamic data) {
12 } else if (data is List<int>) { 12 } else if (data is List<int>) {
13 return data; 13 return data;
14 } else { 14 } else {
15 - throw FormatException('File is not "File" or "String" or "List<int>"'); 15 + throw const FormatException(
  16 + 'File is not "File" or "String" or "List<int>"');
16 } 17 }
17 } 18 }
18 19
@@ -8,9 +8,8 @@ import '../../response/response.dart'; @@ -8,9 +8,8 @@ import '../../response/response.dart';
8 import '../interface/request_base.dart'; 8 import '../interface/request_base.dart';
9 import '../utils/body_decoder.dart'; 9 import '../utils/body_decoder.dart';
10 10
11 -  
12 -/// A `dart:io` implementation of `HttpRequestBase`.  
13 -class HttpRequestImpl extends HttpRequestBase { 11 +/// A `dart:io` implementation of `IClient`.
  12 +class HttpRequestImpl extends IClient {
14 io.HttpClient? _httpClient; 13 io.HttpClient? _httpClient;
15 io.SecurityContext? _securityContext; 14 io.SecurityContext? _securityContext;
16 15
@@ -58,10 +57,11 @@ class HttpRequestImpl extends HttpRequestBase { @@ -58,10 +57,11 @@ class HttpRequestImpl extends HttpRequestBase {
58 }); 57 });
59 58
60 final bodyBytes = (response); 59 final bodyBytes = (response);
61 -  
62 - final interceptionResponse = await request.responseInterceptor?.call(request, T, response);  
63 - if(interceptionResponse != null) return interceptionResponse;  
64 - 60 +
  61 + final interceptionResponse =
  62 + await request.responseInterceptor?.call(request, T, response);
  63 + if (interceptionResponse != null) return interceptionResponse;
  64 +
65 final stringBody = await bodyBytesToString(bodyBytes, headers); 65 final stringBody = await bodyBytesToString(bodyBytes, headers);
66 66
67 final body = bodyDecoded<T>( 67 final body = bodyDecoded<T>(
@@ -5,7 +5,7 @@ import '../utils/body_decoder.dart'; @@ -5,7 +5,7 @@ import '../utils/body_decoder.dart';
5 5
6 typedef MockClientHandler = Future<Response> Function(Request request); 6 typedef MockClientHandler = Future<Response> Function(Request request);
7 7
8 -class MockClient extends HttpRequestBase { 8 +class MockClient extends IClient {
9 /// The handler for than transforms request on response 9 /// The handler for than transforms request on response
10 final MockClientHandler _handler; 10 final MockClientHandler _handler;
11 11
@@ -16,7 +16,7 @@ class MockClient extends HttpRequestBase { @@ -16,7 +16,7 @@ class MockClient extends HttpRequestBase {
16 @override 16 @override
17 Future<Response<T>> send<T>(Request<T> request) async { 17 Future<Response<T>> send<T>(Request<T> request) async {
18 var requestBody = await request.bodyBytes.toBytes(); 18 var requestBody = await request.bodyBytes.toBytes();
19 - var bodyBytes = BodyBytesStream.fromBytes(requestBody); 19 + var bodyBytes = requestBody.toStream();
20 20
21 var response = await _handler(request); 21 var response = await _handler(request);
22 22
@@ -3,7 +3,7 @@ import '../../request/request.dart'; @@ -3,7 +3,7 @@ import '../../request/request.dart';
3 import '../../response/response.dart'; 3 import '../../response/response.dart';
4 import '../interface/request_base.dart'; 4 import '../interface/request_base.dart';
5 5
6 -class HttpRequestImpl extends HttpRequestBase { 6 +class HttpRequestImpl extends IClient {
7 HttpRequestImpl({ 7 HttpRequestImpl({
8 bool allowAutoSignedCert = true, 8 bool allowAutoSignedCert = true,
9 List<TrustedCertificate>? trustedCertificates, 9 List<TrustedCertificate>? trustedCertificates,
@@ -25,9 +25,9 @@ class FormData { @@ -25,9 +25,9 @@ class FormData {
25 static const int _maxBoundaryLength = 70; 25 static const int _maxBoundaryLength = 70;
26 26
27 static String _getBoundary() { 27 static String _getBoundary() {
28 - final _random = Random(); 28 + final newRandom = Random();
29 var list = List<int>.generate(_maxBoundaryLength - GET_BOUNDARY.length, 29 var list = List<int>.generate(_maxBoundaryLength - GET_BOUNDARY.length,
30 - (_) => boundaryCharacters[_random.nextInt(boundaryCharacters.length)], 30 + (_) => boundaryCharacters[newRandom.nextInt(boundaryCharacters.length)],
31 growable: false); 31 growable: false);
32 return '$GET_BOUNDARY${String.fromCharCodes(list)}'; 32 return '$GET_BOUNDARY${String.fromCharCodes(list)}';
33 } 33 }
1 import '../http/stub/file_decoder_stub.dart' 1 import '../http/stub/file_decoder_stub.dart'
2 if (dart.library.html) '../http/html/file_decoder_html.dart' 2 if (dart.library.html) '../http/html/file_decoder_html.dart'
3 if (dart.library.io) '../http/io/file_decoder_io.dart'; 3 if (dart.library.io) '../http/io/file_decoder_io.dart';
4 -  
5 import '../request/request.dart'; 4 import '../request/request.dart';
6 5
7 class MultipartFile { 6 class MultipartFile {
@@ -11,7 +10,7 @@ class MultipartFile { @@ -11,7 +10,7 @@ class MultipartFile {
11 this.contentType = 'application/octet-stream', 10 this.contentType = 'application/octet-stream',
12 }) : _bytes = fileToBytes(data) { 11 }) : _bytes = fileToBytes(data) {
13 _length = _bytes.length; 12 _length = _bytes.length;
14 - _stream = BodyBytesStream.fromBytes(_bytes); 13 + _stream = _bytes.toStream();
15 } 14 }
16 15
17 final List<int> _bytes; 16 final List<int> _bytes;
@@ -68,7 +68,7 @@ class Request<T> { @@ -68,7 +68,7 @@ class Request<T> {
68 return Request._( 68 return Request._(
69 url: url, 69 url: url,
70 method: method, 70 method: method,
71 - bodyBytes: bodyBytes ??= BodyBytesStream.fromBytes(const []), 71 + bodyBytes: bodyBytes ??= <int>[].toStream(),
72 headers: Map.from(headers), 72 headers: Map.from(headers),
73 followRedirects: followRedirects, 73 followRedirects: followRedirects,
74 maxRedirects: maxRedirects, 74 maxRedirects: maxRedirects,
@@ -113,9 +113,11 @@ class Request<T> { @@ -113,9 +113,11 @@ class Request<T> {
113 } 113 }
114 } 114 }
115 115
116 -extension BodyBytesStream on Stream<List<int>> {  
117 - static Stream<List<int>> fromBytes(List<int> bytes) => Stream.value(bytes); 116 +extension StreamExt on List<int> {
  117 + Stream<List<int>> toStream() => Stream.value(this).asBroadcastStream();
  118 +}
118 119
  120 +extension BodyBytesStream on Stream<List<int>> {
119 Future<Uint8List> toBytes() { 121 Future<Uint8List> toBytes() {
120 var completer = Completer<Uint8List>(); 122 var completer = Completer<Uint8List>();
121 var sink = ByteConversionSink.withCallback( 123 var sink = ByteConversionSink.withCallback(
1 import 'package:flutter/widgets.dart'; 1 import 'package:flutter/widgets.dart';
2 2
3 -class Engine{  
4 - static WidgetsBinding get instance { 3 +class Engine {
  4 + static WidgetsBinding get instance {
5 return WidgetsFlutterBinding.ensureInitialized(); 5 return WidgetsFlutterBinding.ensureInitialized();
6 } 6 }
7 -}  
  7 +}
@@ -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
@@ -143,11 +161,11 @@ extension Inst on GetInterface { @@ -143,11 +161,11 @@ extension Inst on GetInterface {
143 161
144 _InstanceBuilderFactory<S>? dep; 162 _InstanceBuilderFactory<S>? dep;
145 if (_singl.containsKey(key)) { 163 if (_singl.containsKey(key)) {
146 - final _dep = _singl[key];  
147 - if (_dep == null || !_dep.isDirty) { 164 + final newDep = _singl[key];
  165 + if (newDep == null || !newDep.isDirty) {
148 return; 166 return;
149 } else { 167 } else {
150 - dep = _dep as _InstanceBuilderFactory<S>; 168 + dep = newDep as _InstanceBuilderFactory<S>;
151 } 169 }
152 } 170 }
153 _singl[key] = _InstanceBuilderFactory<S>( 171 _singl[key] = _InstanceBuilderFactory<S>(
@@ -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 ///
@@ -5,7 +5,6 @@ export 'src/extension_navigation.dart'; @@ -5,7 +5,6 @@ export 'src/extension_navigation.dart';
5 export 'src/root/get_cupertino_app.dart'; 5 export 'src/root/get_cupertino_app.dart';
6 export 'src/root/get_material_app.dart'; 6 export 'src/root/get_material_app.dart';
7 export 'src/root/internacionalization.dart'; 7 export 'src/root/internacionalization.dart';
8 -export 'src/root/root_controller.dart';  
9 export 'src/routes/custom_transition.dart'; 8 export 'src/routes/custom_transition.dart';
10 export 'src/routes/default_route.dart'; 9 export 'src/routes/default_route.dart';
11 export 'src/routes/get_route.dart'; 10 export 'src/routes/get_route.dart';
@@ -21,6 +21,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { @@ -21,6 +21,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
21 RouteSettings? settings, 21 RouteSettings? settings,
22 this.enterBottomSheetDuration = const Duration(milliseconds: 250), 22 this.enterBottomSheetDuration = const Duration(milliseconds: 250),
23 this.exitBottomSheetDuration = const Duration(milliseconds: 200), 23 this.exitBottomSheetDuration = const Duration(milliseconds: 200),
  24 + this.curve,
24 }) : super(settings: settings) { 25 }) : super(settings: settings) {
25 RouterReportManager.instance.reportCurrentRoute(this); 26 RouterReportManager.instance.reportCurrentRoute(this);
26 } 27 }
@@ -38,11 +39,12 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { @@ -38,11 +39,12 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
38 // final String name; 39 // final String name;
39 final Duration enterBottomSheetDuration; 40 final Duration enterBottomSheetDuration;
40 final Duration exitBottomSheetDuration; 41 final Duration exitBottomSheetDuration;
  42 + final Curve? curve;
41 // remove safearea from top 43 // remove safearea from top
42 final bool removeTop; 44 final bool removeTop;
43 45
44 @override 46 @override
45 - Duration get transitionDuration => Duration(milliseconds: 700); 47 + Duration get transitionDuration => const Duration(milliseconds: 700);
46 48
47 @override 49 @override
48 bool get barrierDismissible => isDismissible; 50 bool get barrierDismissible => isDismissible;
@@ -62,6 +64,14 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { @@ -62,6 +64,14 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
62 } 64 }
63 65
64 @override 66 @override
  67 + Animation<double> createAnimation() {
  68 + if (curve != null) {
  69 + return CurvedAnimation(curve: curve!, parent: _animationController!.view);
  70 + }
  71 + return _animationController!.view;
  72 + }
  73 +
  74 + @override
65 AnimationController createAnimationController() { 75 AnimationController createAnimationController() {
66 assert(_animationController == null); 76 assert(_animationController == null);
67 _animationController = 77 _animationController =
@@ -51,9 +51,9 @@ class GetDialogRoute<T> extends PopupRoute<T> { @@ -51,9 +51,9 @@ class GetDialogRoute<T> extends PopupRoute<T> {
51 Widget buildPage(BuildContext context, Animation<double> animation, 51 Widget buildPage(BuildContext context, Animation<double> animation,
52 Animation<double> secondaryAnimation) { 52 Animation<double> secondaryAnimation) {
53 return Semantics( 53 return Semantics(
54 - child: widget(context, animation, secondaryAnimation),  
55 scopesRoute: true, 54 scopesRoute: true,
56 explicitChildNodes: true, 55 explicitChildNodes: true,
  56 + child: widget(context, animation, secondaryAnimation),
57 ); 57 );
58 } 58 }
59 59
@@ -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
@@ -27,6 +28,7 @@ extension ExtensionBottomSheet on GetInterface { @@ -27,6 +28,7 @@ extension ExtensionBottomSheet on GetInterface {
27 RouteSettings? settings, 28 RouteSettings? settings,
28 Duration? enterBottomSheetDuration, 29 Duration? enterBottomSheetDuration,
29 Duration? exitBottomSheetDuration, 30 Duration? exitBottomSheetDuration,
  31 + Curve? curve,
30 }) { 32 }) {
31 return Navigator.of(overlayContext!, rootNavigator: useRootNavigator) 33 return Navigator.of(overlayContext!, rootNavigator: useRootNavigator)
32 .push(GetModalBottomSheetRoute<T>( 34 .push(GetModalBottomSheetRoute<T>(
@@ -52,6 +54,7 @@ extension ExtensionBottomSheet on GetInterface { @@ -52,6 +54,7 @@ extension ExtensionBottomSheet on GetInterface {
52 enterBottomSheetDuration ?? const Duration(milliseconds: 250), 54 enterBottomSheetDuration ?? const Duration(milliseconds: 250),
53 exitBottomSheetDuration: 55 exitBottomSheetDuration:
54 exitBottomSheetDuration ?? const Duration(milliseconds: 200), 56 exitBottomSheetDuration ?? const Duration(milliseconds: 200),
  57 + curve: curve,
55 )); 58 ));
56 } 59 }
57 } 60 }
@@ -184,7 +187,7 @@ extension ExtensionDialog on GetInterface { @@ -184,7 +187,7 @@ extension ExtensionDialog on GetInterface {
184 actions.add(TextButton( 187 actions.add(TextButton(
185 style: TextButton.styleFrom( 188 style: TextButton.styleFrom(
186 tapTargetSize: MaterialTapTargetSize.shrinkWrap, 189 tapTargetSize: MaterialTapTargetSize.shrinkWrap,
187 - padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), 190 + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
188 shape: RoundedRectangleBorder( 191 shape: RoundedRectangleBorder(
189 side: BorderSide( 192 side: BorderSide(
190 color: buttonColor ?? theme.colorScheme.secondary, 193 color: buttonColor ?? theme.colorScheme.secondary,
@@ -217,8 +220,8 @@ extension ExtensionDialog on GetInterface { @@ -217,8 +220,8 @@ extension ExtensionDialog on GetInterface {
217 ), 220 ),
218 child: Text( 221 child: Text(
219 textConfirm ?? "Ok", 222 textConfirm ?? "Ok",
220 - style:  
221 - TextStyle(color: confirmTextColor ?? theme.backgroundColor), 223 + style: TextStyle(
  224 + color: confirmTextColor ?? theme.colorScheme.background),
222 ), 225 ),
223 onPressed: () { 226 onPressed: () {
224 onConfirm?.call(); 227 onConfirm?.call();
@@ -227,8 +230,8 @@ extension ExtensionDialog on GetInterface { @@ -227,8 +230,8 @@ extension ExtensionDialog on GetInterface {
227 } 230 }
228 231
229 Widget baseAlertDialog = AlertDialog( 232 Widget baseAlertDialog = AlertDialog(
230 - titlePadding: titlePadding ?? EdgeInsets.all(8),  
231 - contentPadding: contentPadding ?? EdgeInsets.all(8), 233 + titlePadding: titlePadding ?? const EdgeInsets.all(8),
  234 + contentPadding: contentPadding ?? const EdgeInsets.all(8),
232 235
233 backgroundColor: backgroundColor ?? theme.dialogBackgroundColor, 236 backgroundColor: backgroundColor ?? theme.dialogBackgroundColor,
234 shape: RoundedRectangleBorder( 237 shape: RoundedRectangleBorder(
@@ -241,7 +244,7 @@ extension ExtensionDialog on GetInterface { @@ -241,7 +244,7 @@ extension ExtensionDialog on GetInterface {
241 content ?? 244 content ??
242 Text(middleText, 245 Text(middleText,
243 textAlign: TextAlign.center, style: middleTextStyle), 246 textAlign: TextAlign.center, style: middleTextStyle),
244 - SizedBox(height: 16), 247 + const SizedBox(height: 16),
245 ButtonTheme( 248 ButtonTheme(
246 minWidth: 78.0, 249 minWidth: 78.0,
247 height: 34.0, 250 height: 34.0,
@@ -392,6 +395,7 @@ extension ExtensionSnackbar on GetInterface { @@ -392,6 +395,7 @@ extension ExtensionSnackbar on GetInterface {
392 Gradient? backgroundGradient, 395 Gradient? backgroundGradient,
393 TextButton? mainButton, 396 TextButton? mainButton,
394 OnTap? onTap, 397 OnTap? onTap,
  398 + OnHover? onHover,
395 bool? isDismissible, 399 bool? isDismissible,
396 bool? showProgressIndicator, 400 bool? showProgressIndicator,
397 DismissDirection? dismissDirection, 401 DismissDirection? dismissDirection,
@@ -430,14 +434,14 @@ extension ExtensionSnackbar on GetInterface { @@ -430,14 +434,14 @@ extension ExtensionSnackbar on GetInterface {
430 ), 434 ),
431 snackPosition: snackPosition ?? SnackPosition.top, 435 snackPosition: snackPosition ?? SnackPosition.top,
432 borderRadius: borderRadius ?? 15, 436 borderRadius: borderRadius ?? 15,
433 - margin: margin ?? EdgeInsets.symmetric(horizontal: 10), 437 + margin: margin ?? const EdgeInsets.symmetric(horizontal: 10),
434 duration: duration, 438 duration: duration,
435 barBlur: barBlur ?? 7.0, 439 barBlur: barBlur ?? 7.0,
436 backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2), 440 backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2),
437 icon: icon, 441 icon: icon,
438 shouldIconPulse: shouldIconPulse ?? true, 442 shouldIconPulse: shouldIconPulse ?? true,
439 maxWidth: maxWidth, 443 maxWidth: maxWidth,
440 - padding: padding ?? EdgeInsets.all(16), 444 + padding: padding ?? const EdgeInsets.all(16),
441 borderColor: borderColor, 445 borderColor: borderColor,
442 borderWidth: borderWidth, 446 borderWidth: borderWidth,
443 leftBarIndicatorColor: leftBarIndicatorColor, 447 leftBarIndicatorColor: leftBarIndicatorColor,
@@ -445,6 +449,7 @@ extension ExtensionSnackbar on GetInterface { @@ -445,6 +449,7 @@ extension ExtensionSnackbar on GetInterface {
445 backgroundGradient: backgroundGradient, 449 backgroundGradient: backgroundGradient,
446 mainButton: mainButton, 450 mainButton: mainButton,
447 onTap: onTap, 451 onTap: onTap,
  452 + onHover: onHover,
448 isDismissible: isDismissible ?? true, 453 isDismissible: isDismissible ?? true,
449 dismissDirection: dismissDirection, 454 dismissDirection: dismissDirection,
450 showProgressIndicator: showProgressIndicator ?? false, 455 showProgressIndicator: showProgressIndicator ?? false,
@@ -454,7 +459,7 @@ extension ExtensionSnackbar on GetInterface { @@ -454,7 +459,7 @@ extension ExtensionSnackbar on GetInterface {
454 snackStyle: snackStyle ?? SnackStyle.floating, 459 snackStyle: snackStyle ?? SnackStyle.floating,
455 forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc, 460 forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc,
456 reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc, 461 reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc,
457 - animationDuration: animationDuration ?? Duration(seconds: 1), 462 + animationDuration: animationDuration ?? const Duration(seconds: 1),
458 overlayBlur: overlayBlur ?? 0.0, 463 overlayBlur: overlayBlur ?? 0.0,
459 overlayColor: overlayColor ?? Colors.transparent, 464 overlayColor: overlayColor ?? Colors.transparent,
460 userInputForm: userInputForm); 465 userInputForm: userInputForm);
@@ -1007,36 +1012,36 @@ extension GetNavigationExt on GetInterface { @@ -1007,36 +1012,36 @@ extension GetNavigationExt on GetInterface {
1007 } 1012 }
1008 return Uri.tryParse(name)?.toString() ?? name; 1013 return Uri.tryParse(name)?.toString() ?? name;
1009 } 1014 }
1010 -  
1011 - /// change default config of Get  
1012 - void config(  
1013 - {bool? enableLog,  
1014 - LogWriterCallback? logWriterCallback,  
1015 - bool? defaultPopGesture,  
1016 - bool? defaultOpaqueRoute,  
1017 - Duration? defaultDurationTransition,  
1018 - bool? defaultGlobalState,  
1019 - Transition? defaultTransition}) {  
1020 - if (enableLog != null) {  
1021 - Get.isLogEnable = enableLog;  
1022 - }  
1023 - if (logWriterCallback != null) {  
1024 - Get.log = logWriterCallback;  
1025 - }  
1026 - if (defaultPopGesture != null) {  
1027 - _getxController.defaultPopGesture = defaultPopGesture;  
1028 - }  
1029 - if (defaultOpaqueRoute != null) {  
1030 - _getxController.defaultOpaqueRoute = defaultOpaqueRoute;  
1031 - }  
1032 - if (defaultTransition != null) {  
1033 - _getxController.defaultTransition = defaultTransition;  
1034 - }  
1035 -  
1036 - if (defaultDurationTransition != null) {  
1037 - _getxController.defaultTransitionDuration = defaultDurationTransition;  
1038 - }  
1039 - } 1015 + //TODO: Deprecated
  1016 + // /// change default config of Get
  1017 + // void config(
  1018 + // {bool? enableLog,
  1019 + // LogWriterCallback? logWriterCallback,
  1020 + // bool? defaultPopGesture,
  1021 + // bool? defaultOpaqueRoute,
  1022 + // Duration? defaultDurationTransition,
  1023 + // bool? defaultGlobalState,
  1024 + // Transition? defaultTransition}) {
  1025 + // if (enableLog != null) {
  1026 + // Get.isLogEnable = enableLog;
  1027 + // }
  1028 + // if (logWriterCallback != null) {
  1029 + // Get.log = logWriterCallback;
  1030 + // }
  1031 + // if (defaultPopGesture != null) {
  1032 + // _getxController.defaultPopGesture = defaultPopGesture;
  1033 + // }
  1034 + // if (defaultOpaqueRoute != null) {
  1035 + // _getxController.defaultOpaqueRoute = defaultOpaqueRoute;
  1036 + // }
  1037 + // if (defaultTransition != null) {
  1038 + // _getxController.defaultTransition = defaultTransition;
  1039 + // }
  1040 +
  1041 + // if (defaultDurationTransition != null) {
  1042 + // _getxController.defaultTransitionDuration = defaultDurationTransition;
  1043 + // }
  1044 + // }
1040 1045
1041 Future<void> updateLocale(Locale l) async { 1046 Future<void> updateLocale(Locale l) async {
1042 Get.locale = l; 1047 Get.locale = l;
@@ -1060,33 +1065,33 @@ extension GetNavigationExt on GetInterface { @@ -1060,33 +1065,33 @@ extension GetNavigationExt on GetInterface {
1060 await engine.performReassemble(); 1065 await engine.performReassemble();
1061 } 1066 }
1062 1067
1063 - void appUpdate() => _getxController.update(); 1068 + void appUpdate() => rootController.update();
1064 1069
1065 void changeTheme(ThemeData theme) { 1070 void changeTheme(ThemeData theme) {
1066 - _getxController.setTheme(theme); 1071 + rootController.setTheme(theme);
1067 } 1072 }
1068 1073
1069 void changeThemeMode(ThemeMode themeMode) { 1074 void changeThemeMode(ThemeMode themeMode) {
1070 - _getxController.setThemeMode(themeMode); 1075 + rootController.setThemeMode(themeMode);
1071 } 1076 }
1072 1077
1073 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { 1078 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
1074 - return _getxController.addKey(newKey); 1079 + return rootController.addKey(newKey);
1075 } 1080 }
1076 1081
1077 GetDelegate? nestedKey(String? key) { 1082 GetDelegate? nestedKey(String? key) {
1078 - return _getxController.nestedKey(key); 1083 + return rootController.nestedKey(key);
1079 } 1084 }
1080 1085
1081 GetDelegate searchDelegate(dynamic k) { 1086 GetDelegate searchDelegate(dynamic k) {
1082 - GetDelegate _key; 1087 + GetDelegate key;
1083 if (k == null) { 1088 if (k == null) {
1084 - _key = Get.rootController.rootDelegate; 1089 + key = Get.rootController.rootDelegate;
1085 } else { 1090 } else {
1086 if (!keys.containsKey(k)) { 1091 if (!keys.containsKey(k)) {
1087 throw 'Route id ($k) not found'; 1092 throw 'Route id ($k) not found';
1088 } 1093 }
1089 - _key = keys[k]!; 1094 + key = keys[k]!;
1090 } 1095 }
1091 1096
1092 // if (_key.listenersLength == 0 && !testMode) { 1097 // if (_key.listenersLength == 0 && !testMode) {
@@ -1099,12 +1104,12 @@ extension GetNavigationExt on GetInterface { @@ -1099,12 +1104,12 @@ extension GetNavigationExt on GetInterface {
1099 // """; 1104 // """;
1100 // } 1105 // }
1101 1106
1102 - return _key; 1107 + return key;
1103 } 1108 }
1104 1109
1105 /// give current arguments 1110 /// give current arguments
1106 //dynamic get arguments => routing.args; 1111 //dynamic get arguments => routing.args;
1107 - dynamic get arguments => _getxController.rootDelegate.arguments(); 1112 + dynamic get arguments => rootController.rootDelegate.arguments();
1108 1113
1109 /// give name from current route 1114 /// give name from current route
1110 String get currentRoute => routing.current; 1115 String get currentRoute => routing.current;
@@ -1153,11 +1158,11 @@ extension GetNavigationExt on GetInterface { @@ -1153,11 +1158,11 @@ extension GetNavigationExt on GetInterface {
1153 1158
1154 /// give access to Theme.of(context) 1159 /// give access to Theme.of(context)
1155 ThemeData get theme { 1160 ThemeData get theme {
1156 - var _theme = ThemeData.fallback(); 1161 + var theme = ThemeData.fallback();
1157 if (context != null) { 1162 if (context != null) {
1158 - _theme = Theme.of(context!); 1163 + theme = Theme.of(context!);
1159 } 1164 }
1160 - return _theme; 1165 + return theme;
1161 } 1166 }
1162 1167
1163 /// The current null safe [WidgetsBinding] 1168 /// The current null safe [WidgetsBinding]
@@ -1217,11 +1222,13 @@ extension GetNavigationExt on GetInterface { @@ -1217,11 +1222,13 @@ extension GetNavigationExt on GetInterface {
1217 // /// give access to Immutable MediaQuery.of(context).size.width 1222 // /// give access to Immutable MediaQuery.of(context).size.width
1218 // double get width => MediaQuery.of(context).size.width; 1223 // double get width => MediaQuery.of(context).size.width;
1219 1224
1220 - GlobalKey<NavigatorState> get key => _getxController.key; 1225 + GlobalKey<NavigatorState> get key => rootController.key;
1221 1226
1222 - Map<dynamic, GetDelegate> get keys => _getxController.keys; 1227 + Map<dynamic, GetDelegate> get keys => rootController.keys;
1223 1228
1224 - GetMaterialController get rootController => _getxController; 1229 + GetRootState get rootController => GetRootState.controller;
  1230 +
  1231 + ConfigData get _getxController => GetRootState.controller.config;
1225 1232
1226 bool get defaultPopGesture => _getxController.defaultPopGesture; 1233 bool get defaultPopGesture => _getxController.defaultPopGesture;
1227 bool get defaultOpaqueRoute => _getxController.defaultOpaqueRoute; 1234 bool get defaultOpaqueRoute => _getxController.defaultOpaqueRoute;
@@ -1244,20 +1251,18 @@ extension GetNavigationExt on GetInterface { @@ -1244,20 +1251,18 @@ extension GetNavigationExt on GetInterface {
1244 1251
1245 Routing get routing => _getxController.routing; 1252 Routing get routing => _getxController.routing;
1246 1253
1247 - Map<String, String?> get parameters =>  
1248 - _getxController.rootDelegate.parameters;  
1249 set parameters(Map<String, String?> newParameters) => 1254 set parameters(Map<String, String?> newParameters) =>
1250 - _getxController.parameters = newParameters; 1255 + rootController.parameters = newParameters;
  1256 +
  1257 + set testMode(bool isTest) => rootController.testMode = isTest;
1251 1258
1252 bool get testMode => _getxController.testMode; 1259 bool get testMode => _getxController.testMode;
1253 - set testMode(bool isTest) => _getxController.testMode = isTest; 1260 +
  1261 + Map<String, String?> get parameters => rootController.rootDelegate.parameters;
1254 1262
1255 /// Casts the stored router delegate to a desired type 1263 /// Casts the stored router delegate to a desired type
1256 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => 1264 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() =>
1257 _getxController.routerDelegate as TDelegate?; 1265 _getxController.routerDelegate as TDelegate?;
1258 -  
1259 - static final GetMaterialController _getxController =  
1260 - Get.find<GetMaterialController>();  
1261 } 1266 }
1262 1267
1263 extension OverlayExt on GetInterface { 1268 extension OverlayExt on GetInterface {
@@ -1280,8 +1285,8 @@ extension OverlayExt on GetInterface { @@ -1280,8 +1285,8 @@ extension OverlayExt on GetInterface {
1280 }); 1285 });
1281 final overlayEntryLoader = OverlayEntry(builder: (context) { 1286 final overlayEntryLoader = OverlayEntry(builder: (context) {
1282 return loadingWidget ?? 1287 return loadingWidget ??
1283 - Center(  
1284 - child: Container( 1288 + const Center(
  1289 + child: SizedBox(
1285 height: 90, 1290 height: 90,
1286 width: 90, 1291 width: 90,
1287 child: Text('Loading...'), 1292 child: Text('Loading...'),
@@ -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;
@@ -67,7 +66,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -67,7 +66,7 @@ class GetCupertinoApp extends StatelessWidget {
67 final List<Bind> binds; 66 final List<Bind> binds;
68 final ScrollBehavior? scrollBehavior; 67 final ScrollBehavior? scrollBehavior;
69 68
70 - GetCupertinoApp({ 69 + const GetCupertinoApp({
71 Key? key, 70 Key? key,
72 this.theme, 71 this.theme,
73 this.navigatorKey, 72 this.navigatorKey,
@@ -128,18 +127,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -128,18 +127,7 @@ class GetCupertinoApp extends StatelessWidget {
128 routerConfig = null, 127 routerConfig = null,
129 super(key: key); 128 super(key: key);
130 129
131 - static String _cleanRouteName(String name) {  
132 - name = name.replaceAll('() => ', '');  
133 -  
134 - /// uncommonent for URL styling.  
135 - // name = name.paramCase!;  
136 - if (!name.startsWith('/')) {  
137 - name = '/$name';  
138 - }  
139 - return Uri.tryParse(name)?.toString() ?? name;  
140 - }  
141 -  
142 - GetCupertinoApp.router({ 130 + const GetCupertinoApp.router({
143 Key? key, 131 Key? key,
144 this.theme, 132 this.theme,
145 this.routeInformationProvider, 133 this.routeInformationProvider,
@@ -200,67 +188,53 @@ class GetCupertinoApp extends StatelessWidget { @@ -200,67 +188,53 @@ class GetCupertinoApp extends StatelessWidget {
200 188
201 @override 189 @override
202 Widget build(BuildContext context) { 190 Widget build(BuildContext context) {
203 - return Binds(  
204 - binds: [  
205 - Bind.lazyPut<GetMaterialController>(  
206 - () => GetMaterialController(  
207 - ConfigData(  
208 - backButtonDispatcher: backButtonDispatcher,  
209 - binds: binds,  
210 - customTransition: customTransition,  
211 - defaultGlobalState: defaultGlobalState,  
212 - defaultTransition: defaultTransition,  
213 - enableLog: enableLog,  
214 - fallbackLocale: fallbackLocale,  
215 - getPages: getPages,  
216 - home: home,  
217 - initialRoute: initialRoute,  
218 - locale: locale,  
219 - logWriterCallback: logWriterCallback,  
220 - navigatorKey: navigatorKey,  
221 - navigatorObservers: navigatorObservers,  
222 - onDispose: onDispose,  
223 - onInit: onInit,  
224 - onReady: onReady,  
225 - opaqueRoute: opaqueRoute,  
226 - popGesture: popGesture,  
227 - routeInformationParser: routeInformationParser,  
228 - routeInformationProvider: routeInformationProvider,  
229 - routerDelegate: routerDelegate,  
230 - routingCallback: routingCallback,  
231 - scaffoldMessengerKey: GlobalKey<ScaffoldMessengerState>(),  
232 - smartManagement: smartManagement,  
233 - transitionDuration: transitionDuration,  
234 - translations: translations,  
235 - translationsKeys: translationsKeys,  
236 - unknownRoute: unknownRoute,  
237 - ),  
238 - ),  
239 - onClose: () {  
240 - Get.clearTranslations();  
241 - RouterReportManager.dispose();  
242 - Get.resetInstance(clearRouteBindings: true);  
243 - },  
244 - ),  
245 - ...binds,  
246 - ], 191 + return GetRoot(
  192 + config: ConfigData(
  193 + backButtonDispatcher: backButtonDispatcher,
  194 + binds: binds,
  195 + customTransition: customTransition,
  196 + defaultGlobalState: defaultGlobalState,
  197 + defaultTransition: defaultTransition,
  198 + enableLog: enableLog,
  199 + fallbackLocale: fallbackLocale,
  200 + getPages: getPages,
  201 + home: home,
  202 + initialRoute: initialRoute,
  203 + locale: locale,
  204 + logWriterCallback: logWriterCallback,
  205 + navigatorKey: navigatorKey,
  206 + navigatorObservers: navigatorObservers,
  207 + onDispose: onDispose,
  208 + onInit: onInit,
  209 + onReady: onReady,
  210 + routeInformationParser: routeInformationParser,
  211 + routeInformationProvider: routeInformationProvider,
  212 + routerDelegate: routerDelegate,
  213 + routingCallback: routingCallback,
  214 + scaffoldMessengerKey: GlobalKey<ScaffoldMessengerState>(),
  215 + smartManagement: smartManagement,
  216 + transitionDuration: transitionDuration,
  217 + translations: translations,
  218 + translationsKeys: translationsKeys,
  219 + unknownRoute: unknownRoute,
  220 + ),
247 child: Builder(builder: (context) { 221 child: Builder(builder: (context) {
248 - final controller = context.listen<GetMaterialController>(); 222 + final controller = GetRoot.of(context);
249 return CupertinoApp.router( 223 return CupertinoApp.router(
250 - routerDelegate: controller.routerDelegate,  
251 - routeInformationParser: controller.routeInformationParser, 224 + routerDelegate: controller.config.routerDelegate,
  225 + routeInformationParser: controller.config.routeInformationParser,
252 backButtonDispatcher: backButtonDispatcher, 226 backButtonDispatcher: backButtonDispatcher,
253 routeInformationProvider: routeInformationProvider, 227 routeInformationProvider: routeInformationProvider,
254 routerConfig: routerConfig, 228 routerConfig: routerConfig,
255 - key: controller.unikey, 229 + key: controller.config.unikey,
256 builder: (context, child) => Directionality( 230 builder: (context, child) => Directionality(
257 textDirection: textDirection ?? 231 textDirection: textDirection ??
258 (rtlLanguages.contains(Get.locale?.languageCode) 232 (rtlLanguages.contains(Get.locale?.languageCode)
259 ? TextDirection.rtl 233 ? TextDirection.rtl
260 : TextDirection.ltr), 234 : TextDirection.ltr),
261 child: builder == null 235 child: builder == null
262 - ? (child ?? Material())  
263 - : builder!(context, child ?? Material()), 236 + ? (child ?? const Material())
  237 + : builder!(context, child ?? const Material()),
264 ), 238 ),
265 title: title, 239 title: title,
266 onGenerateTitle: onGenerateTitle, 240 onGenerateTitle: onGenerateTitle,
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;
@@ -132,7 +131,7 @@ class GetMaterialApp extends StatelessWidget { @@ -132,7 +131,7 @@ class GetMaterialApp extends StatelessWidget {
132 routerConfig = null, 131 routerConfig = null,
133 super(key: key); 132 super(key: key);
134 133
135 - GetMaterialApp.router({ 134 + const GetMaterialApp.router({
136 Key? key, 135 Key? key,
137 this.routeInformationProvider, 136 this.routeInformationProvider,
138 this.scaffoldMessengerKey, 137 this.scaffoldMessengerKey,
@@ -196,80 +195,80 @@ class GetMaterialApp extends StatelessWidget { @@ -196,80 +195,80 @@ class GetMaterialApp extends StatelessWidget {
196 195
197 @override 196 @override
198 Widget build(BuildContext context) { 197 Widget build(BuildContext context) {
199 - return Binds(  
200 - binds: [  
201 - Bind.lazyPut<GetMaterialController>(  
202 - () => GetMaterialController(  
203 - ConfigData(  
204 - backButtonDispatcher: backButtonDispatcher,  
205 - binds: binds,  
206 - customTransition: customTransition,  
207 - defaultGlobalState: defaultGlobalState,  
208 - defaultTransition: defaultTransition,  
209 - enableLog: enableLog,  
210 - fallbackLocale: fallbackLocale,  
211 - getPages: getPages,  
212 - home: home,  
213 - initialRoute: initialRoute,  
214 - locale: locale,  
215 - logWriterCallback: logWriterCallback,  
216 - navigatorKey: navigatorKey,  
217 - navigatorObservers: navigatorObservers,  
218 - onDispose: onDispose,  
219 - onInit: onInit,  
220 - onReady: onReady,  
221 - opaqueRoute: opaqueRoute,  
222 - popGesture: popGesture,  
223 - routeInformationParser: routeInformationParser,  
224 - routeInformationProvider: routeInformationProvider,  
225 - routerDelegate: routerDelegate,  
226 - routingCallback: routingCallback,  
227 - scaffoldMessengerKey: scaffoldMessengerKey,  
228 - smartManagement: smartManagement,  
229 - transitionDuration: transitionDuration,  
230 - translations: translations,  
231 - translationsKeys: translationsKeys,  
232 - unknownRoute: unknownRoute,  
233 - ),  
234 - ),  
235 - onClose: () {  
236 - Get.clearTranslations();  
237 - RouterReportManager.dispose();  
238 - Get.resetInstance(clearRouteBindings: true);  
239 - },  
240 - ),  
241 - ...binds,  
242 - ], 198 + return GetRoot(
  199 + config: ConfigData(
  200 + backButtonDispatcher: backButtonDispatcher,
  201 + binds: binds,
  202 + customTransition: customTransition,
  203 + defaultGlobalState: defaultGlobalState,
  204 + defaultTransition: defaultTransition,
  205 + enableLog: enableLog,
  206 + fallbackLocale: fallbackLocale,
  207 + getPages: getPages,
  208 + home: home,
  209 + initialRoute: initialRoute,
  210 + locale: locale,
  211 + logWriterCallback: logWriterCallback,
  212 + navigatorKey: navigatorKey,
  213 + navigatorObservers: navigatorObservers,
  214 + onDispose: onDispose,
  215 + onInit: onInit,
  216 + onReady: onReady,
  217 + routeInformationParser: routeInformationParser,
  218 + routeInformationProvider: routeInformationProvider,
  219 + routerDelegate: routerDelegate,
  220 + routingCallback: routingCallback,
  221 + scaffoldMessengerKey: scaffoldMessengerKey,
  222 + smartManagement: smartManagement,
  223 + transitionDuration: transitionDuration,
  224 + translations: translations,
  225 + translationsKeys: translationsKeys,
  226 + unknownRoute: unknownRoute,
  227 + theme: theme,
  228 + darkTheme: darkTheme,
  229 + themeMode: themeMode,
  230 + ),
  231 + // binds: [
  232 + // Bind.lazyPut<GetMaterialController>(
  233 + // () => GetMaterialController(
  234 +
  235 + // ),
  236 + // onClose: () {
  237 + // Get.clearTranslations();
  238 + // RouterReportManager.dispose();
  239 + // Get.resetInstance(clearRouteBindings: true);
  240 + // },
  241 + // ),
  242 + // ...binds,
  243 + // ],
243 child: Builder(builder: (context) { 244 child: Builder(builder: (context) {
244 - final controller = context.listen<GetMaterialController>(); 245 + final controller = GetRoot.of(context);
245 return MaterialApp.router( 246 return MaterialApp.router(
246 - routerDelegate: controller.routerDelegate,  
247 - routeInformationParser: controller.routeInformationParser, 247 + routerDelegate: controller.config.routerDelegate,
  248 + routeInformationParser: controller.config.routeInformationParser,
248 backButtonDispatcher: backButtonDispatcher, 249 backButtonDispatcher: backButtonDispatcher,
249 routeInformationProvider: routeInformationProvider, 250 routeInformationProvider: routeInformationProvider,
250 routerConfig: routerConfig, 251 routerConfig: routerConfig,
251 - key: controller.unikey, 252 + key: controller.config.unikey,
252 builder: (context, child) => Directionality( 253 builder: (context, child) => Directionality(
253 textDirection: textDirection ?? 254 textDirection: textDirection ??
254 (rtlLanguages.contains(Get.locale?.languageCode) 255 (rtlLanguages.contains(Get.locale?.languageCode)
255 ? TextDirection.rtl 256 ? TextDirection.rtl
256 : TextDirection.ltr), 257 : TextDirection.ltr),
257 child: builder == null 258 child: builder == null
258 - ? (child ?? Material())  
259 - : builder!(context, child ?? Material()), 259 + ? (child ?? const Material())
  260 + : builder!(context, child ?? const Material()),
260 ), 261 ),
261 title: title, 262 title: title,
262 onGenerateTitle: onGenerateTitle, 263 onGenerateTitle: onGenerateTitle,
263 color: color, 264 color: color,
264 - theme: controller.theme ?? theme ?? ThemeData.fallback(),  
265 - darkTheme: controller.darkTheme ??  
266 - darkTheme ??  
267 - theme ?? 265 + theme: controller.config.theme ?? ThemeData.fallback(),
  266 + darkTheme: controller.config.darkTheme ??
  267 + controller.config.theme ??
268 ThemeData.fallback(), 268 ThemeData.fallback(),
269 - themeMode: controller.themeMode ?? themeMode, 269 + themeMode: controller.config.themeMode,
270 locale: Get.locale ?? locale, 270 locale: Get.locale ?? locale,
271 - scaffoldMessengerKey:  
272 - scaffoldMessengerKey ?? controller.scaffoldMessengerKey, 271 + scaffoldMessengerKey: controller.config.scaffoldMessengerKey,
273 localizationsDelegates: localizationsDelegates, 272 localizationsDelegates: localizationsDelegates,
274 localeListResolutionCallback: localeListResolutionCallback, 273 localeListResolutionCallback: localeListResolutionCallback,
275 localeResolutionCallback: localeResolutionCallback, 274 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 + const 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 +}
1 -import 'package:flutter/foundation.dart';  
2 -import 'package:flutter/material.dart';  
3 -  
4 -import '../../../get.dart';  
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 -  
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 -  
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 -}  
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> {
@@ -132,15 +132,15 @@ class GetPageRoute<T> extends PageRoute<T> @@ -132,15 +132,15 @@ class GetPageRoute<T> extends PageRoute<T>
132 final dep = item.dependencies(); 132 final dep = item.dependencies();
133 if (dep is List<Bind>) { 133 if (dep is List<Bind>) {
134 _child = Binds( 134 _child = Binds(
135 - child: middlewareRunner.runOnPageBuilt(pageToBuild()),  
136 binds: dep, 135 binds: dep,
  136 + child: middlewareRunner.runOnPageBuilt(pageToBuild()),
137 ); 137 );
138 } 138 }
139 } 139 }
140 } else if (bindingsToBind is List<Bind>) { 140 } else if (bindingsToBind is List<Bind>) {
141 _child = Binds( 141 _child = Binds(
142 - child: middlewareRunner.runOnPageBuilt(pageToBuild()),  
143 binds: bindingsToBind, 142 binds: bindingsToBind,
  143 + child: middlewareRunner.runOnPageBuilt(pageToBuild()),
144 ); 144 );
145 } 145 }
146 } 146 }
@@ -89,7 +89,7 @@ class SlideDownTransition { @@ -89,7 +89,7 @@ class SlideDownTransition {
89 Widget child) { 89 Widget child) {
90 return SlideTransition( 90 return SlideTransition(
91 position: Tween<Offset>( 91 position: Tween<Offset>(
92 - begin: Offset(0.0, 1.0), 92 + begin: const Offset(0.0, 1.0),
93 end: Offset.zero, 93 end: Offset.zero,
94 ).animate(animation), 94 ).animate(animation),
95 child: child, 95 child: child,
@@ -107,7 +107,7 @@ class SlideLeftTransition { @@ -107,7 +107,7 @@ class SlideLeftTransition {
107 Widget child) { 107 Widget child) {
108 return SlideTransition( 108 return SlideTransition(
109 position: Tween<Offset>( 109 position: Tween<Offset>(
110 - begin: Offset(-1.0, 0.0), 110 + begin: const Offset(-1.0, 0.0),
111 end: Offset.zero, 111 end: Offset.zero,
112 ).animate(animation), 112 ).animate(animation),
113 child: child, 113 child: child,
@@ -125,7 +125,7 @@ class SlideRightTransition { @@ -125,7 +125,7 @@ class SlideRightTransition {
125 Widget child) { 125 Widget child) {
126 return SlideTransition( 126 return SlideTransition(
127 position: Tween<Offset>( 127 position: Tween<Offset>(
128 - begin: Offset(1.0, 0.0), 128 + begin: const Offset(1.0, 0.0),
129 end: Offset.zero, 129 end: Offset.zero,
130 ).animate(animation), 130 ).animate(animation),
131 child: child, 131 child: child,
@@ -143,7 +143,7 @@ class SlideTopTransition { @@ -143,7 +143,7 @@ class SlideTopTransition {
143 Widget child) { 143 Widget child) {
144 return SlideTransition( 144 return SlideTransition(
145 position: Tween<Offset>( 145 position: Tween<Offset>(
146 - begin: Offset(0.0, -1.0), 146 + begin: const Offset(0.0, -1.0),
147 end: Offset.zero, 147 end: Offset.zero,
148 ).animate(animation), 148 ).animate(animation),
149 child: child, 149 child: child,
@@ -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;
@@ -48,7 +48,7 @@ class GetNavigator extends Navigator { @@ -48,7 +48,7 @@ class GetNavigator extends Navigator {
48 ); 48 );
49 49
50 GetNavigator({ 50 GetNavigator({
51 - GlobalKey<NavigatorState>? key, 51 + Key? key,
52 bool Function(Route<dynamic>, dynamic)? onPopPage, 52 bool Function(Route<dynamic>, dynamic)? onPopPage,
53 required List<GetPage> pages, 53 required List<GetPage> pages,
54 List<NavigatorObserver>? observers, 54 List<NavigatorObserver>? observers,
@@ -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,25 +157,26 @@ class GetPage<T> extends Page<T> { @@ -153,25 +157,26 @@ 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
159 @override 164 @override
160 Route<T> createRoute(BuildContext context) { 165 Route<T> createRoute(BuildContext context) {
161 // return GetPageRoute<T>(settings: this, page: page); 166 // return GetPageRoute<T>(settings: this, page: page);
162 - final _page = PageRedirect( 167 + final page = PageRedirect(
163 route: this, 168 route: this,
164 settings: this, 169 settings: this,
165 unknownRoute: unknownRoute, 170 unknownRoute: unknownRoute,
166 ).getPageToRoute<T>(this, unknownRoute, context); 171 ).getPageToRoute<T>(this, unknownRoute, context);
167 172
168 - return _page; 173 + return page;
169 } 174 }
170 175
171 static PathDecoded _nameToRegex(String path) { 176 static PathDecoded _nameToRegex(String path) {
172 var keys = <String?>[]; 177 var keys = <String?>[];
173 178
174 - String _replace(Match pattern) { 179 + String recursiveReplace(Match pattern) {
175 var buffer = StringBuffer('(?:'); 180 var buffer = StringBuffer('(?:');
176 181
177 if (pattern[1] != null) buffer.write('.'); 182 if (pattern[1] != null) buffer.write('.');
@@ -183,7 +188,7 @@ class GetPage<T> extends Page<T> { @@ -183,7 +188,7 @@ class GetPage<T> extends Page<T> {
183 } 188 }
184 189
185 var stringPath = '$path/?' 190 var stringPath = '$path/?'
186 - .replaceAllMapped(RegExp(r'(\.)?:(\w+)(\?)?'), _replace) 191 + .replaceAllMapped(RegExp(r'(\.)?:(\w+)(\?)?'), recursiveReplace)
187 .replaceAll('//', '/'); 192 .replaceAll('//', '/');
188 193
189 return PathDecoded(RegExp('^$stringPath\$'), keys); 194 return PathDecoded(RegExp('^$stringPath\$'), keys);
@@ -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;
@@ -72,7 +93,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -72,7 +93,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
72 }) : navigatorKey = navigatorKey ?? GlobalKey<NavigatorState>(), 93 }) : navigatorKey = navigatorKey ?? GlobalKey<NavigatorState>(),
73 notFoundRoute = notFoundRoute ??= GetPage( 94 notFoundRoute = notFoundRoute ??= GetPage(
74 name: '/404', 95 name: '/404',
75 - page: () => Scaffold( 96 + page: () => const Scaffold(
76 body: Center(child: Text('Route not found')), 97 body: Center(child: Text('Route not found')),
77 ), 98 ),
78 ) { 99 ) {
@@ -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;
@@ -112,11 +133,11 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -112,11 +133,11 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
112 _activePages.add(res); 133 _activePages.add(res);
113 } 134 }
114 135
115 - Future<T?> _unsafeHistoryRemove<T>(RouteDecoder config, T result) async {  
116 - var index = _activePages.indexOf(config);  
117 - if (index >= 0) return _unsafeHistoryRemoveAt(index, result);  
118 - return null;  
119 - } 136 + // Future<T?> _unsafeHistoryRemove<T>(RouteDecoder config, T result) async {
  137 + // var index = _activePages.indexOf(config);
  138 + // if (index >= 0) return _unsafeHistoryRemoveAt(index, result);
  139 + // return null;
  140 + // }
120 141
121 Future<T?> _unsafeHistoryRemoveAt<T>(int index, T result) async { 142 Future<T?> _unsafeHistoryRemoveAt<T>(int index, T result) async {
122 if (index == _activePages.length - 1 && _activePages.length > 1) { 143 if (index == _activePages.length - 1 && _activePages.length > 1) {
@@ -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,
@@ -786,7 +802,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -786,7 +802,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
786 if (wasPopup) return true; 802 if (wasPopup) return true;
787 803
788 if (_canPop(popMode ?? backButtonPopMode)) { 804 if (_canPop(popMode ?? backButtonPopMode)) {
789 - await _pop(popMode ?? backButtonPopMode, result); 805 + await _pop(popMode ?? backButtonPopMode, result);
790 notifyListeners(); 806 notifyListeners();
791 return true; 807 return true;
792 } 808 }
@@ -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
@@ -379,8 +380,8 @@ Cannot read the previousTitle for a route that has not yet been installed''', @@ -379,8 +380,8 @@ Cannot read the previousTitle for a route that has not yet been installed''',
379 ? CurvedAnimation(parent: animation, curve: finalCurve) 380 ? CurvedAnimation(parent: animation, curve: finalCurve)
380 : animation, 381 : animation,
381 secondaryRouteAnimation: secondaryAnimation, 382 secondaryRouteAnimation: secondaryAnimation,
382 - child: child,  
383 linearTransition: linearTransition, 383 linearTransition: linearTransition,
  384 + child: child,
384 ); 385 );
385 } else { 386 } else {
386 if (route.customTransition != null) { 387 if (route.customTransition != null) {
@@ -635,7 +636,7 @@ Cannot read the previousTitle for a route that has not yet been installed''', @@ -635,7 +636,7 @@ Cannot read the previousTitle for a route that has not yet been installed''',
635 )); 636 ));
636 637
637 case Transition.fade: 638 case Transition.fade:
638 - return FadeUpwardsPageTransitionsBuilder().buildTransitions( 639 + return const FadeUpwardsPageTransitionsBuilder().buildTransitions(
639 route, 640 route,
640 context, 641 context,
641 animation, 642 animation,
@@ -655,7 +656,7 @@ Cannot read the previousTitle for a route that has not yet been installed''', @@ -655,7 +656,7 @@ Cannot read the previousTitle for a route that has not yet been installed''',
655 )); 656 ));
656 657
657 case Transition.topLevel: 658 case Transition.topLevel:
658 - return ZoomPageTransitionsBuilder().buildTransitions( 659 + return const ZoomPageTransitionsBuilder().buildTransitions(
659 route, 660 route,
660 context, 661 context,
661 animation, 662 animation,
@@ -675,7 +676,7 @@ Cannot read the previousTitle for a route that has not yet been installed''', @@ -675,7 +676,7 @@ Cannot read the previousTitle for a route that has not yet been installed''',
675 )); 676 ));
676 677
677 case Transition.native: 678 case Transition.native:
678 - return PageTransitionsTheme().buildTransitions( 679 + return const PageTransitionsTheme().buildTransitions(
679 route, 680 route,
680 context, 681 context,
681 iosAnimation, 682 iosAnimation,
@@ -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);
@@ -57,17 +57,17 @@ class Dependencies { @@ -57,17 +57,17 @@ class Dependencies {
57 } 57 }
58 58
59 abstract class Module extends StatefulWidget { 59 abstract class Module extends StatefulWidget {
60 - Module({Key? key}) : super(key: key); 60 + const Module({Key? key}) : super(key: key);
61 61
62 Widget view(BuildContext context); 62 Widget view(BuildContext context);
63 63
64 void dependencies(Dependencies i); 64 void dependencies(Dependencies i);
65 65
66 @override 66 @override
67 - _ModuleState createState() => _ModuleState(); 67 + ModuleState createState() => ModuleState();
68 } 68 }
69 69
70 -class _ModuleState extends State<Module> { 70 +class ModuleState extends State<Module> {
71 @override 71 @override
72 void initState() { 72 void initState() {
73 RouterReportManager.instance.reportCurrentRoute(this); 73 RouterReportManager.instance.reportCurrentRoute(this);
  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 +}
@@ -185,6 +185,7 @@ class GetObserver extends NavigatorObserver { @@ -185,6 +185,7 @@ class GetObserver extends NavigatorObserver {
185 } 185 }
186 } 186 }
187 187
  188 +//TODO: Use copyWith, and remove mutate variables
188 class Routing { 189 class Routing {
189 String current; 190 String current;
190 String previous; 191 String previous;
1 import 'package:flutter/foundation.dart'; 1 import 'package:flutter/foundation.dart';
2 2
3 -import '../../../route_manager.dart'; 3 +import '../../../get.dart';
4 4
5 @immutable 5 @immutable
6 class RouteDecoder { 6 class RouteDecoder {
@@ -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,
@@ -57,10 +57,10 @@ class RouteDecoder { @@ -57,10 +57,10 @@ class RouteDecoder {
57 } 57 }
58 58
59 void replaceArguments(Object? arguments) { 59 void replaceArguments(Object? arguments) {
60 - final _route = route;  
61 - if (_route != null) {  
62 - final index = currentTreeBranch.indexOf(_route);  
63 - currentTreeBranch[index] = _route.copy(arguments: arguments); 60 + final newRoute = route;
  61 + if (newRoute != null) {
  62 + final index = currentTreeBranch.indexOf(newRoute);
  63 + currentTreeBranch[index] = newRoute.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,14 +184,28 @@ class ParseRouteTree { @@ -185,14 +184,28 @@ 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 ];
  190 +
  191 + final parentBindings = [
  192 + if (page.binding != null) page.binding!,
  193 + if (page.bindings.isNotEmpty) ...page.bindings,
  194 + if (route.bindings.isNotEmpty) ...route.bindings
  195 + ];
  196 +
  197 + final parentBinds = [
  198 + if (page.binds.isNotEmpty) ...page.binds,
  199 + if (route.binds.isNotEmpty) ...route.binds
  200 + ];
  201 +
191 result.add( 202 result.add(
192 _addChild( 203 _addChild(
193 page, 204 page,
194 parentPath, 205 parentPath,
195 parentMiddlewares, 206 parentMiddlewares,
  207 + parentBindings,
  208 + parentBinds,
196 ), 209 ),
197 ); 210 );
198 211
@@ -203,7 +216,16 @@ class ParseRouteTree { @@ -203,7 +216,16 @@ class ParseRouteTree {
203 parentPath, 216 parentPath,
204 [ 217 [
205 ...parentMiddlewares, 218 ...parentMiddlewares,
206 - if (child.middlewares != null) ...child.middlewares!, 219 + if (child.middlewares.isNotEmpty) ...child.middlewares,
  220 + ],
  221 + [
  222 + ...parentBindings,
  223 + if (child.binding != null) child.binding!,
  224 + if (child.bindings.isNotEmpty) ...child.bindings,
  225 + ],
  226 + [
  227 + ...parentBinds,
  228 + if (child.binds.isNotEmpty) ...child.binds,
207 ], 229 ],
208 )); 230 ));
209 } 231 }
@@ -213,10 +235,19 @@ class ParseRouteTree { @@ -213,10 +235,19 @@ class ParseRouteTree {
213 235
214 /// Change the Path for a [GetPage] 236 /// Change the Path for a [GetPage]
215 GetPage _addChild( 237 GetPage _addChild(
216 - GetPage origin, String parentPath, List<GetMiddleware> middlewares) {  
217 - return origin.copy( 238 + GetPage origin,
  239 + String parentPath,
  240 + List<GetMiddleware> middlewares,
  241 + List<BindingsInterface> bindings,
  242 + List<Bind> binds,
  243 + ) {
  244 + return origin.copyWith(
218 middlewares: middlewares, 245 middlewares: middlewares,
219 - name: (parentPath + origin.name).replaceAll(r'//', '/'), 246 + name: origin.inheritParentPath
  247 + ? (parentPath + origin.name).replaceAll(r'//', '/')
  248 + : origin.name,
  249 + bindings: bindings,
  250 + binds: binds,
220 // key: 251 // key:
221 ); 252 );
222 } 253 }
@@ -130,8 +130,8 @@ class MiddlewareRunner { @@ -130,8 +130,8 @@ class MiddlewareRunner {
130 final List<GetMiddleware>? _middlewares; 130 final List<GetMiddleware>? _middlewares;
131 131
132 List<GetMiddleware> _getMiddlewares() { 132 List<GetMiddleware> _getMiddlewares() {
133 - final _m = _middlewares ?? <GetMiddleware>[];  
134 - return _m 133 + final newMiddleware = _middlewares ?? <GetMiddleware>[];
  134 + return List.of(newMiddleware)
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 );
@@ -198,34 +198,33 @@ class PageRedirect { @@ -198,34 +198,33 @@ class PageRedirect {
198 GetPageRoute<T> getPageToRoute<T>( 198 GetPageRoute<T> getPageToRoute<T>(
199 GetPage rou, GetPage? unk, BuildContext context) { 199 GetPage rou, GetPage? unk, BuildContext context) {
200 while (needRecheck(context)) {} 200 while (needRecheck(context)) {}
201 - final _r = (isUnknown ? unk : rou)!; 201 + final r = (isUnknown ? unk : rou)!;
202 202
203 return GetPageRoute<T>( 203 return GetPageRoute<T>(
204 - page: _r.page,  
205 - parameter: _r.parameters,  
206 - alignment: _r.alignment,  
207 - title: _r.title,  
208 - maintainState: _r.maintainState,  
209 - routeName: _r.name,  
210 - settings: _r,  
211 - curve: _r.curve,  
212 - showCupertinoParallax: _r.showCupertinoParallax,  
213 - gestureWidth: _r.gestureWidth,  
214 - opaque: _r.opaque,  
215 - customTransition: _r.customTransition,  
216 - bindings: _r.bindings,  
217 - binding: _r.binding,  
218 - binds: _r.binds,  
219 - transitionDuration:  
220 - _r.transitionDuration ?? Get.defaultTransitionDuration, 204 + page: r.page,
  205 + parameter: r.parameters,
  206 + alignment: r.alignment,
  207 + title: r.title,
  208 + maintainState: r.maintainState,
  209 + routeName: r.name,
  210 + settings: r,
  211 + curve: r.curve,
  212 + showCupertinoParallax: r.showCupertinoParallax,
  213 + gestureWidth: r.gestureWidth,
  214 + opaque: r.opaque,
  215 + customTransition: r.customTransition,
  216 + bindings: r.bindings,
  217 + binding: r.binding,
  218 + binds: r.binds,
  219 + transitionDuration: r.transitionDuration ?? Get.defaultTransitionDuration,
221 reverseTransitionDuration: 220 reverseTransitionDuration:
222 - _r.reverseTransitionDuration ?? Get.defaultTransitionDuration, 221 + r.reverseTransitionDuration ?? Get.defaultTransitionDuration,
223 // performIncomeAnimation: _r.performIncomeAnimation, 222 // performIncomeAnimation: _r.performIncomeAnimation,
224 // performOutGoingAnimation: _r.performOutGoingAnimation, 223 // performOutGoingAnimation: _r.performOutGoingAnimation,
225 - transition: _r.transition,  
226 - popGesture: _r.popGesture,  
227 - fullscreenDialog: _r.fullscreenDialog,  
228 - middlewares: _r.middlewares, 224 + transition: r.transition,
  225 + popGesture: r.popGesture,
  226 + fullscreenDialog: r.fullscreenDialog,
  227 + middlewares: r.middlewares,
229 ); 228 );
230 } 229 }
231 230
@@ -248,7 +247,7 @@ class PageRedirect { @@ -248,7 +247,7 @@ class PageRedirect {
248 addPageParameter(route!); 247 addPageParameter(route!);
249 248
250 // No middlewares found return match. 249 // No middlewares found return match.
251 - if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) { 250 + if (match.route!.middlewares.isEmpty) {
252 return false; 251 return false;
253 } 252 }
254 final newSettings = runner.runRedirect(settings!.name); 253 final newSettings = runner.runRedirect(settings!.name);
@@ -4,14 +4,14 @@ import '../router_report.dart'; @@ -4,14 +4,14 @@ import '../router_report.dart';
4 import 'default_route.dart'; 4 import 'default_route.dart';
5 5
6 class RouteReport extends StatefulWidget { 6 class RouteReport extends StatefulWidget {
7 - RouteReport({Key? key, required this.builder}) : super(key: key); 7 + const RouteReport({Key? key, required this.builder}) : super(key: key);
8 final WidgetBuilder builder; 8 final WidgetBuilder builder;
9 9
10 @override 10 @override
11 - _RouteReportState createState() => _RouteReportState(); 11 + RouteReportState createState() => RouteReportState();
12 } 12 }
13 13
14 -class _RouteReportState extends State<RouteReport> with RouteReportMixin { 14 +class RouteReportState extends State<RouteReport> with RouteReportMixin {
15 @override 15 @override
16 void initState() { 16 void initState() {
17 RouterReportManager.instance.reportCurrentRoute(this); 17 RouterReportManager.instance.reportCurrentRoute(this);
@@ -9,12 +9,13 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> @@ -9,12 +9,13 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
9 9
10 //keys 10 //keys
11 RouterOutlet.builder({ 11 RouterOutlet.builder({
  12 + super.key,
12 TDelegate? delegate, 13 TDelegate? delegate,
13 required this.builder, 14 required this.builder,
14 - }) : routerDelegate = delegate ?? Get.delegate<TDelegate, T>()!,  
15 - super(); 15 + }) : routerDelegate = delegate ?? Get.delegate<TDelegate, T>()!;
16 16
17 RouterOutlet({ 17 RouterOutlet({
  18 + Key? key,
18 TDelegate? delegate, 19 TDelegate? delegate,
19 required Iterable<GetPage> Function(T currentNavStack) pickPages, 20 required Iterable<GetPage> Function(T currentNavStack) pickPages,
20 required Widget Function( 21 required Widget Function(
@@ -24,6 +25,7 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> @@ -24,6 +25,7 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
24 ) 25 )
25 pageBuilder, 26 pageBuilder,
26 }) : this.builder( 27 }) : this.builder(
  28 + key: key,
27 builder: (context) { 29 builder: (context) {
28 final currentConfig = context.delegate.currentConfiguration as T?; 30 final currentConfig = context.delegate.currentConfiguration as T?;
29 final rDelegate = context.delegate as TDelegate; 31 final rDelegate = context.delegate as TDelegate;
@@ -37,11 +39,11 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> @@ -37,11 +39,11 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
37 delegate: delegate, 39 delegate: delegate,
38 ); 40 );
39 @override 41 @override
40 - _RouterOutletState<TDelegate, T> createState() =>  
41 - _RouterOutletState<TDelegate, T>(); 42 + RouterOutletState<TDelegate, T> createState() =>
  43 + RouterOutletState<TDelegate, T>();
42 } 44 }
43 45
44 -class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> 46 +class RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
45 extends State<RouterOutlet<TDelegate, T>> { 47 extends State<RouterOutlet<TDelegate, T>> {
46 RouterDelegate? delegate; 48 RouterDelegate? delegate;
47 late ChildBackButtonDispatcher _backButtonDispatcher; 49 late ChildBackButtonDispatcher _backButtonDispatcher;
@@ -80,7 +82,7 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> @@ -80,7 +82,7 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
80 } 82 }
81 } 83 }
82 84
83 -// class _RouterOutletState<TDelegate extends RouterDelegate<T>, 85 +// class RouterOutletState<TDelegate extends RouterDelegate<T>,
84 //T extends Object> 86 //T extends Object>
85 // extends State<RouterOutlet<TDelegate, T>> { 87 // extends State<RouterOutlet<TDelegate, T>> {
86 // TDelegate get delegate => context.delegate as TDelegate; 88 // TDelegate get delegate => context.delegate as TDelegate;
@@ -152,11 +154,11 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> { @@ -152,11 +154,11 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
152 delegate: delegate, 154 delegate: delegate,
153 ); 155 );
154 GetRouterOutlet.pickPages({ 156 GetRouterOutlet.pickPages({
  157 + super.key,
155 Widget Function(GetDelegate delegate)? emptyWidget, 158 Widget Function(GetDelegate delegate)? emptyWidget,
156 GetPage Function(GetDelegate delegate)? emptyPage, 159 GetPage Function(GetDelegate delegate)? emptyPage,
157 required Iterable<GetPage> Function(RouteDecoder currentNavStack) pickPages, 160 required Iterable<GetPage> Function(RouteDecoder currentNavStack) pickPages,
158 bool Function(Route<dynamic>, dynamic)? onPopPage, 161 bool Function(Route<dynamic>, dynamic)? onPopPage,
159 - GlobalKey<NavigatorState>? key,  
160 GetDelegate? delegate, 162 GetDelegate? delegate,
161 }) : super( 163 }) : super(
162 pageBuilder: (context, rDelegate, pages) { 164 pageBuilder: (context, rDelegate, pages) {
@@ -179,13 +181,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> { @@ -179,13 +181,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
179 key: key, 181 key: key,
180 ); 182 );
181 } 183 }
182 - return (emptyWidget?.call(rDelegate) ?? SizedBox.shrink()); 184 + return (emptyWidget?.call(rDelegate) ?? const SizedBox.shrink());
183 }, 185 },
184 pickPages: pickPages, 186 pickPages: pickPages,
185 delegate: delegate ?? Get.rootController.rootDelegate, 187 delegate: delegate ?? Get.rootController.rootDelegate,
186 ); 188 );
187 189
188 GetRouterOutlet.builder({ 190 GetRouterOutlet.builder({
  191 + super.key,
189 required Widget Function( 192 required Widget Function(
190 BuildContext context, 193 BuildContext context,
191 ) 194 )
@@ -7,88 +7,10 @@ import '../../../get_core/get_core.dart'; @@ -7,88 +7,10 @@ import '../../../get_core/get_core.dart';
7 import '../../get_navigation.dart'; 7 import '../../get_navigation.dart';
8 8
9 typedef OnTap = void Function(GetSnackBar snack); 9 typedef OnTap = void Function(GetSnackBar snack);
  10 +typedef OnHover = void Function(GetSnackBar snack, SnackHoverState snackHoverState);
10 11
11 typedef SnackbarStatusCallback = void Function(SnackbarStatus? status); 12 typedef SnackbarStatusCallback = void Function(SnackbarStatus? status);
12 13
13 -@Deprecated('use GetSnackBar')  
14 -class GetBar extends GetSnackBar {  
15 - GetBar({  
16 - Key? key,  
17 - String? title,  
18 - String? message,  
19 - Widget? titleText,  
20 - Widget? messageText,  
21 - Widget? icon,  
22 - bool shouldIconPulse = true,  
23 - double? maxWidth,  
24 - EdgeInsets margin = const EdgeInsets.all(0.0),  
25 - EdgeInsets padding = const EdgeInsets.all(16),  
26 - double borderRadius = 0.0,  
27 - Color? borderColor,  
28 - double borderWidth = 1.0,  
29 - Color backgroundColor = const Color(0xFF303030),  
30 - Color? leftBarIndicatorColor,  
31 - List<BoxShadow>? boxShadows,  
32 - Gradient? backgroundGradient,  
33 - Widget? mainButton,  
34 - OnTap? onTap,  
35 - Duration? duration,  
36 - bool isDismissible = true,  
37 - DismissDirection? dismissDirection,  
38 - bool showProgressIndicator = false,  
39 - AnimationController? progressIndicatorController,  
40 - Color? progressIndicatorBackgroundColor,  
41 - Animation<Color>? progressIndicatorValueColor,  
42 - SnackPosition snackPosition = SnackPosition.bottom,  
43 - SnackStyle snackStyle = SnackStyle.floating,  
44 - Curve forwardAnimationCurve = Curves.easeOutCirc,  
45 - Curve reverseAnimationCurve = Curves.easeOutCirc,  
46 - Duration animationDuration = const Duration(seconds: 1),  
47 - double barBlur = 0.0,  
48 - double overlayBlur = 0.0,  
49 - Color overlayColor = Colors.transparent,  
50 - Form? userInputForm,  
51 - SnackbarStatusCallback? snackbarStatus,  
52 - }) : super(  
53 - key: key,  
54 - title: title,  
55 - message: message,  
56 - titleText: titleText,  
57 - messageText: messageText,  
58 - icon: icon,  
59 - shouldIconPulse: shouldIconPulse,  
60 - maxWidth: maxWidth,  
61 - margin: margin,  
62 - padding: padding,  
63 - borderRadius: borderRadius,  
64 - borderColor: borderColor,  
65 - borderWidth: borderWidth,  
66 - backgroundColor: backgroundColor,  
67 - leftBarIndicatorColor: leftBarIndicatorColor,  
68 - boxShadows: boxShadows,  
69 - backgroundGradient: backgroundGradient,  
70 - mainButton: mainButton,  
71 - onTap: onTap,  
72 - duration: duration,  
73 - isDismissible: isDismissible,  
74 - dismissDirection: dismissDirection,  
75 - showProgressIndicator: showProgressIndicator,  
76 - progressIndicatorController: progressIndicatorController,  
77 - progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,  
78 - progressIndicatorValueColor: progressIndicatorValueColor,  
79 - snackPosition: snackPosition,  
80 - snackStyle: snackStyle,  
81 - forwardAnimationCurve: forwardAnimationCurve,  
82 - reverseAnimationCurve: reverseAnimationCurve,  
83 - animationDuration: animationDuration,  
84 - barBlur: barBlur,  
85 - overlayBlur: overlayBlur,  
86 - overlayColor: overlayColor,  
87 - userInputForm: userInputForm,  
88 - snackbarStatus: snackbarStatus,  
89 - );  
90 -}  
91 -  
92 class GetSnackBar extends StatefulWidget { 14 class GetSnackBar extends StatefulWidget {
93 /// A callback for you to listen to the different Snack status 15 /// A callback for you to listen to the different Snack status
94 final SnackbarStatusCallback? snackbarStatus; 16 final SnackbarStatusCallback? snackbarStatus;
@@ -150,6 +72,9 @@ class GetSnackBar extends StatefulWidget { @@ -150,6 +72,9 @@ class GetSnackBar extends StatefulWidget {
150 /// An alternative to [mainButton] 72 /// An alternative to [mainButton]
151 final OnTap? onTap; 73 final OnTap? onTap;
152 74
  75 + /// A callback that registers the user's hover anywhere over the Snackbar.
  76 + final OnHover? onHover;
  77 +
153 /// How long until Snack will hide itself (be dismissed). 78 /// How long until Snack will hide itself (be dismissed).
154 /// To make it indefinite, leave it null. 79 /// To make it indefinite, leave it null.
155 final Duration? duration; 80 final Duration? duration;
@@ -259,6 +184,7 @@ class GetSnackBar extends StatefulWidget { @@ -259,6 +184,7 @@ class GetSnackBar extends StatefulWidget {
259 this.backgroundGradient, 184 this.backgroundGradient,
260 this.mainButton, 185 this.mainButton,
261 this.onTap, 186 this.onTap,
  187 + this.onHover,
262 this.duration, 188 this.duration,
263 this.isDismissible = true, 189 this.isDismissible = true,
264 this.dismissDirection, 190 this.dismissDirection,
@@ -293,11 +219,11 @@ class GetSnackBarState extends State<GetSnackBar> @@ -293,11 +219,11 @@ class GetSnackBarState extends State<GetSnackBar>
293 AnimationController? _fadeController; 219 AnimationController? _fadeController;
294 late Animation<double> _fadeAnimation; 220 late Animation<double> _fadeAnimation;
295 221
296 - final Widget _emptyWidget = SizedBox(width: 0.0, height: 0.0); 222 + final Widget _emptyWidget = const SizedBox(width: 0.0, height: 0.0);
297 final double _initialOpacity = 1.0; 223 final double _initialOpacity = 1.0;
298 final double _finalOpacity = 0.4; 224 final double _finalOpacity = 0.4;
299 225
300 - final Duration _pulseAnimationDuration = Duration(seconds: 1); 226 + final Duration _pulseAnimationDuration = const Duration(seconds: 1);
301 227
302 late bool _isTitlePresent; 228 late bool _isTitlePresent;
303 late double _messageTopMargin; 229 late double _messageTopMargin;
@@ -513,9 +439,9 @@ You need to either use message[String], or messageText[Widget] or define a userI @@ -513,9 +439,9 @@ You need to either use message[String], or messageText[Widget] or define a userI
513 padding: const EdgeInsets.only( 439 padding: const EdgeInsets.only(
514 left: 8.0, right: 8.0, bottom: 8.0, top: 16.0), 440 left: 8.0, right: 8.0, bottom: 8.0, top: 16.0),
515 child: FocusScope( 441 child: FocusScope(
516 - child: widget.userInputForm!,  
517 node: _focusNode, 442 node: _focusNode,
518 autofocus: true, 443 autofocus: true,
  444 + child: widget.userInputForm!,
519 ), 445 ),
520 ), 446 ),
521 ); 447 );
@@ -581,7 +507,7 @@ You need to either use message[String], or messageText[Widget] or define a userI @@ -581,7 +507,7 @@ You need to either use message[String], or messageText[Widget] or define a userI
581 child: widget.titleText ?? 507 child: widget.titleText ??
582 Text( 508 Text(
583 widget.title ?? "", 509 widget.title ?? "",
584 - style: TextStyle( 510 + style: const TextStyle(
585 fontSize: 16.0, 511 fontSize: 16.0,
586 color: Colors.white, 512 color: Colors.white,
587 fontWeight: FontWeight.bold, 513 fontWeight: FontWeight.bold,
@@ -600,8 +526,8 @@ You need to either use message[String], or messageText[Widget] or define a userI @@ -600,8 +526,8 @@ You need to either use message[String], or messageText[Widget] or define a userI
600 child: widget.messageText ?? 526 child: widget.messageText ??
601 Text( 527 Text(
602 widget.message ?? "", 528 widget.message ?? "",
603 - style:  
604 - TextStyle(fontSize: 14.0, color: Colors.white), 529 + style: const TextStyle(
  530 + fontSize: 14.0, color: Colors.white),
605 ), 531 ),
606 ), 532 ),
607 ], 533 ],
@@ -657,3 +583,6 @@ enum SnackPosition { top, bottom } @@ -657,3 +583,6 @@ enum SnackPosition { top, bottom }
657 583
658 /// Indicates if snack will be attached to the edge of the screen or not 584 /// Indicates if snack will be attached to the edge of the screen or not
659 enum SnackStyle { floating, grounded } 585 enum SnackStyle { floating, grounded }
  586 +
  587 +/// Indicates if the mouse entered or exited
  588 +enum SnackHoverState { entered, exited }
@@ -220,15 +220,15 @@ class SnackbarController { @@ -220,15 +220,15 @@ class SnackbarController {
220 ], 220 ],
221 OverlayEntry( 221 OverlayEntry(
222 builder: (context) => Semantics( 222 builder: (context) => Semantics(
  223 + focused: false,
  224 + container: true,
  225 + explicitChildNodes: true,
223 child: AlignTransition( 226 child: AlignTransition(
224 alignment: _animation, 227 alignment: _animation,
225 child: snackbar.isDismissible 228 child: snackbar.isDismissible
226 ? _getDismissibleSnack(child) 229 ? _getDismissibleSnack(child)
227 : _getSnackbarContainer(child), 230 : _getSnackbarContainer(child),
228 ), 231 ),
229 - focused: false,  
230 - container: true,  
231 - explicitChildNodes: true,  
232 ), 232 ),
233 maintainState: false, 233 maintainState: false,
234 opaque: false, 234 opaque: false,
@@ -238,11 +238,15 @@ class SnackbarController { @@ -238,11 +238,15 @@ class SnackbarController {
238 238
239 Widget _getBodyWidget() { 239 Widget _getBodyWidget() {
240 return Builder(builder: (_) { 240 return Builder(builder: (_) {
241 - return GestureDetector(  
242 - child: snackbar,  
243 - onTap: snackbar.onTap != null  
244 - ? () => snackbar.onTap?.call(snackbar)  
245 - : null, 241 + return MouseRegion(
  242 + onEnter: (_) => snackbar.onHover?.call(snackbar, SnackHoverState.entered),
  243 + onExit: (_) => snackbar.onHover?.call(snackbar, SnackHoverState.exited),
  244 + child: GestureDetector(
  245 + child: snackbar,
  246 + onTap: snackbar.onTap != null
  247 + ? () => snackbar.onTap?.call(snackbar)
  248 + : null,
  249 + ),
246 ); 250 );
247 }); 251 });
248 } 252 }
@@ -226,11 +226,11 @@ Worker debounce<T>( @@ -226,11 +226,11 @@ Worker debounce<T>(
226 void Function()? onDone, 226 void Function()? onDone,
227 bool? cancelOnError, 227 bool? cancelOnError,
228 }) { 228 }) {
229 - final _debouncer = 229 + final newDebouncer =
230 Debouncer(delay: time ?? const Duration(milliseconds: 800)); 230 Debouncer(delay: time ?? const Duration(milliseconds: 800));
231 StreamSubscription sub = listener.listen( 231 StreamSubscription sub = listener.listen(
232 (event) { 232 (event) {
233 - _debouncer(() { 233 + newDebouncer(() {
234 callback(event); 234 callback(event);
235 }); 235 });
236 }, 236 },
@@ -22,6 +22,7 @@ class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { @@ -22,6 +22,7 @@ class GetX<T extends GetLifeCycleMixin> extends StatefulWidget {
22 final String? tag; 22 final String? tag;
23 23
24 const GetX({ 24 const GetX({
  25 + super.key,
25 this.tag, 26 this.tag,
26 required this.builder, 27 required this.builder,
27 this.global = true, 28 this.global = true,
@@ -32,7 +32,7 @@ mixin StateMixin<T> on ListNotifier { @@ -32,7 +32,7 @@ mixin StateMixin<T> on ListNotifier {
32 void _fillInitialStatus() { 32 void _fillInitialStatus() {
33 _status = (_value == null || _value!._isEmpty()) 33 _status = (_value == null || _value!._isEmpty())
34 ? GetStatus<T>.loading() 34 ? GetStatus<T>.loading()
35 - : GetStatus<T>.success(_value!); 35 + : GetStatus<T>.success(_value as T);
36 } 36 }
37 37
38 GetStatus<T> get status { 38 GetStatus<T> get status {
@@ -71,7 +71,7 @@ mixin StateMixin<T> on ListNotifier { @@ -71,7 +71,7 @@ mixin StateMixin<T> on ListNotifier {
71 } 71 }
72 } 72 }
73 73
74 - void futurize(Future<T> Function() body, 74 + void futurize(Future<T> Function() body,
75 {T? initialData, String? errorMessage, bool useEmpty = true}) { 75 {T? initialData, String? errorMessage, bool useEmpty = true}) {
76 final compute = body; 76 final compute = body;
77 _value ??= initialData; 77 _value ??= initialData;
@@ -231,12 +231,12 @@ extension StateExt<T> on StateMixin<T> { @@ -231,12 +231,12 @@ extension StateExt<T> on StateMixin<T> {
231 : Center(child: Text('A error occurred: ${status.errorMessage}')); 231 : Center(child: Text('A error occurred: ${status.errorMessage}'));
232 } else if (status.isEmpty) { 232 } else if (status.isEmpty) {
233 return onEmpty ?? 233 return onEmpty ??
234 - SizedBox.shrink(); // Also can be widget(null); but is risky 234 + const SizedBox.shrink(); // Also can be widget(null); but is risky
235 } else if (status.isSuccess) { 235 } else if (status.isSuccess) {
236 return widget(value); 236 return widget(value);
237 } else if (status.isCustom) { 237 } else if (status.isCustom) {
238 return onCustom?.call(_) ?? 238 return onCustom?.call(_) ??
239 - SizedBox.shrink(); // Also can be widget(null); but is risky 239 + const SizedBox.shrink(); // Also can be widget(null); but is risky
240 } 240 }
241 return widget(value); 241 return widget(value);
242 }); 242 });
@@ -24,7 +24,7 @@ abstract class ObxWidget extends ObxStatelessWidget { @@ -24,7 +24,7 @@ abstract class ObxWidget extends ObxStatelessWidget {
24 class Obx extends ObxWidget { 24 class Obx extends ObxWidget {
25 final WidgetCallback builder; 25 final WidgetCallback builder;
26 26
27 - const Obx(this.builder); 27 + const Obx(this.builder, {super.key});
28 28
29 @override 29 @override
30 Widget build(BuildContext context) { 30 Widget build(BuildContext context) {