jonataslaw

Update to version 3.0

  1 +## [3.0.1]
  2 +- Breaking changes on Rx api and GetController and RxController were merged, and now you only have the 'GetxController'
  3 +- Refactor routing system. Now you can add custom transitions and more
  4 +- Improved the use of dynamic routes, you can now define two different pages according to your arguments.
  5 +- Added GetView widget
  6 +- Added internacionalization
  7 +- Added validations
  8 +- Added Get queqe
  9 +- Added GetStorage (with separated package)
  10 +- Minor bug fixes.
  11 +
  12 +
1 ## [2.14.0] 13 ## [2.14.0]
2 - Added getPages API. 14 - Added getPages API.
3 - Deprecated namedPages 15 - Deprecated namedPages
@@ -12,7 +24,7 @@ @@ -12,7 +24,7 @@
12 24
13 ## [2.13.0] 25 ## [2.13.0]
14 - Update docs 26 - Update docs
15 -- Fix Bindings list on GetRouteBase 27 +- Fix Bindings list on GetPageRoute
16 28
17 ## [2.12.5] 29 ## [2.12.5]
18 - Update readme 30 - Update readme
@@ -64,7 +76,7 @@ Get.lazyPut () will not receive this resource. Initially he had it, but we saw i @@ -64,7 +76,7 @@ Get.lazyPut () will not receive this resource. Initially he had it, but we saw i
64 ## [2.10.0] 76 ## [2.10.0]
65 - Added SmartManagement, your application's memory is managed intelligently like never before! 77 - Added SmartManagement, your application's memory is managed intelligently like never before!
66 - Added Obx, a widget that knows when to rebuild a child, without needing any type. 78 - Added Obx, a widget that knows when to rebuild a child, without needing any type.
67 -- Added MIxinBuilder - If you need to use GetBuilder in conjunction with GetX, use GetController with this widget, and the changes will occur either using update (this) or changing some reactive variable. Use only if necessary, for better RAM consumption, prefer widgets in that order: 79 +- Added MIxinBuilder - If you need to use GetBuilder in conjunction with GetX, use GetxController with this widget, and the changes will occur either using update (this) or changing some reactive variable. Use only if necessary, for better RAM consumption, prefer widgets in that order:
68 Obx => GetX => GetBuilder => MixinBuilder. 80 Obx => GetX => GetBuilder => MixinBuilder.
69 Obx is the lightest of all, and MixinBuilder is a mix of the other 3, whenever possible, use the specific widget. 81 Obx is the lightest of all, and MixinBuilder is a mix of the other 3, whenever possible, use the specific widget.
70 - Refactor: refactor StateManager of Get. 82 - Refactor: refactor StateManager of Get.
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 </a> 10 </a>
11 <a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a> 11 <a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
12 <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> 12 <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
13 -[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-) 13 +[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)
14 <!-- ALL-CONTRIBUTORS-BADGE:END --> 14 <!-- ALL-CONTRIBUTORS-BADGE:END -->
15 15
16 16
@@ -33,7 +33,7 @@ Create your business logic class and place all variables, methods and controller @@ -33,7 +33,7 @@ Create your business logic class and place all variables, methods and controller
33 You can make any variable observable using a simple ".obs". 33 You can make any variable observable using a simple ".obs".
34 34
35 ```dart 35 ```dart
36 -class Controller extends RxController{ 36 +class Controller extends GetxController{
37 var count = 0.obs; 37 var count = 0.obs;
38 increment() => count.value++; 38 increment() => count.value++;
39 } 39 }
@@ -112,6 +112,7 @@ This is a simple project but it already makes clear how powerful Get is. As your @@ -112,6 +112,7 @@ This is a simple project but it already makes clear how powerful Get is. As your
112 - [Change Theme](#change-theme) 112 - [Change Theme](#change-theme)
113 - [Other Advanced APIs and Manual configurations](#other-advanced-apis-and-manual-configurations) 113 - [Other Advanced APIs and Manual configurations](#other-advanced-apis-and-manual-configurations)
114 - [Optional Global Settings](#optional-global-settings) 114 - [Optional Global Settings](#optional-global-settings)
  115 +- [Breaking changes from 2.0](#breaking-changes-from-2.0)
115 116
116 *Want to contribute to the project? We will be proud to highlight you as one of our collaborators. Here are some points where you can contribute and make Get (and Flutter) even better.* 117 *Want to contribute to the project? We will be proud to highlight you as one of our collaborators. Here are some points where you can contribute and make Get (and Flutter) even better.*
117 118
@@ -237,18 +238,12 @@ void main() { @@ -237,18 +238,12 @@ void main() {
237 GetMaterialApp( 238 GetMaterialApp(
238 initialRoute: '/', 239 initialRoute: '/',
239 getPages: [ 240 getPages: [
240 - GetPage(  
241 - name: '/',  
242 - page: () => MyHomePage(),  
243 - ),  
244 - GetPage(  
245 - name: '/second',  
246 - page: () => Second(),  
247 - ), 241 + GetPage(name: '/', page: () => MyHomePage()),
  242 + GetPage(name: '/second', page: () => Second()),
248 GetPage( 243 GetPage(
249 name: '/third', 244 name: '/third',
250 page: () => Third(), 245 page: () => Third(),
251 - transition: Transition.cupertino 246 + transition: Transition.zoom
252 ), 247 ),
253 ], 248 ],
254 ) 249 )
@@ -297,12 +292,13 @@ void main() { @@ -297,12 +292,13 @@ void main() {
297 page: () => MyHomePage(), 292 page: () => MyHomePage(),
298 ), 293 ),
299 GetPage( 294 GetPage(
300 - /// Important! :user is not a new route, it is just a parameter  
301 - /// specification. Do not use '/second/:user' and '/second'  
302 - /// if you need new route to user, use '/second/user/:user'  
303 - /// if '/second' is a route.  
304 - name: '/second/:user',  
305 - page: () => Second(), 295 + name: '/profile/',
  296 + page: () => MyProfile(),
  297 + ),
  298 + //You can define a different page for routes with arguments, and another without arguments, but for that you must use the slash '/' on the route that will not receive arguments as above.
  299 + GetPage(
  300 + name: '/profile/:user',
  301 + page: () => UserProfile(),
306 ), 302 ),
307 GetPage( 303 GetPage(
308 name: '/third', 304 name: '/third',
@@ -333,7 +329,7 @@ And now, all you need to do is use Get.toNamed() to navigate your named routes, @@ -333,7 +329,7 @@ And now, all you need to do is use Get.toNamed() to navigate your named routes,
333 If you want listen Get events to trigger actions, you can to use routingCallback to it 329 If you want listen Get events to trigger actions, you can to use routingCallback to it
334 ```dart 330 ```dart
335 GetMaterialApp( 331 GetMaterialApp(
336 - routingCallback: (route) { 332 + routingCallback: (routing) {
337 if(routing.current == '/second'){ 333 if(routing.current == '/second'){
338 openAds(); 334 openAds();
339 } 335 }
@@ -449,7 +445,8 @@ class Third extends StatelessWidget { @@ -449,7 +445,8 @@ class Third extends StatelessWidget {
449 445
450 ### SnackBars 446 ### SnackBars
451 447
452 -To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold, 448 +To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold
  449 +
453 ```dart 450 ```dart
454 final snackBar = SnackBar( 451 final snackBar = SnackBar(
455 content: Text('Hi!'), 452 content: Text('Hi!'),
@@ -584,7 +581,7 @@ Navigator( @@ -584,7 +581,7 @@ Navigator(
584 initialRoute: '/', 581 initialRoute: '/',
585 onGenerateRoute: (settings) { 582 onGenerateRoute: (settings) {
586 if (settings.name == '/') { 583 if (settings.name == '/') {
587 - return GetRouteBase( 584 + return GetPageRoute(
588 page: Scaffold( 585 page: Scaffold(
589 appBar: AppBar( 586 appBar: AppBar(
590 title: Text("Main"), 587 title: Text("Main"),
@@ -601,7 +598,7 @@ Navigator( @@ -601,7 +598,7 @@ Navigator(
601 ), 598 ),
602 ); 599 );
603 } else if (settings.name == '/second') { 600 } else if (settings.name == '/second') {
604 - return GetRouteBase( 601 + return GetPageRoute(
605 page: Center( 602 page: Center(
606 child: Scaffold( 603 child: Scaffold(
607 appBar: AppBar( 604 appBar: AppBar(
@@ -658,8 +655,8 @@ Get has a state manager that is extremely light and easy, which does not use Cha @@ -658,8 +655,8 @@ Get has a state manager that is extremely light and easy, which does not use Cha
658 ### Usage 655 ### Usage
659 656
660 ```dart 657 ```dart
661 -// Create controller class and extends GetController  
662 -class Controller extends GetController { 658 +// Create controller class and extends GetxController
  659 +class Controller extends GetxController {
663 int counter = 0; 660 int counter = 0;
664 void increment() { 661 void increment() {
665 counter++; 662 counter++;
@@ -700,7 +697,7 @@ class OtherClass extends StatelessWidget { @@ -700,7 +697,7 @@ class OtherClass extends StatelessWidget {
700 If you need to use your controller in many other places, and outside of GetBuilder, just create a get in your controller and have it easily. (or use `Get.find<Controller>()`) 697 If you need to use your controller in many other places, and outside of GetBuilder, just create a get in your controller and have it easily. (or use `Get.find<Controller>()`)
701 698
702 ```dart 699 ```dart
703 -class Controller extends GetController { 700 +class Controller extends GetxController {
704 701
705 /// You do not need that. I recommend using it just for ease of syntax. 702 /// You do not need that. I recommend using it just for ease of syntax.
706 /// with static method: Controller.to.counter(); 703 /// with static method: Controller.to.counter();
@@ -768,10 +765,10 @@ So to simplify this: @@ -768,10 +765,10 @@ So to simplify this:
768 You don't need to call methods in initState and send them by parameter to your controller, nor use your controller constructor for that, you have the onInit() method that is called at the right time for you to start your services. 765 You don't need to call methods in initState and send them by parameter to your controller, nor use your controller constructor for that, you have the onInit() method that is called at the right time for you to start your services.
769 You do not need to call the device, you have the onClose() method that will be called at the exact moment when your controller is no longer needed and will be removed from memory. That way, leave views for widgets only, refrain from any kind of business logic from it. 766 You do not need to call the device, you have the onClose() method that will be called at the exact moment when your controller is no longer needed and will be removed from memory. That way, leave views for widgets only, refrain from any kind of business logic from it.
770 767
771 -Do not call a dispose method inside GetController, it will not do anything, remember that the controller is not a Widget, you should not "dispose" it, and it will be automatically and intelligently removed from memory by Get. If you used any stream on it and want to close it, just insert it into the close method. Example: 768 +Do not call a dispose method inside GetxController, it will not do anything, remember that the controller is not a Widget, you should not "dispose" it, and it will be automatically and intelligently removed from memory by Get. If you used any stream on it and want to close it, just insert it into the close method. Example:
772 769
773 ```dart 770 ```dart
774 -class Controller extends GetController { 771 +class Controller extends GetxController {
775 StreamController<User> user = StreamController<User>(); 772 StreamController<User> user = StreamController<User>();
776 StreamController<String> name = StreamController<String>(); 773 StreamController<String> name = StreamController<String>();
777 774
@@ -804,7 +801,7 @@ GetBuilder<Controller>( @@ -804,7 +801,7 @@ GetBuilder<Controller>(
804 You may also need an instance of your controller outside of your GetBuilder, and you can use these approaches to achieve this: 801 You may also need an instance of your controller outside of your GetBuilder, and you can use these approaches to achieve this:
805 802
806 ```dart 803 ```dart
807 -class Controller extends GetController { 804 +class Controller extends GetxController {
808 static Controller get to => Get.find(); 805 static Controller get to => Get.find();
809 [...] 806 [...]
810 } 807 }
@@ -818,7 +815,7 @@ GetBuilder<Controller>( @@ -818,7 +815,7 @@ GetBuilder<Controller>(
818 ``` 815 ```
819 or 816 or
820 ```dart 817 ```dart
821 -class Controller extends GetController { 818 +class Controller extends GetxController {
822 // static Controller get to => Get.find(); // with no static get 819 // static Controller get to => Get.find(); // with no static get
823 [...] 820 [...]
824 } 821 }
@@ -870,6 +867,34 @@ GetX does this automatically and only reconstructs the widget that uses the exac @@ -870,6 +867,34 @@ GetX does this automatically and only reconstructs the widget that uses the exac
870 867
871 ## Reactive State Manager 868 ## Reactive State Manager
872 869
  870 +Reactive programming can alienate many people because it is said to be complicated. Getx turns reactive programming into something so simple, that it can be used and learned by those who started at that very moment in Flutter. No, you will not need to create StreamControllers. You also won't need to create a StreamBuilder for each variable. You will not need to create a class for each state. You will not need to create a get for an initial value. Reactive programming with Get is as easy as using setState (or even easier!).
  871 +
  872 +Let's imagine that you have a name variable and want that every time you change it, all widgets that use it are automatically changed.
  873 +
  874 +This is your count variable:
  875 +```dart
  876 +var name = 'Jonatas Borges';
  877 +```
  878 +To make it observable, you just need to add ".obs" to the end of it:
  879 +```dart
  880 +var name = 'Jonatas Borges'.obs;
  881 +```
  882 +
  883 +This borders on absurdity when it comes to practicality. What did we do under the hood? We created a stream of Strings, assigned the initial value "Jonatas Borges", we warn all widgets that use "Jonatas Borges" that they now belong to this variable, and when it is changed, they will be changed too. This is the magic of Get, that only dart allows us to do this.
  884 +
  885 +Okay, but as we know, a widget can only be changed if it is inside a function, because static classes do not have the power to "auto-change". You will need to create a StreamBuilder, subscribe to listen to this variable, and create a "cascade" of StreamBuilder if you want to change several variables in the same scope, right?
  886 +No, you don't need a StreamBuilder, but you are right about static classes.
  887 +
  888 +Well, in the view we usually have a lot of boilerplate when we want to change a specific widget. With Get you can also forget about this Boilerplate. StreamBuilder? initialValue? builder?
  889 +No, you just need to play this variable inside an Obx widget.
  890 +```dart
  891 +Obx (() => Text (controller.name));
  892 +```
  893 +
  894 +What do you need to memorize? "Obx(() =>" You are just passing that widget through an arrow-function into an Obx. Obx is smart, and will only be changed if the value of name is changed. If name is "John" and you change it to "John", it will not have any changes on the screen, and Obx will simply ignore this change, and will not rebuild the widget, to save resources. Isn't that amazing?
  895 +
  896 +What if I have 5 observable variables within an Obx? It will update when any of them are changed. And if I have 30 variables in a class, when I update one, will it update all variables that are in that class? No, just the specific widget that uses that variable. And if I machine-gun my observable variable 1 billion times with the same value, will I have freeze on the screen for unnecessary reconstructions? No, GetX only updates the screen when the variable changes on the screen, if the screen remains the same, it will not reconstruct anything.
  897 +
873 ### Advantages 898 ### Advantages
874 GetBuilder is aimed precisely at multiple state control. Imagine that you added 30 products to a cart, you click delete one, at the same time that the list is updated, the price is updated and the badge in the shopping cart is updated to a smaller number. This type of approach makes GetBuilder killer, because it groups states and changes them all at once without any "computational logic" for that. GetBuilder was created with this type of situation in mind, since for ephemeral change of state, you can use setState and you would not need a state manager for this. However, there are situations where you want only the widget where a certain variable has been changed to be rebuilt, and this is what GetX does with a mastery never seen before. 899 GetBuilder is aimed precisely at multiple state control. Imagine that you added 30 products to a cart, you click delete one, at the same time that the list is updated, the price is updated and the badge in the shopping cart is updated to a smaller number. This type of approach makes GetBuilder killer, because it groups states and changes them all at once without any "computational logic" for that. GetBuilder was created with this type of situation in mind, since for ephemeral change of state, you can use setState and you would not need a state manager for this. However, there are situations where you want only the widget where a certain variable has been changed to be rebuilt, and this is what GetX does with a mastery never seen before.
875 900
@@ -887,6 +912,29 @@ The state only changes if the values ​​change. That's the main difference be @@ -887,6 +912,29 @@ The state only changes if the values ​​change. That's the main difference be
887 912
888 ### Usage 913 ### Usage
889 914
  915 +You have 3 ways to turn a variable into an observable.
  916 +The first is using Rx{Type}.
  917 +
  918 +```dart
  919 +var count = RxString();
  920 +```
  921 +The second is to use Rx and type it with `Rx<Type>`
  922 +```dart
  923 +var count = Rx<String>();
  924 +```
  925 +
  926 +The third, more practical, easy, and incredible approach, is just to add an .obs to your variable.
  927 +
  928 +```dart
  929 +var count = 0.obs;
  930 +
  931 +// or Rxint count = 0.obs;
  932 +// or Rx<int> count = 0.obs;
  933 +```
  934 +
  935 + As we know, Dart is now heading towards null safety. With that it is a good idea, from now on, you start to use your variables always with an initial value. Transforming a variable into an observable with an initial value with Get is the simplest and most practical approach that currently exists in Flutter. You will literally add a ".obs" to the end of your variable, and that’s it, you’ve made it observable, and its value will be the initial value, this is fantastic!
  936 +
  937 +You can add variables, and if you want to type your widget to get your controller inside, you just need to use GetX widget instead of Obx
890 ```dart 938 ```dart
891 final count1 = 0.obs; 939 final count1 = 0.obs;
892 final count2 = 0.obs; 940 final count2 = 0.obs;
@@ -895,9 +943,9 @@ int get sum => count1.value + count2.value; @@ -895,9 +943,9 @@ int get sum => count1.value + count2.value;
895 943
896 ```dart 944 ```dart
897 GetX<Controller>( 945 GetX<Controller>(
898 - builder: (_) { 946 + builder: (value) {
899 print("count 1 rebuild"); 947 print("count 1 rebuild");
900 - return Text('${_.count1.value}'); 948 + return Text('${value.count1.value}');
901 }, 949 },
902 ), 950 ),
903 GetX<Controller>( 951 GetX<Controller>(
@@ -959,7 +1007,7 @@ Without decorations, without a code generator, without complications, GetX will @@ -959,7 +1007,7 @@ Without decorations, without a code generator, without complications, GetX will
959 Do you know Flutter's counter app? Your Controller class might look like this: 1007 Do you know Flutter's counter app? Your Controller class might look like this:
960 1008
961 ```dart 1009 ```dart
962 -class CountCtl extends RxController { 1010 +class CountCtl extends GetxController {
963 final count = 0.obs; 1011 final count = 0.obs;
964 } 1012 }
965 ``` 1013 ```
@@ -1074,9 +1122,7 @@ interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1)); @@ -1074,9 +1122,7 @@ interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
1074 ## Mixing the two state managers 1122 ## Mixing the two state managers
1075 Some people opened a feature request, as they wanted to use only one type of reactive variable, and the other mechanics, and needed to insert an Obx into a GetBuilder for this. Thinking about it MixinBuilder was created. It allows both reactive changes by changing ".obs" variables, and mechanical updates via update(). However, of the 4 widgets he is the one that consumes the most resources, since in addition to having a Subscription to receive change events from his children, he subscribes to the update method of his controller. 1123 Some people opened a feature request, as they wanted to use only one type of reactive variable, and the other mechanics, and needed to insert an Obx into a GetBuilder for this. Thinking about it MixinBuilder was created. It allows both reactive changes by changing ".obs" variables, and mechanical updates via update(). However, of the 4 widgets he is the one that consumes the most resources, since in addition to having a Subscription to receive change events from his children, he subscribes to the update method of his controller.
1076 1124
1077 -- Note: To use GetBuilder and MixinBuilder you must use GetController. To use GetX and Obx you must use RxController.  
1078 -Probably using a GetController using GetX and Obx will work, but it will not be possible to use an RxController on a GetBuilder.  
1079 -Extending these controllers is important, as they have life cycles, and can "start" and "end" events in their onInit() and onClose() methods. 1125 +Extending GetxController is important, as they have life cycles, and can "start" and "end" events in their onInit() and onClose() methods. You can use any class for this, but I strongly recommend you use the GetxController class to place your variables, whether they are observable or not.
1080 1126
1081 ## GetBuilder vs GetX vs Obx vs MixinBuilder 1127 ## GetBuilder vs GetX vs Obx vs MixinBuilder
1082 In a decade working with programming I was able to learn some valuable lessons. 1128 In a decade working with programming I was able to learn some valuable lessons.
@@ -1097,8 +1143,6 @@ There are other situations where reactive programming is really interesting, and @@ -1097,8 +1143,6 @@ There are other situations where reactive programming is really interesting, and
1097 GetX is still more economical than any other reactive state manager, but it consumes a little more RAM than GetBuilder. Thinking about it and aiming to maximize the consumption of resources that Obx was created. Unlike GetX and GetBuilder, you will not be able to initialize a controller inside an Obx, it is just a Widget with a StreamSubscription that receives change events from your children, that's all. It is more economical than GetX, but loses to GetBuilder, which was to be expected, since it is reactive, and GetBuilder has the most simplistic approach that exists, of storing a widget's hashcode and its StateSetter. With Obx you don't need to write your controller type, and you can hear the change from multiple different controllers, but it needs to be initialized before, either using the example approach at the beginning of this readme, or using the Bindings class. 1143 GetX is still more economical than any other reactive state manager, but it consumes a little more RAM than GetBuilder. Thinking about it and aiming to maximize the consumption of resources that Obx was created. Unlike GetX and GetBuilder, you will not be able to initialize a controller inside an Obx, it is just a Widget with a StreamSubscription that receives change events from your children, that's all. It is more economical than GetX, but loses to GetBuilder, which was to be expected, since it is reactive, and GetBuilder has the most simplistic approach that exists, of storing a widget's hashcode and its StateSetter. With Obx you don't need to write your controller type, and you can hear the change from multiple different controllers, but it needs to be initialized before, either using the example approach at the beginning of this readme, or using the Bindings class.
1098 1144
1099 1145
1100 -  
1101 -  
1102 # Dependency Management 1146 # Dependency Management
1103 1147
1104 1148
@@ -1325,6 +1369,57 @@ Get.config( @@ -1325,6 +1369,57 @@ Get.config(
1325 ) 1369 )
1326 ``` 1370 ```
1327 1371
  1372 +# Breaking changes from 2.0
  1373 +1- Rx types:
  1374 +Before: StringX now: RxString
  1375 +
  1376 +Before: IntX now: RxInt
  1377 +
  1378 +Before: MapX now: RxMax
  1379 +
  1380 +Before: ListX now: RxList
  1381 +
  1382 +Before: NumX now: RxNum
  1383 +
  1384 +Before: RxDouble now: RxDouble
  1385 +
  1386 +RxController and GetBuilder now have merged, you no longer need to memorize which controller you want to use, just use GetxController, it will work for simple state management and for reactive as well.
  1387 +
  1388 +
  1389 +2- NamedRoutes
  1390 +Before:
  1391 +```dart
  1392 +GetMaterialApp(
  1393 + namedRoutes: {
  1394 + '/': GetRoute(page: Home()),
  1395 + }
  1396 +)
  1397 +```
  1398 +Now:
  1399 +```dart
  1400 +GetMaterialApp(
  1401 + getPages: [
  1402 + GetPage(name: '/', page:()=> Home()),
  1403 + ]
  1404 +)
  1405 +```
  1406 +
  1407 +Why this change?
  1408 +Often, it may be necessary to decide which page will be displayed from a parameter, or a login token, the previous approach was inflexible, as it did not allow this.
  1409 +Inserting the page into a function has significantly reduced the RAM consumption, since the routes will not be allocated in memory since the app was started, and it also allowed to do this type of approach:
  1410 +
  1411 +```dart
  1412 +
  1413 +GetStorage box = GetStorage();
  1414 +
  1415 +GetMaterialApp(
  1416 + getPages: [
  1417 + GetPage(name: '/', page:(){
  1418 + return box.hasData('token') ? Home() : Login();
  1419 + })
  1420 + ]
  1421 +)
  1422 +```
1328 1423
1329 1424
1330 This library will always be updated and implementing new features. Feel free to offer PRs and contribute to them. 1425 This library will always be updated and implementing new features. Feel free to offer PRs and contribute to them.
@@ -68,3 +68,4 @@ extension MDQ on BuildContext { @@ -68,3 +68,4 @@ extension MDQ on BuildContext {
68 /// True if the current device is Tablet 68 /// True if the current device is Tablet
69 bool get isTablet => isSmallTablet || isLargeTablet; 69 bool get isTablet => isSmallTablet || isLargeTablet;
70 } 70 }
  71 +
@@ -6,6 +6,9 @@ export 'src/snackbar/snack.dart'; @@ -6,6 +6,9 @@ export 'src/snackbar/snack.dart';
6 export 'src/bottomsheet/bottomsheet.dart'; 6 export 'src/bottomsheet/bottomsheet.dart';
7 export 'src/snackbar/snack_route.dart'; 7 export 'src/snackbar/snack_route.dart';
8 export 'src/state/get_state.dart'; 8 export 'src/state/get_state.dart';
  9 +export 'src/state/get_view.dart';
  10 +export 'src/regex/get_utils.dart';
  11 +export 'src/queue/get_queue.dart';
9 export 'src/state/mixin_state.dart'; 12 export 'src/state/mixin_state.dart';
10 export 'src/rx/rx_interface.dart'; 13 export 'src/rx/rx_interface.dart';
11 export 'src/rx/rx_impl.dart'; 14 export 'src/rx/rx_impl.dart';
@@ -21,3 +24,4 @@ export 'src/routes/observers/route_observer.dart'; @@ -21,3 +24,4 @@ export 'src/routes/observers/route_observer.dart';
21 export 'src/routes/transitions_type.dart'; 24 export 'src/routes/transitions_type.dart';
22 export 'src/platform/platform.dart'; 25 export 'src/platform/platform.dart';
23 export 'src/extension_instance.dart'; 26 export 'src/extension_instance.dart';
  27 +export 'src/routes/custom_transition.dart';
@@ -7,8 +7,9 @@ extension Storage on GetImpl { @@ -7,8 +7,9 @@ extension Storage on GetImpl {
7 return GetInstance().lazyPut<S>(builder, tag: tag); 7 return GetInstance().lazyPut<S>(builder, tag: tag);
8 } 8 }
9 9
10 - Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder, {String tag}) async =>  
11 - GetInstance().putAsync<S>(builder, tag: tag); 10 + Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
  11 + {String tag, bool permanent = false}) async =>
  12 + GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
12 13
13 S find<S>({String tag, FcBuilderFunc<S> instance}) => 14 S find<S>({String tag, FcBuilderFunc<S> instance}) =>
14 GetInstance().find<S>(tag: tag, instance: instance); 15 GetInstance().find<S>(tag: tag, instance: instance);
@@ -2,7 +2,6 @@ import 'root/smart_management.dart'; @@ -2,7 +2,6 @@ import 'root/smart_management.dart';
2 import 'rx/rx_interface.dart'; 2 import 'rx/rx_interface.dart';
3 import 'typedefs/typedefs.dart'; 3 import 'typedefs/typedefs.dart';
4 4
5 -  
6 class GetConfig { 5 class GetConfig {
7 //////////// INSTANCE MANAGER 6 //////////// INSTANCE MANAGER
8 static Map<dynamic, dynamic> _singl = {}; 7 static Map<dynamic, dynamic> _singl = {};
@@ -26,8 +25,9 @@ class GetInstance { @@ -26,8 +25,9 @@ class GetInstance {
26 GetConfig._factory.putIfAbsent(key, () => builder); 25 GetConfig._factory.putIfAbsent(key, () => builder);
27 } 26 }
28 27
29 - Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder, {String tag}) async {  
30 - return put<S>(await builder(), tag: tag); 28 + Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
  29 + {String tag, bool permanent = false}) async {
  30 + return put<S>(await builder(), tag: tag, permanent: permanent);
31 } 31 }
32 32
33 /// Inject class on Get Instance Manager 33 /// Inject class on Get Instance Manager
@@ -105,14 +105,13 @@ class GetInstance { @@ -105,14 +105,13 @@ class GetInstance {
105 } 105 }
106 106
107 void registerRouteInstance<S>({String tag}) { 107 void registerRouteInstance<S>({String tag}) {
108 - // print("Register route [$S] as ${currentRoute}");  
109 GetConfig.routesKey 108 GetConfig.routesKey
110 .putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute); 109 .putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute);
111 } 110 }
112 111
113 S findByType<S>(Type type, {String tag}) { 112 S findByType<S>(Type type, {String tag}) {
114 String key = _getKey(type, tag); 113 String key = _getKey(type, tag);
115 - return GetConfig._singl[key].getSependency(); 114 + return GetConfig._singl[key].getSependency() as S;
116 } 115 }
117 116
118 void initController<S>({String tag}) { 117 void initController<S>({String tag}) {
@@ -136,7 +135,7 @@ class GetInstance { @@ -136,7 +135,7 @@ class GetInstance {
136 callInit = true; 135 callInit = true;
137 } 136 }
138 137
139 - FcBuilder builder = GetConfig._singl[key]; 138 + FcBuilder builder = GetConfig._singl[key] as FcBuilder;
140 if (builder == null) { 139 if (builder == null) {
141 if (tag == null) { 140 if (tag == null) {
142 throw "class ${S.toString()} is not register"; 141 throw "class ${S.toString()} is not register";
@@ -148,7 +147,7 @@ class GetInstance { @@ -148,7 +147,7 @@ class GetInstance {
148 initController<S>(tag: tag); 147 initController<S>(tag: tag);
149 } 148 }
150 149
151 - return GetConfig._singl[key].getSependency(); 150 + return GetConfig._singl[key].getSependency() as S;
152 } else { 151 } else {
153 if (!GetConfig._factory.containsKey(key)) 152 if (!GetConfig._factory.containsKey(key))
154 throw " $S not found. You need call put<$S>($S()) before"; 153 throw " $S not found. You need call put<$S>($S()) before";
@@ -177,7 +176,7 @@ class GetInstance { @@ -177,7 +176,7 @@ class GetInstance {
177 /// Remove dependency of [S] on dependency abstraction. For concrete class use delete 176 /// Remove dependency of [S] on dependency abstraction. For concrete class use delete
178 void remove<S>({String tag}) { 177 void remove<S>({String tag}) {
179 String key = _getKey(S, tag); 178 String key = _getKey(S, tag);
180 - FcBuilder builder = GetConfig._singl[key]; 179 + FcBuilder builder = GetConfig._singl[key] as FcBuilder;
181 final i = builder.dependency; 180 final i = builder.dependency;
182 181
183 if (i is DisposableInterface) { 182 if (i is DisposableInterface) {
@@ -217,7 +216,7 @@ class GetInstance { @@ -217,7 +216,7 @@ class GetInstance {
217 return false; 216 return false;
218 } 217 }
219 218
220 - FcBuilder builder = GetConfig._singl[newKey]; 219 + FcBuilder builder = GetConfig._singl[newKey] as FcBuilder;
221 if (builder.permanent) { 220 if (builder.permanent) {
222 (key == null) 221 (key == null)
223 ? print( 222 ? print(
@@ -184,7 +184,7 @@ abstract class GetService { @@ -184,7 +184,7 @@ abstract class GetService {
184 Color overlayColor = Colors.transparent, 184 Color overlayColor = Colors.transparent,
185 Form userInputForm}); 185 Form userInputForm});
186 186
187 - void snackbar(title, message, 187 + void snackbar(String title, String message,
188 {Color colorText, 188 {Color colorText,
189 Duration duration, 189 Duration duration,
190 190
@@ -224,11 +224,11 @@ abstract class GetService { @@ -224,11 +224,11 @@ abstract class GetService {
224 224
225 /// INSTANCE MANAGER 225 /// INSTANCE MANAGER
226 226
227 - GetMaterialController getController; 227 + GetMaterialController getxController;
228 228
229 - changeTheme(ThemeData theme); 229 + void changeTheme(ThemeData theme);
230 230
231 - changeThemeMode(ThemeMode themeMode); 231 + void changeThemeMode(ThemeMode themeMode);
232 232
233 GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey); 233 GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey);
234 234
@@ -5,6 +5,7 @@ import 'package:get/src/get_instance.dart'; @@ -5,6 +5,7 @@ import 'package:get/src/get_instance.dart';
5 import 'package:get/src/get_interface.dart'; 5 import 'package:get/src/get_interface.dart';
6 import 'bottomsheet/bottomsheet.dart'; 6 import 'bottomsheet/bottomsheet.dart';
7 import 'platform/platform.dart'; 7 import 'platform/platform.dart';
  8 +import 'root/parse_route.dart';
8 import 'root/root_controller.dart'; 9 import 'root/root_controller.dart';
9 import 'routes/bindings_interface.dart'; 10 import 'routes/bindings_interface.dart';
10 import 'routes/default_route.dart'; 11 import 'routes/default_route.dart';
@@ -22,7 +23,7 @@ class GetImpl implements GetService { @@ -22,7 +23,7 @@ class GetImpl implements GetService {
22 bool defaultPopGesture = GetPlatform.isIOS; 23 bool defaultPopGesture = GetPlatform.isIOS;
23 bool defaultOpaqueRoute = true; 24 bool defaultOpaqueRoute = true;
24 Transition defaultTransition = 25 Transition defaultTransition =
25 - (GetPlatform.isIOS ? Transition.cupertino : Transition.fade); 26 + (GetPlatform.isIOS ? Transition.leftToRight : Transition.fadeIn);
26 Duration defaultDurationTransition = Duration(milliseconds: 400); 27 Duration defaultDurationTransition = Duration(milliseconds: 400);
27 bool defaultGlobalState = true; 28 bool defaultGlobalState = true;
28 RouteSettings settings; 29 RouteSettings settings;
@@ -45,32 +46,42 @@ class GetImpl implements GetService { @@ -45,32 +46,42 @@ class GetImpl implements GetService {
45 bool fullscreenDialog = false, 46 bool fullscreenDialog = false,
46 Object arguments, 47 Object arguments,
47 Bindings binding, 48 Bindings binding,
  49 + preventDuplicates = true,
48 bool popGesture}) { 50 bool popGesture}) {
49 - return global(id).currentState.push(GetRouteBase( 51 + if (preventDuplicates &&
  52 + '/' + page.toString().toLowerCase() == currentRoute) {
  53 + return null;
  54 + }
  55 +
  56 + return global(id).currentState.push(GetPageRoute(
50 opaque: opaque ?? true, 57 opaque: opaque ?? true,
51 - page: page, 58 + page: () => page,
52 settings: RouteSettings( 59 settings: RouteSettings(
53 name: '/' + page.toString().toLowerCase(), arguments: arguments), 60 name: '/' + page.toString().toLowerCase(), arguments: arguments),
54 popGesture: popGesture ?? defaultPopGesture, 61 popGesture: popGesture ?? defaultPopGesture,
55 transition: transition ?? defaultTransition, 62 transition: transition ?? defaultTransition,
56 fullscreenDialog: fullscreenDialog, 63 fullscreenDialog: fullscreenDialog,
57 binding: binding, 64 binding: binding,
58 - transitionDuration: duration ?? defaultDurationTransition)); 65 + duration: duration ?? defaultDurationTransition));
59 } 66 }
60 67
61 /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed 68 /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed
62 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior 69 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
63 /// of rebuilding every app after a route, use opaque = true as the parameter. 70 /// of rebuilding every app after a route, use opaque = true as the parameter.
64 - Future<T> toNamed<T>(String page, {Object arguments, int id}) {  
65 - // if (key.currentState.mounted) // add this if appear problems on future with route navigate  
66 - // when widget don't mounted 71 + Future<T> toNamed<T>(String page,
  72 + {Object arguments, int id, preventDuplicates = true}) {
  73 + if (preventDuplicates && page == currentRoute) {
  74 + return null;
  75 + }
67 return global(id).currentState.pushNamed(page, arguments: arguments); 76 return global(id).currentState.pushNamed(page, arguments: arguments);
68 } 77 }
69 78
70 /// It replaces Navigator.pushReplacementNamed, but needs no context. 79 /// It replaces Navigator.pushReplacementNamed, but needs no context.
71 - Future<T> offNamed<T>(String page, {Object arguments, int id}) {  
72 - // if (key.currentState.mounted) // add this if appear problems on future with route navigate  
73 - // when widget don't mounted 80 + Future<T> offNamed<T>(String page,
  81 + {Object arguments, int id, preventDuplicates = true}) {
  82 + if (preventDuplicates && page == currentRoute) {
  83 + return null;
  84 + }
74 return global(id) 85 return global(id)
75 .currentState 86 .currentState
76 .pushReplacementNamed(page, arguments: arguments); 87 .pushReplacementNamed(page, arguments: arguments);
@@ -128,15 +139,23 @@ class GetImpl implements GetService { @@ -128,15 +139,23 @@ class GetImpl implements GetService {
128 (!isSnackbarOpen && !isDialogOpen && !isBottomSheetOpen); 139 (!isSnackbarOpen && !isDialogOpen && !isBottomSheetOpen);
129 140
130 /// It replaces Navigator.pop, but needs no context. 141 /// It replaces Navigator.pop, but needs no context.
131 - void back({dynamic result, bool closeOverlays = false, int id}) { 142 + void back(
  143 + {dynamic result,
  144 + bool closeOverlays = false,
  145 + bool canPop = true,
  146 + int id}) {
132 if (closeOverlays && isOverlaysOpen) { 147 if (closeOverlays && isOverlaysOpen) {
133 navigator.popUntil((route) { 148 navigator.popUntil((route) {
134 return (isOverlaysClosed); 149 return (isOverlaysClosed);
135 }); 150 });
136 } 151 }
  152 + if (canPop) {
137 if (global(id).currentState.canPop()) { 153 if (global(id).currentState.canPop()) {
138 global(id).currentState.pop(result); 154 global(id).currentState.pop(result);
139 } 155 }
  156 + } else {
  157 + global(id).currentState.pop(result);
  158 + }
140 } 159 }
141 160
142 /// It will close as many screens as you define. Times must be> 0; 161 /// It will close as many screens as you define. Times must be> 0;
@@ -162,17 +181,22 @@ class GetImpl implements GetService { @@ -162,17 +181,22 @@ class GetImpl implements GetService {
162 Object arguments, 181 Object arguments,
163 Bindings binding, 182 Bindings binding,
164 bool fullscreenDialog = false, 183 bool fullscreenDialog = false,
  184 + preventDuplicates = true,
165 Duration duration}) { 185 Duration duration}) {
166 - return global(id).currentState.pushReplacement(GetRouteBase( 186 + if (preventDuplicates &&
  187 + '/' + page.toString().toLowerCase() == currentRoute) {
  188 + return null;
  189 + }
  190 + return global(id).currentState.pushReplacement(GetPageRoute(
167 opaque: opaque ?? true, 191 opaque: opaque ?? true,
168 - page: page, 192 + page: () => page,
169 binding: binding, 193 binding: binding,
170 settings: RouteSettings( 194 settings: RouteSettings(
171 name: '/' + page.toString().toLowerCase(), arguments: arguments), 195 name: '/' + page.toString().toLowerCase(), arguments: arguments),
172 fullscreenDialog: fullscreenDialog, 196 fullscreenDialog: fullscreenDialog,
173 popGesture: popGesture ?? defaultPopGesture, 197 popGesture: popGesture ?? defaultPopGesture,
174 transition: transition ?? defaultTransition, 198 transition: transition ?? defaultTransition,
175 - transitionDuration: duration ?? defaultDurationTransition)); 199 + duration: duration ?? defaultDurationTransition));
176 } 200 }
177 201
178 /// It replaces Navigator.pushAndRemoveUntil, but needs no context 202 /// It replaces Navigator.pushAndRemoveUntil, but needs no context
@@ -184,21 +208,22 @@ class GetImpl implements GetService { @@ -184,21 +208,22 @@ class GetImpl implements GetService {
184 Object arguments, 208 Object arguments,
185 Bindings binding, 209 Bindings binding,
186 bool fullscreenDialog = false, 210 bool fullscreenDialog = false,
187 - Transition transition,  
188 - Duration duration}) { 211 + Duration duration,
  212 + Transition transition}) {
189 var route = (Route<dynamic> rota) => false; 213 var route = (Route<dynamic> rota) => false;
190 214
191 return global(id).currentState.pushAndRemoveUntil( 215 return global(id).currentState.pushAndRemoveUntil(
192 - GetRouteBase( 216 + GetPageRoute(
193 opaque: opaque ?? true, 217 opaque: opaque ?? true,
194 popGesture: popGesture ?? defaultPopGesture, 218 popGesture: popGesture ?? defaultPopGesture,
195 - page: page, 219 + page: () => page,
196 binding: binding, 220 binding: binding,
197 settings: RouteSettings( 221 settings: RouteSettings(
198 - name: '/' + page.toString().toLowerCase(), arguments: arguments), 222 + name: '/' + page.runtimeType.toString().toLowerCase(),
  223 + arguments: arguments),
199 fullscreenDialog: fullscreenDialog, 224 fullscreenDialog: fullscreenDialog,
200 transition: transition ?? defaultTransition, 225 transition: transition ?? defaultTransition,
201 - transitionDuration: duration ?? defaultDurationTransition, 226 + duration: duration ?? defaultDurationTransition,
202 ), 227 ),
203 predicate ?? route); 228 predicate ?? route);
204 } 229 }
@@ -461,7 +486,7 @@ class GetImpl implements GetService { @@ -461,7 +486,7 @@ class GetImpl implements GetService {
461 } 486 }
462 } 487 }
463 488
464 - void snackbar(title, message, 489 + void snackbar(String title, String message,
465 {Color colorText, 490 {Color colorText,
466 Duration duration, 491 Duration duration,
467 492
@@ -558,6 +583,24 @@ class GetImpl implements GetService { @@ -558,6 +583,24 @@ class GetImpl implements GetService {
558 } 583 }
559 } 584 }
560 585
  586 + ParseRouteTree routeTree;
  587 +
  588 + addPages(List<GetPage> getPages) {
  589 + if (getPages != null) {
  590 + if (routeTree == null) routeTree = ParseRouteTree();
  591 + getPages.forEach((element) {
  592 + routeTree.addRoute(element);
  593 + });
  594 + }
  595 + }
  596 +
  597 + addPage(GetPage getPage) {
  598 + if (getPage != null) {
  599 + if (routeTree == null) routeTree = ParseRouteTree();
  600 + routeTree.addRoute(getPage);
  601 + }
  602 + }
  603 +
561 /// change default config of Get 604 /// change default config of Get
562 config( 605 config(
563 {bool enableLog, 606 {bool enableLog,
@@ -588,14 +631,27 @@ class GetImpl implements GetService { @@ -588,14 +631,27 @@ class GetImpl implements GetService {
588 } 631 }
589 } 632 }
590 633
591 - GetMaterialController getController = GetMaterialController(); 634 + GetMaterialController getxController = GetMaterialController();
  635 +
  636 + Locale locale;
  637 +
  638 + void updateLocale(Locale l) {
  639 + locale = l;
  640 + getxController.update();
  641 + }
  642 +
  643 + Map<String, Map<String, String>> translations;
  644 +
  645 + void addTranslations(Map<String, Map<String, String>> tr) {
  646 + translations.addAll(tr);
  647 + }
592 648
593 - changeTheme(ThemeData theme) {  
594 - getController.setTheme(theme); 649 + void changeTheme(ThemeData theme) {
  650 + getxController.setTheme(theme);
595 } 651 }
596 652
597 - changeThemeMode(ThemeMode themeMode) {  
598 - getController.setThemeMode(themeMode); 653 + void changeThemeMode(ThemeMode themeMode) {
  654 + getxController.setThemeMode(themeMode);
599 } 655 }
600 656
601 GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) { 657 GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) {
  1 +import 'dart:async';
  2 +
  3 +class GetQueue {
  4 + final List<_Item> _queue = [];
  5 + bool _active = false;
  6 +
  7 + void _check() async {
  8 + if (!_active && _queue.isNotEmpty) {
  9 + _active = true;
  10 + var item = _queue.removeAt(0);
  11 + try {
  12 + item.completer.complete(await item.job());
  13 + } catch (e) {
  14 + item.completer.completeError(e);
  15 + }
  16 + _active = false;
  17 + _check();
  18 + }
  19 + }
  20 +
  21 + Future<T> add<T>(Function job) {
  22 + var completer = Completer<T>();
  23 + _queue.add(_Item(completer, job));
  24 + _check();
  25 + return completer.future;
  26 + }
  27 +}
  28 +
  29 +class _Item {
  30 + final completer;
  31 + final job;
  32 + _Item(this.completer, this.job);
  33 +}
  1 +import 'package:get/src/regex/regex.dart';
  2 +
  3 +class GetUtils {
  4 + /// Checks if data is null.
  5 + static bool isNull(dynamic s) => s == null;
  6 +
  7 + /// Checks if data is null or blank (empty or only contains whitespace).
  8 + static bool isNullOrBlank(dynamic s) {
  9 + if (isNull(s)) return true;
  10 + switch (s.runtimeType) {
  11 + case String:
  12 + case List:
  13 + case Map:
  14 + case Set:
  15 + case Iterable:
  16 + return s.isEmpty;
  17 + break;
  18 + default:
  19 + return s.toString() == 'null' || s.toString().trim().isEmpty;
  20 + }
  21 + }
  22 +
  23 + /// Checks if string is int or double.
  24 + static bool isNum(String s) {
  25 + if (isNull(s)) return false;
  26 + return num.tryParse(s) is num ?? false;
  27 + }
  28 +
  29 + /// Checks if string consist only numeric.
  30 + /// Numeric only doesnt accepting "." which double data type have
  31 + static bool isNumericOnly(String s) =>
  32 + RegexValidation.hasMatch(s, regex.numericOnly);
  33 +
  34 + /// Checks if string consist only Alphabet. (No Whitespace)
  35 + static bool isAlphabetOnly(String s) =>
  36 + RegexValidation.hasMatch(s, regex.alphabetOnly);
  37 +
  38 + /// Checks if string is boolean.
  39 + static bool isBool(String s) {
  40 + if (isNull(s)) return false;
  41 + return (s == 'true' || s == 'false');
  42 + }
  43 +
  44 + /// Checks if string is an vector file.
  45 + static bool isVector(String s) => RegexValidation.hasMatch(s, regex.vector);
  46 +
  47 + /// Checks if string is an image file.
  48 + static bool isImage(String s) => RegexValidation.hasMatch(s, regex.image);
  49 +
  50 + /// Checks if string is an audio file.
  51 + static bool isAudio(String s) => RegexValidation.hasMatch(s, regex.audio);
  52 +
  53 + /// Checks if string is an video file.
  54 + static bool isVideo(String s) => RegexValidation.hasMatch(s, regex.video);
  55 +
  56 + /// Checks if string is an txt file.
  57 + static bool isTxt(String s) => RegexValidation.hasMatch(s, regex.txt);
  58 +
  59 + /// Checks if string is an Doc file.
  60 + static bool isDocument(String s) => RegexValidation.hasMatch(s, regex.doc);
  61 +
  62 + /// Checks if string is an Excel file.
  63 + static bool isExcel(String s) => RegexValidation.hasMatch(s, regex.excel);
  64 +
  65 + /// Checks if string is an PPT file.
  66 + static bool isPPT(String s) => RegexValidation.hasMatch(s, regex.ppt);
  67 +
  68 + /// Checks if string is an APK file.
  69 + static bool isAPK(String s) => RegexValidation.hasMatch(s, regex.apk);
  70 +
  71 + /// Checks if string is an video file.
  72 + static bool isPDF(String s) => RegexValidation.hasMatch(s, regex.pdf);
  73 +
  74 + /// Checks if string is an HTML file.
  75 + static bool isHTML(String s) => RegexValidation.hasMatch(s, regex.html);
  76 +
  77 + /// Checks if string is URL.
  78 + static bool isURL(String s) => RegexValidation.hasMatch(s, regex.url);
  79 +
  80 + /// Checks if string is email.
  81 + static bool isEmail(String s) => RegexValidation.hasMatch(s, regex.txt);
  82 +
  83 + /// Checks if string is phone number.
  84 + static bool isPhoneNumber(String s) =>
  85 + RegexValidation.hasMatch(s, regex.phone);
  86 +
  87 + /// Checks if string is DateTime (UTC or Iso8601).
  88 + static bool isDateTime(String s) =>
  89 + RegexValidation.hasMatch(s, regex.basicDateTime);
  90 +
  91 + /// Checks if string is MD5 hash.
  92 + static bool isMD5(String s) => RegexValidation.hasMatch(s, regex.md5);
  93 +
  94 + /// Checks if string is SHA1 hash.
  95 + static bool isSHA1(String s) => RegexValidation.hasMatch(s, regex.sha1);
  96 +
  97 + /// Checks if string is SHA256 hash.
  98 + static bool isSHA256(String s) => RegexValidation.hasMatch(s, regex.sha256);
  99 +
  100 + /// Checks if string is ISBN 10 or 13.
  101 + static bool isISBN(String s) => RegexValidation.hasMatch(s, regex.isbn);
  102 +
  103 + /// Checks if string is SSN (Social Security Number).
  104 + static bool isSSN(String s) => RegexValidation.hasMatch(s, regex.ssn);
  105 +
  106 + /// Checks if string is binary.
  107 + static bool isBinary(String s) => RegexValidation.hasMatch(s, regex.binary);
  108 +
  109 + /// Checks if string is IPv4.
  110 + static bool isIPv4(String s) => RegexValidation.hasMatch(s, regex.ipv4);
  111 +
  112 + /// Checks if string is IPv6.
  113 + static bool isIPv6(String s) => RegexValidation.hasMatch(s, regex.ipv6);
  114 +
  115 + /// Checks if string is hexadecimal.
  116 + /// Example: HexColor => #12F
  117 + static bool isHexadecimal(String s) =>
  118 + RegexValidation.hasMatch(s, regex.hexadecimal);
  119 +
  120 + /// Checks if string is Palindrom.
  121 + static bool isPalindrom(String s) {
  122 + bool isPalindrom = true;
  123 + for (var i = 0; i < s.length; i++) {
  124 + if (s[i] != s[s.length - i - 1]) isPalindrom = false;
  125 + }
  126 + return isPalindrom;
  127 + }
  128 +
  129 + /// Checks if all data have same value.
  130 + /// Example: 111111 -> true, wwwww -> true, [1,1,1,1] -> true
  131 + static bool isOneAKind(dynamic s) {
  132 + if ((s is String || s is List) && !isNullOrBlank(s)) {
  133 + var first = s[0];
  134 + var isOneAKind = true;
  135 + for (var i = 0; i < s.length; i++) {
  136 + if (s[i] != first) isOneAKind = false;
  137 + }
  138 + return isOneAKind;
  139 + }
  140 + if (s is int) {
  141 + String value = s.toString();
  142 + var first = value[0];
  143 + var isOneAKind = true;
  144 + for (var i = 0; i < value.length; i++) {
  145 + if (value[i] != first) isOneAKind = false;
  146 + }
  147 + return isOneAKind;
  148 + }
  149 + return false;
  150 + }
  151 +
  152 + /// Checks if string is Passport No.
  153 + static bool isPassport(String s) =>
  154 + RegexValidation.hasMatch(s, regex.passport);
  155 +
  156 + /// Checks if string is Currency.
  157 + static bool isCurrency(String s) =>
  158 + RegexValidation.hasMatch(s, regex.currency);
  159 +
  160 + /// Checks if length of data is LOWER than maxLength.
  161 + static bool isLengthLowerThan(dynamic s, int maxLength) {
  162 + if (isNull(s)) return (maxLength <= 0) ? true : false;
  163 + switch (s.runtimeType) {
  164 + case String:
  165 + case List:
  166 + case Map:
  167 + case Set:
  168 + case Iterable:
  169 + return s.length < maxLength;
  170 + break;
  171 + case int:
  172 + return s.toString().length < maxLength;
  173 + break;
  174 + case double:
  175 + return s.toString().replaceAll('.', '').length < maxLength;
  176 + break;
  177 + default:
  178 + return false;
  179 + }
  180 + }
  181 +
  182 + /// Checks if length of data is GREATER than maxLength.
  183 + static bool isLengthGreaterThan(dynamic s, int maxLength) {
  184 + if (isNull(s)) return false;
  185 + switch (s.runtimeType) {
  186 + case String:
  187 + case List:
  188 + case Map:
  189 + case Set:
  190 + case Iterable:
  191 + return s.length > maxLength;
  192 + break;
  193 + case int:
  194 + return s.toString().length > maxLength;
  195 + break;
  196 + case double:
  197 + return s.toString().replaceAll('.', '').length > maxLength;
  198 + break;
  199 + default:
  200 + return false;
  201 + }
  202 + }
  203 +
  204 + /// Checks if length of data is GREATER OR EQUAL to maxLength.
  205 + static bool isLengthGreaterOrEqual(dynamic s, int maxLength) {
  206 + if (isNull(s)) return false;
  207 + switch (s.runtimeType) {
  208 + case String:
  209 + case List:
  210 + case Map:
  211 + case Set:
  212 + case Iterable:
  213 + return s.length >= maxLength;
  214 + break;
  215 + case int:
  216 + return s.toString().length >= maxLength;
  217 + break;
  218 + case double:
  219 + return s.toString().replaceAll('.', '').length >= maxLength;
  220 + break;
  221 + default:
  222 + return false;
  223 + }
  224 + }
  225 +
  226 + /// Checks if length of data is LOWER OR EQUAL to maxLength.
  227 + static bool isLengthLowerOrEqual(dynamic s, int maxLength) {
  228 + if (isNull(s)) return false;
  229 + switch (s.runtimeType) {
  230 + case String:
  231 + case List:
  232 + case Map:
  233 + case Set:
  234 + case Iterable:
  235 + return s.length <= maxLength;
  236 + break;
  237 + case int:
  238 + return s.toString().length <= maxLength;
  239 + break;
  240 + case double:
  241 + return s.toString().replaceAll('.', '').length <= maxLength;
  242 + default:
  243 + return false;
  244 + }
  245 + }
  246 +
  247 + /// Checks if length of data is EQUAL to maxLength.
  248 + static bool isLengthEqualTo(dynamic s, int maxLength) {
  249 + if (isNull(s)) return false;
  250 + switch (s.runtimeType) {
  251 + case String:
  252 + case List:
  253 + case Map:
  254 + case Set:
  255 + case Iterable:
  256 + return s.length == maxLength;
  257 + break;
  258 + case int:
  259 + return s.toString().length == maxLength;
  260 + break;
  261 + case double:
  262 + return s.toString().replaceAll('.', '').length == maxLength;
  263 + break;
  264 + default:
  265 + return false;
  266 + }
  267 + }
  268 +
  269 + /// Checks if length of data is BETWEEN minLength to maxLength.
  270 + static bool isLengthBetween(dynamic s, int minLength, int maxLength) {
  271 + if (isNull(s)) return false;
  272 + return isLengthGreaterOrEqual(s, minLength) &&
  273 + isLengthLowerOrEqual(s, maxLength);
  274 + }
  275 +
  276 + /// Checks if a contains b (Treating or interpreting upper- and lowercase letters as being the same).
  277 + static bool isCaseInsensitiveContains(String a, String b) =>
  278 + a.toLowerCase().contains(b.toLowerCase());
  279 +
  280 + /// Checks if a contains b or b contains a (Treating or interpreting upper- and lowercase letters as being the same).
  281 + static bool isCaseInsensitiveContainsAny(String a, String b) {
  282 + String lowA = a.toLowerCase();
  283 + String lowB = b.toLowerCase();
  284 + return lowA.contains(lowB) || lowB.contains(lowA);
  285 + }
  286 +
  287 + /// Checks if num a LOWER than num b.
  288 + static bool isLowerThan(num a, num b) => a < b;
  289 +
  290 + /// Checks if num a GREATER than num b.
  291 + static bool isGreaterThan(num a, num b) => a > b;
  292 +
  293 + /// Checks if num a EQUAL than num b.
  294 + static bool isEqual(num a, num b) => a == b;
  295 +
  296 + /// Capitalize each word inside string
  297 + /// Example: your name => Your Name, your name => Your name
  298 + ///
  299 + /// If First Only is `true`, the only letter get uppercase is the first letter
  300 + static String capitalize(String s, {bool firstOnly = false}) {
  301 + if (isNullOrBlank(s)) return null;
  302 + if (firstOnly) return capitalizeFirst(s);
  303 +
  304 + List lst = s.split(' ');
  305 + String newStr = '';
  306 + for (var s in lst) newStr += capitalizeFirst(s);
  307 + return newStr;
  308 + }
  309 +
  310 + /// Uppercase first letter inside string and let the others lowercase
  311 + /// Example: your name => Your name
  312 + static String capitalizeFirst(String s) {
  313 + if (isNullOrBlank(s)) return null;
  314 + return s[0].toUpperCase() + s.substring(1).toLowerCase();
  315 + }
  316 +
  317 + /// Remove all whitespace inside string
  318 + /// Example: your name => yourname
  319 + static String removeAllWhitespace(String s) {
  320 + if (isNullOrBlank(s)) return null;
  321 + return s.replaceAll(' ', '');
  322 + }
  323 +
  324 + /// Camelcase string
  325 + /// Example: your name => yourName
  326 + static String camelCase(String s) {
  327 + if (isNullOrBlank(s)) return null;
  328 + return s[0].toLowerCase() + removeAllWhitespace(capitalize(s)).substring(1);
  329 + }
  330 +
  331 + /// Extract numeric value of string
  332 + /// Example: OTP 12312 27/04/2020 => 1231227042020ß
  333 + /// If firstword only is true, then the example return is "12312" (first found numeric word)
  334 + static String numericOnly(String s, {bool firstWordOnly = false}) {
  335 + String numericOnlyStr = '';
  336 + for (var i = 0; i < s.length; i++) {
  337 + if (isNumericOnly(s[i])) numericOnlyStr += s[i];
  338 + if (firstWordOnly && numericOnlyStr.isNotEmpty && s[i] == " ") break;
  339 + }
  340 + return numericOnlyStr;
  341 + }
  342 +
  343 + static Regex regex = Regex();
  344 +}
  345 +
  346 +class RegexValidation {
  347 + /// Returns whether the pattern has a match in the string [input].
  348 + static bool hasMatch(String s, Pattern p) =>
  349 + (s == null) ? false : RegExp(p).hasMatch(s);
  350 +}
  1 +class Regex {
  2 + /// Username regex
  3 + Pattern username = r'^[a-zA-Z0-9][a-zA-Z0-9_.]+[a-zA-Z0-9]$';
  4 +
  5 + /// Email regex
  6 + Pattern email =
  7 + r'^[a-z0-9]+([-+._][a-z0-9]+){0,2}@.*?(\.(a(?:[cdefgilmnoqrstuwxz]|ero|(?:rp|si)a)|b(?:[abdefghijmnorstvwyz]iz)|c(?:[acdfghiklmnoruvxyz]|at|o(?:m|op))|d[ejkmoz]|e(?:[ceghrstu]|du)|f[ijkmor]|g(?:[abdefghilmnpqrstuwy]|ov)|h[kmnrtu]|i(?:[delmnoqrst]|n(?:fo|t))|j(?:[emop]|obs)|k[eghimnprwyz]|l[abcikrstuvy]|m(?:[acdeghklmnopqrstuvwxyz]|il|obi|useum)|n(?:[acefgilopruz]|ame|et)|o(?:m|rg)|p(?:[aefghklmnrstwy]|ro)|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|t(?:[cdfghjklmnoprtvwz]|(?:rav)?el)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])\b){1,2}$';
  8 +
  9 + /// URL regex
  10 + Pattern url =
  11 + r"^((((H|h)(T|t)|(F|f))(T|t)(P|p)((S|s)?))\://)?(www.|[a-zA-Z0-9].)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,6}(\:[0-9]{1,5})*(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&amp;%\$#\=~_\-]+))*$";
  12 +
  13 + /// Phone Number regex
  14 + /// Must started by either, "0", "+", "+XX <X between 2 to 4 digit>", "(+XX <X between 2 to 3 digit>)"
  15 + /// Can add whitespace separating digit with "+" or "(+XX)"
  16 + /// Example: 05555555555, +555 5555555555, (+123) 5555555555, (555) 5555555555, +5555 5555555555
  17 + Pattern phone =
  18 + r'^(0|\+|(\+[0-9]{2,4}|\(\+?[0-9]{2,4}\)) ?)([0-9]*|\d{2,4}-\d{2,4}(-\d{2,4})?)$';
  19 +
  20 + /// Hexadecimal regex
  21 + Pattern hexadecimal = r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$';
  22 +
  23 + /// Image vector regex
  24 + Pattern vector = r'.(svg)$';
  25 +
  26 + /// Image regex
  27 + Pattern image = r'.(jpeg|jpg|gif|png|bmp)$';
  28 +
  29 + /// Audio regex
  30 + Pattern audio = r'.(mp3|wav|wma|amr|ogg)$';
  31 +
  32 + /// Video regex
  33 + Pattern video = r'.(mp4|avi|wmv|rmvb|mpg|mpeg|3gp)$';
  34 +
  35 + /// Txt regex
  36 + Pattern txt = r'.txt$';
  37 +
  38 + /// Document regex
  39 + Pattern doc = r'.(doc|docx)$';
  40 +
  41 + /// Excel regex
  42 + Pattern excel = r'.(xls|xlsx)$';
  43 +
  44 + /// PPT regex
  45 + Pattern ppt = r'.(ppt|pptx)$';
  46 +
  47 + /// Document regex
  48 + Pattern apk = r'.apk$';
  49 +
  50 + /// PDF regex
  51 + Pattern pdf = r'.pdf$';
  52 +
  53 + /// HTML regex
  54 + Pattern html = r'.html$';
  55 +
  56 + /// DateTime regex (UTC)
  57 + /// Unformatted date time (UTC and Iso8601)
  58 + /// Example: 2020-04-27 08:14:39.977, 2020-04-27T08:14:39.977, 2020-04-27 01:14:39.977Z
  59 + Pattern basicDateTime = r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}.\d{3}Z?$';
  60 +
  61 + /// Binary regex
  62 + /// Consist only 0 & 1
  63 + Pattern binary = r'^[0-1]*$';
  64 +
  65 + /// MD5 regex
  66 + Pattern md5 = r'^[a-f0-9]{32}$';
  67 +
  68 + /// SHA1 regex
  69 + Pattern sha1 = r'(([A-Fa-f0-9]{2}\:){19}[A-Fa-f0-9]{2}|[A-Fa-f0-9]{40})';
  70 +
  71 + /// SHA256 regex
  72 + Pattern sha256 = r'([A-Fa-f0-9]{2}\:){31}[A-Fa-f0-9]{2}|[A-Fa-f0-9]{64}';
  73 +
  74 + /// SSN (Social Security Number) regex
  75 + Pattern ssn =
  76 + r'^(?!0{3}|6{3}|9[0-9]{2})[0-9]{3}-?(?!0{2})[0-9]{2}-?(?!0{4})[0-9]{4}$';
  77 +
  78 + /// IPv4 regex
  79 + Pattern ipv4 = r'^(?:(?:^|\.)(?:2(?:5[0-5]|[0-4]\d)|1?\d?\d)){4}$';
  80 +
  81 + /// IPv6 regex
  82 + Pattern ipv6 =
  83 + r'^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$';
  84 +
  85 + /// ISBN 10 & 13 regex
  86 + Pattern isbn =
  87 + r'(ISBN(\-1[03])?[:]?[ ]?)?(([0-9Xx][- ]?){13}|([0-9Xx][- ]?){10})';
  88 +
  89 + /// Passport No. regex
  90 + Pattern passport = r'^(?!^0+$)[a-zA-Z0-9]{6,9}$';
  91 +
  92 + /// Currency regex
  93 + Pattern currency =
  94 + r'^(S?\$|\₩|Rp|\¥|\€|\₹|\₽|fr|R$|R)?[ ]?[-]?([0-9]{1,3}[,.]([0-9]{3}[,.])*[0-9]{3}|[0-9]+)([,.][0-9]{1,2})?( ?(USD?|AUD|NZD|CAD|CHF|GBP|CNY|EUR|JPY|IDR|MXN|NOK|KRW|TRY|INR|RUB|BRL|ZAR|SGD|MYR))?$';
  95 +
  96 + /// Numeric Only regex (No Whitespace & Symbols)
  97 + Pattern numericOnly = r'^\d+$';
  98 +
  99 + /// Alphabet Only regex (No Whitespace & Symbols)
  100 + Pattern alphabetOnly = r'^[a-zA-Z]+$';
  101 +
  102 + /// Password (Easy) Regex
  103 + /// Allowing all character except 'whitespace'
  104 + /// Minimum character: 8
  105 + Pattern passwordEasy = r'^\S{8,}$';
  106 +
  107 + /// Password (Easy) Regex
  108 + /// Allowing all character
  109 + /// Minimum character: 8
  110 + Pattern passwordEasyAllowedWhitespace = r'^[\S ]{8,}$';
  111 +
  112 + /// Password (Normal) Regex
  113 + /// Allowing all character except 'whitespace'
  114 + /// Must contains at least: 1 letter & 1 number
  115 + /// Minimum character: 8
  116 + Pattern passwordNormal1 = r'^(?=.*[A-Za-z])(?=.*\d)\S{8,}$';
  117 +
  118 + /// Password (Normal) Regex
  119 + /// Allowing all character
  120 + /// Must contains at least: 1 letter & 1 number
  121 + /// Minimum character: 8
  122 + Pattern passwordNormal1AllowedWhitespace =
  123 + r'^(?=.*[A-Za-z])(?=.*\d)[\S ]{8,}$';
  124 +
  125 + /// Password (Normal) Regex
  126 + /// Allowing LETTER and NUMBER only
  127 + /// Must contains at least: 1 letter & 1 number
  128 + /// Minimum character: 8
  129 + Pattern passwordNormal2 = r'^(?=.*[A-Za-z])(?=.*\d)[a-zA-Z0-9]{8,}$';
  130 +
  131 + /// Password (Normal) Regex
  132 + /// Allowing LETTER and NUMBER only
  133 + /// Must contains: 1 letter & 1 number
  134 + /// Minimum character: 8
  135 + Pattern passwordNormal2AllowedWhitespace =
  136 + r'^(?=.*[A-Za-z])(?=.*\d)[a-zA-Z0-9 ]{8,}$';
  137 +
  138 + /// Password (Normal) Regex
  139 + /// Allowing all character except 'whitespace'
  140 + /// Must contains at least: 1 uppercase letter, 1 lowecase letter & 1 number
  141 + /// Minimum character: 8
  142 + Pattern passwordNormal3 = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)\S{8,}$';
  143 +
  144 + /// Password (Normal) Regex
  145 + /// Allowing all character
  146 + /// Must contains at least: 1 uppercase letter, 1 lowecase letter & 1 number
  147 + /// Minimum character: 8
  148 + Pattern passwordNormal3AllowedWhitespace =
  149 + r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\S ]{8,}$';
  150 +
  151 + /// Password (Hard) Regex
  152 + /// Allowing all character except 'whitespace'
  153 + /// Must contains at least: 1 uppercase letter, 1 lowecase letter, 1 number, & 1 special character (symbol)
  154 + /// Minimum character: 8
  155 + Pattern passwordHard = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_])\S{8,}$';
  156 +
  157 + /// Password (Hard) Regex
  158 + /// Allowing all character
  159 + /// Must contains at least: 1 uppercase letter, 1 lowecase letter, 1 number, & 1 special character (symbol)
  160 + /// Minimum character: 8
  161 + Pattern passwordHardAllowedWhitespace =
  162 + r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_])[\S ]{8,}$';
  163 +}
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 -import 'package:get/src/routes/utils/parse_arguments.dart';  
3 import 'package:get/src/state/get_state.dart'; 2 import 'package:get/src/state/get_state.dart';
4 3
5 -class GetMaterialController extends GetController {  
6 - ParseRoute parse = ParseRoute(); 4 +class GetMaterialController extends GetxController {
7 Key key; 5 Key key;
8 ThemeData theme; 6 ThemeData theme;
9 ThemeMode themeMode; 7 ThemeMode themeMode;
  1 +import 'package:flutter/foundation.dart';
1 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
3 import 'package:get/src/routes/get_route.dart'; 4 import 'package:get/src/routes/get_route.dart';
4 -import 'package:get/src/routes/utils/parse_arguments.dart';  
5 import '../get_instance.dart'; 5 import '../get_instance.dart';
6 import 'parse_route.dart'; 6 import 'parse_route.dart';
7 import 'root_controller.dart'; 7 import 'root_controller.dart';
@@ -19,6 +19,8 @@ class GetMaterialApp extends StatelessWidget { @@ -19,6 +19,8 @@ class GetMaterialApp extends StatelessWidget {
19 this.onUnknownRoute, 19 this.onUnknownRoute,
20 this.navigatorObservers = const <NavigatorObserver>[], 20 this.navigatorObservers = const <NavigatorObserver>[],
21 this.builder, 21 this.builder,
  22 + this.translationsKeys,
  23 + this.translations,
22 this.title = '', 24 this.title = '',
23 this.onGenerateTitle, 25 this.onGenerateTitle,
24 this.color, 26 this.color,
@@ -50,27 +52,6 @@ class GetMaterialApp extends StatelessWidget { @@ -50,27 +52,6 @@ class GetMaterialApp extends StatelessWidget {
50 this.popGesture, 52 this.popGesture,
51 this.transitionDuration, 53 this.transitionDuration,
52 this.defaultGlobalState, 54 this.defaultGlobalState,
53 - // ignore: deprecated_member_use_from_same_package  
54 - @Deprecated(  
55 - """Please, use new api getPages. You can now simply create a list of GetPages,  
56 - and enter your route name in the 'name' property.  
57 - Page now receives a function ()=> Page(), which allows more flexibility.  
58 - You can now decide which page you want to display, according to the parameters received on the page.  
59 - Example:  
60 - GetPage(  
61 - name: '/second',  
62 - page:(){  
63 - if (Get.parameters['id'] == null) {  
64 - return Login();  
65 - } else {  
66 - return Home();  
67 - }  
68 - });  
69 -  
70 - """)  
71 - // ignore: deprecated_member_use_from_same_package  
72 - this.namedRoutes,  
73 - this.unknownRoute,  
74 }) : assert(routes != null), 55 }) : assert(routes != null),
75 assert(navigatorObservers != null), 56 assert(navigatorObservers != null),
76 assert(title != null), 57 assert(title != null),
@@ -97,6 +78,8 @@ class GetMaterialApp extends StatelessWidget { @@ -97,6 +78,8 @@ class GetMaterialApp extends StatelessWidget {
97 final ThemeData darkTheme; 78 final ThemeData darkTheme;
98 final ThemeMode themeMode; 79 final ThemeMode themeMode;
99 final Color color; 80 final Color color;
  81 + final Map<String, Map<String, String>> translationsKeys;
  82 + final Translations translations;
100 final Locale locale; 83 final Locale locale;
101 final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates; 84 final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
102 final LocaleListResolutionCallback localeListResolutionCallback; 85 final LocaleListResolutionCallback localeListResolutionCallback;
@@ -121,135 +104,52 @@ class GetMaterialApp extends StatelessWidget { @@ -121,135 +104,52 @@ class GetMaterialApp extends StatelessWidget {
121 final Bindings initialBinding; 104 final Bindings initialBinding;
122 final Duration transitionDuration; 105 final Duration transitionDuration;
123 final bool defaultGlobalState; 106 final bool defaultGlobalState;
124 -  
125 - final Map<String, GetRoute> namedRoutes;  
126 final List<GetPage> getPages; 107 final List<GetPage> getPages;
127 - final GetRoute unknownRoute;  
128 108
129 Route<dynamic> generator(RouteSettings settings) { 109 Route<dynamic> generator(RouteSettings settings) {
130 - final match = _routeTree.matchRoute(settings.name);  
131 - print(settings.name);  
132 - 110 + final match = Get.routeTree.matchRoute(settings.name);
133 Get.parameters = match?.parameters; 111 Get.parameters = match?.parameters;
134 112
135 - return GetRouteBase(  
136 - page: null,  
137 - title: match.route.title,  
138 - route: match.route.page, 113 + return GetPageRoute(
  114 + page: match.route.page,
139 parameter: match.route.parameter, 115 parameter: match.route.parameter,
140 settings: 116 settings:
141 RouteSettings(name: settings.name, arguments: settings.arguments), 117 RouteSettings(name: settings.name, arguments: settings.arguments),
142 - maintainState: match.route.maintainState,  
143 curve: match.route.curve, 118 curve: match.route.curve,
144 - alignment: match.route.alignment,  
145 opaque: match.route.opaque, 119 opaque: match.route.opaque,
146 binding: match.route.binding, 120 binding: match.route.binding,
147 bindings: match.route.bindings, 121 bindings: match.route.bindings,
148 - transitionDuration: (transitionDuration == null  
149 - ? match.route.transitionDuration  
150 - : transitionDuration), 122 + duration: (transitionDuration ?? match.route.transitionDuration),
151 transition: match.route.transition, 123 transition: match.route.transition,
152 popGesture: match.route.popGesture, 124 popGesture: match.route.popGesture,
153 fullscreenDialog: match.route.fullscreenDialog, 125 fullscreenDialog: match.route.fullscreenDialog,
154 ); 126 );
155 } 127 }
156 128
157 - Route<dynamic> namedRoutesGenerate(RouteSettings settings) {  
158 - // Get.setSettings(settings);  
159 -  
160 - /// onGenerateRoute to FlutterWeb is Broken on Dev/Master. This is a temporary  
161 - /// workaround until they fix it, because the problem is with the 'Flutter engine',  
162 - /// which changes the initial route for an empty String, not the main Flutter,  
163 - /// so only Team can fix it.  
164 - var parsedString = Get.getController.parse.split(  
165 - (settings.name == '' || settings.name == null)  
166 - ? (initialRoute ?? '/')  
167 - : settings.name);  
168 -  
169 - if (parsedString == null) {  
170 - parsedString = AppRouteMatch();  
171 - parsedString.route = settings.name;  
172 - }  
173 -  
174 - String settingsName = parsedString.route;  
175 - Map<String, GetRoute> newNamedRoutes = {};  
176 -  
177 - namedRoutes.forEach((key, value) {  
178 - String newName = Get.getController.parse.split(key).route;  
179 - newNamedRoutes.addAll({newName: value});  
180 - });  
181 -  
182 - if (newNamedRoutes.containsKey(settingsName)) {  
183 - Get.parameters = parsedString.parameters;  
184 -  
185 - return GetRouteBase(  
186 - page: newNamedRoutes[settingsName].page,  
187 - title: newNamedRoutes[settingsName].title,  
188 - parameter: parsedString.parameters,  
189 - settings:  
190 - RouteSettings(name: settings.name, arguments: settings.arguments),  
191 - maintainState: newNamedRoutes[settingsName].maintainState,  
192 - curve: newNamedRoutes[settingsName].curve,  
193 - alignment: newNamedRoutes[settingsName].alignment,  
194 - opaque: newNamedRoutes[settingsName].opaque,  
195 - binding: newNamedRoutes[settingsName].binding,  
196 - bindings: newNamedRoutes[settingsName].bindings,  
197 - transitionDuration: (transitionDuration == null  
198 - ? newNamedRoutes[settingsName].transitionDuration  
199 - : transitionDuration),  
200 - transition: newNamedRoutes[settingsName].transition,  
201 - popGesture: newNamedRoutes[settingsName].popGesture,  
202 - fullscreenDialog: newNamedRoutes[settingsName].fullscreenDialog,  
203 - );  
204 - } else {  
205 - return ((unknownRoute == null  
206 - ? GetRouteBase(  
207 - page: Scaffold(  
208 - body: Center(  
209 - child: Text("Route not found :("),  
210 - ),  
211 - ))  
212 - : GetRouteBase(  
213 - page: unknownRoute.page,  
214 - title: unknownRoute.title,  
215 - settings: unknownRoute.settings,  
216 - maintainState: unknownRoute.maintainState,  
217 - curve: unknownRoute.curve,  
218 - alignment: unknownRoute.alignment,  
219 - parameter: unknownRoute.parameter,  
220 - opaque: unknownRoute.opaque,  
221 - binding: unknownRoute.binding,  
222 - bindings: unknownRoute.bindings,  
223 - transitionDuration: unknownRoute.transitionDuration,  
224 - popGesture: unknownRoute.popGesture,  
225 - transition: unknownRoute.transition,  
226 - fullscreenDialog: unknownRoute.fullscreenDialog,  
227 - )));  
228 - }  
229 - }  
230 -  
231 @override 129 @override
232 Widget build(BuildContext context) { 130 Widget build(BuildContext context) {
233 return GetBuilder<GetMaterialController>( 131 return GetBuilder<GetMaterialController>(
234 - init: Get.getController, 132 + init: Get.getxController,
235 dispose: (d) { 133 dispose: (d) {
236 onDispose?.call(); 134 onDispose?.call();
237 }, 135 },
238 initState: (i) { 136 initState: (i) {
239 - if (getPages != null) {  
240 - _routeTree = ParseRouteTree();  
241 - getPages.forEach((element) {  
242 - _routeTree.addRoute(element);  
243 - }); 137 + if (locale != null) {
  138 + Get.locale = locale;
  139 + }
  140 +
  141 + if (translations != null) {
  142 + if (Get.locale == null) Get.translations = translations.keys;
244 } 143 }
  144 + if (translationsKeys != null) {
  145 + Get.translations = translationsKeys;
  146 + }
  147 +
245 initialBinding?.dependencies(); 148 initialBinding?.dependencies();
  149 + Get.addPages(getPages);
246 GetConfig.smartManagement = smartManagement; 150 GetConfig.smartManagement = smartManagement;
247 onInit?.call(); 151 onInit?.call();
248 - if (namedRoutes != null) {  
249 - namedRoutes.forEach((key, value) {  
250 - Get.getController.parse.addRoute(key);  
251 - });  
252 - } 152 +
253 Get.config( 153 Get.config(
254 enableLog: enableLog ?? GetConfig.isLogEnable, 154 enableLog: enableLog ?? GetConfig.isLogEnable,
255 defaultTransition: defaultTransition ?? Get.defaultTransition, 155 defaultTransition: defaultTransition ?? Get.defaultTransition,
@@ -268,32 +168,29 @@ class GetMaterialApp extends StatelessWidget { @@ -268,32 +168,29 @@ class GetMaterialApp extends StatelessWidget {
268 home: home, 168 home: home,
269 routes: routes ?? const <String, WidgetBuilder>{}, 169 routes: routes ?? const <String, WidgetBuilder>{},
270 initialRoute: initialRoute, 170 initialRoute: initialRoute,
271 - onGenerateRoute: (getPages != null  
272 - ? generator  
273 - : namedRoutes != null ? namedRoutesGenerate : onGenerateRoute),  
274 - onGenerateInitialRoutes: onGenerateInitialRoutes ??  
275 - (getPages == null || home != null)  
276 - ? null 171 + onGenerateRoute: (getPages != null ? generator : onGenerateRoute),
  172 + onGenerateInitialRoutes: (getPages == null || home != null)
  173 + ? onGenerateInitialRoutes
277 : (st) { 174 : (st) {
278 - final match = _routeTree.matchRoute(initialRoute);  
279 - Get.parameters = match.parameters; 175 + GetPageMatch match;
  176 + if (initialRoute == null && getPages != null) {
  177 + match = Get.routeTree?.matchRoute(getPages.first.name);
  178 + } else {
  179 + match = Get.routeTree?.matchRoute(initialRoute);
  180 + }
  181 + Get.parameters = match?.parameters;
280 return [ 182 return [
281 - GetRouteBase(  
282 - page: null,  
283 - route: match.route.page,  
284 - title: match.route.title, 183 + GetPageRoute(
  184 + page: match.route.page,
285 parameter: match.parameters, 185 parameter: match.parameters,
286 settings: 186 settings:
287 RouteSettings(name: initialRoute, arguments: null), 187 RouteSettings(name: initialRoute, arguments: null),
288 - maintainState: match.route.maintainState,  
289 curve: match.route.curve, 188 curve: match.route.curve,
290 - alignment: match.route.alignment,  
291 opaque: match.route.opaque, 189 opaque: match.route.opaque,
292 binding: match.route.binding, 190 binding: match.route.binding,
293 bindings: match.route.bindings, 191 bindings: match.route.bindings,
294 - transitionDuration: (transitionDuration == null  
295 - ? match.route.transitionDuration  
296 - : transitionDuration), 192 + duration: (transitionDuration ??
  193 + match.route.transitionDuration),
297 transition: match.route.transition, 194 transition: match.route.transition,
298 popGesture: match.route.popGesture, 195 popGesture: match.route.popGesture,
299 fullscreenDialog: match.route.fullscreenDialog, 196 fullscreenDialog: match.route.fullscreenDialog,
@@ -312,7 +209,7 @@ class GetMaterialApp extends StatelessWidget { @@ -312,7 +209,7 @@ class GetMaterialApp extends StatelessWidget {
312 theme: _.theme ?? theme ?? ThemeData.fallback(), 209 theme: _.theme ?? theme ?? ThemeData.fallback(),
313 darkTheme: darkTheme, 210 darkTheme: darkTheme,
314 themeMode: _.themeMode ?? themeMode ?? ThemeMode.system, 211 themeMode: _.themeMode ?? themeMode ?? ThemeMode.system,
315 - locale: locale, 212 + locale: Get.locale ?? locale,
316 localizationsDelegates: localizationsDelegates, 213 localizationsDelegates: localizationsDelegates,
317 localeListResolutionCallback: localeListResolutionCallback, 214 localeListResolutionCallback: localeListResolutionCallback,
318 localeResolutionCallback: localeResolutionCallback, 215 localeResolutionCallback: localeResolutionCallback,
@@ -332,4 +229,29 @@ class GetMaterialApp extends StatelessWidget { @@ -332,4 +229,29 @@ class GetMaterialApp extends StatelessWidget {
332 } 229 }
333 } 230 }
334 231
335 -ParseRouteTree _routeTree; 232 +abstract class Translations {
  233 + Map<String, Map<String, String>> get keys;
  234 +}
  235 +
  236 +extension Trans on String {
  237 + String get tr {
  238 + if (Get.translations
  239 + .containsKey("${Get.locale.languageCode}_${Get.locale.countryCode}")) {
  240 + return Get.translations[
  241 + "${Get.locale.languageCode}_${Get.locale.countryCode}"][this];
  242 + } else if (Get.translations.containsKey(Get.locale.languageCode)) {
  243 + return Get.translations[Get.locale.languageCode][this];
  244 + }
  245 + return Get.translations.values.first[this];
  246 + }
  247 +
  248 + String trArgs([List<String> args]) {
  249 + String key = tr;
  250 + if (args != null) {
  251 + args.forEach((arg) {
  252 + key = key.replaceFirst(RegExp(r'%s'), arg.toString());
  253 + });
  254 + }
  255 + return key;
  256 + }
  257 +}
1 abstract class Bindings { 1 abstract class Bindings {
2 - void dependencies(); 2 + dependencies();
3 } 3 }
4 4
5 // abstract class INavigation {} 5 // abstract class INavigation {}
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +abstract class CustomTransition {
  4 + Widget buildTransition(
  5 + BuildContext context,
  6 + Animation<double> animation,
  7 + Animation<double> secondaryAnimation,
  8 + Widget child,
  9 + );
  10 +}
1 import 'dart:math'; 1 import 'dart:math';
2 import 'dart:ui' show lerpDouble; 2 import 'dart:ui' show lerpDouble;
3 -  
4 -import 'package:flutter/cupertino.dart';  
5 -import 'package:flutter/foundation.dart';  
6 import 'package:flutter/gestures.dart'; 3 import 'package:flutter/gestures.dart';
7 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
  5 +import 'package:get/src/get_instance.dart';
8 import 'package:get/src/get_main.dart'; 6 import 'package:get/src/get_main.dart';
9 -import 'package:get/src/routes/bindings_interface.dart';  
10 -  
11 -import '../platform/platform.dart'; 7 +import 'package:get/src/platform/platform.dart';
  8 +import 'bindings_interface.dart';
  9 +import 'custom_transition.dart';
  10 +import 'transitions_filter.dart';
12 import 'transitions_type.dart'; 11 import 'transitions_type.dart';
13 12
14 -const double _kBackGestureWidth = 20.0;  
15 -const double _kMinFlingVelocity = 1.0;  
16 -const int _kMaxDroppedSwipePageForwardAnimationTime = 800; // Milliseconds.  
17 -  
18 -// The maximum time for a page to get reset to it's original position if the  
19 -// user releases a page mid swipe.  
20 -const int _kMaxPageBackAnimationTime = 300; 13 +class GetPageRoute<T> extends PageRouteBuilder<T> {
  14 + //final TransitionComponent transitionComponent;
  15 + final Duration duration;
  16 + final bool popGesture;
  17 + final Transition transition;
  18 + final Curve curve;
  19 + final GetPageBuilder page;
  20 + final CustomTransition customTransition;
  21 + final Bindings binding;
  22 + final Map<String, String> parameter;
  23 + final List<Bindings> bindings;
21 24
22 -class GetRouteBase<T> extends PageRoute<T> {  
23 - /// The [builder], [maintainState], and [fullscreenDialog] arguments must not  
24 - /// be null.  
25 - GetRouteBase({  
26 - @required this.page,  
27 - this.title, 25 + GetPageRoute({
  26 + // this.transitionComponent,
28 RouteSettings settings, 27 RouteSettings settings,
29 - this.maintainState = true,  
30 - this.curve = Curves.linear,  
31 - this.alignment,  
32 - this.parameter, 28 + this.duration,
  29 + this.transition = Transition.native,
33 this.binding, 30 this.binding,
34 - this.route, 31 + @required this.page,
35 this.bindings, 32 this.bindings,
36 - this.customBuildPageTransitions,  
37 this.opaque = true, 33 this.opaque = true,
38 - this.transitionDuration = const Duration(milliseconds: 400), 34 + this.parameter,
  35 + this.fullscreenDialog = false,
  36 + this.curve,
39 this.popGesture, 37 this.popGesture,
40 - this.transition,  
41 - // this.duration = const Duration(milliseconds: 400),  
42 - bool fullscreenDialog = false,  
43 - }) : // assert(page != null),  
44 - assert(maintainState != null),  
45 - assert(fullscreenDialog != null),  
46 - // assert(opaque),  
47 - super(settings: settings, fullscreenDialog: fullscreenDialog) {  
48 - /// prebuild dependencies 38 + this.customTransition,
  39 + }) : super(
  40 + pageBuilder: (context, anim1, anim2) {
49 if (binding != null) { 41 if (binding != null) {
50 binding.dependencies(); 42 binding.dependencies();
51 } 43 }
52 if (bindings != null) { 44 if (bindings != null) {
53 - bindings.forEach((element) => element.dependencies()); 45 + for (Bindings element in bindings) {
  46 + element.dependencies();
54 } 47 }
55 } 48 }
56 -  
57 - /// Builds the primary contents of the route.  
58 - final Widget page;  
59 -  
60 - final GetPageBuilder route;  
61 -  
62 - final Widget customBuildPageTransitions;  
63 -  
64 - final bool popGesture;  
65 -  
66 - final Bindings binding;  
67 -  
68 - final List<Bindings> bindings;  
69 -  
70 - // final Duration duration;  
71 -  
72 - final Map<String, String> parameter;  
73 -  
74 - final String title;  
75 -  
76 - final Transition transition;  
77 -  
78 - final Curve curve;  
79 -  
80 - final Alignment alignment;  
81 -  
82 - ValueNotifier<String> _previousTitle;  
83 -  
84 - /// The title string of the previous [GetRoute].  
85 - ///  
86 - /// The [ValueListenable]'s value is readable after the route is installed  
87 - /// onto a [Navigator]. The [ValueListenable] will also notify its listeners  
88 - /// if the value changes (such as by replacing the previous route).  
89 - ///  
90 - /// The [ValueListenable] itself will be null before the route is installed.  
91 - /// Its content value will be null if the previous route has no title or  
92 - /// is not a [GetRoute].  
93 - ///  
94 - /// See also:  
95 - ///  
96 - /// * [ValueListenableBuilder], which can be used to listen and rebuild  
97 - /// widgets based on a ValueListenable.  
98 - ValueListenable<String> get previousTitle {  
99 - assert(  
100 - _previousTitle != null,  
101 - 'Cannot read the previousTitle for a route that has not yet been installed', 49 + GetConfig.currentRoute = settings.name;
  50 + return page();
  51 + },
  52 + settings: settings,
102 ); 53 );
103 - return _previousTitle;  
104 - }  
105 -  
106 - @override  
107 - void didChangePrevious(Route<dynamic> previousRoute) {  
108 - final String previousTitleString =  
109 - previousRoute is GetRouteBase ? previousRoute.title : null;  
110 - if (_previousTitle == null) {  
111 - _previousTitle = ValueNotifier<String>(previousTitleString);  
112 - } else {  
113 - _previousTitle.value = previousTitleString;  
114 - }  
115 - super.didChangePrevious(previousRoute);  
116 - }  
117 -  
118 - @override  
119 - final bool maintainState;  
120 54
121 - /// Allows you to set opaque to false to prevent route reconstruction.  
122 @override 55 @override
123 final bool opaque; 56 final bool opaque;
124 57
125 @override 58 @override
126 - final Duration transitionDuration; 59 + final bool fullscreenDialog;
127 60
128 @override 61 @override
129 - Color get barrierColor => null; //Color(0x00FFFFFF);  
130 -  
131 - @override  
132 - String get barrierLabel => null;  
133 -  
134 - @override  
135 - bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {  
136 - // Don't perform outgoing animation if the next route is a fullscreen dialog.  
137 - return nextRoute is GetRouteBase && !nextRoute.fullscreenDialog; 62 + Widget buildTransitions(BuildContext context, Animation<double> animation,
  63 + Animation<double> secondaryAnimation, Widget child) {
  64 + if (this.customTransition != null) {
  65 + return this.customTransition.buildTransition(
  66 + context,
  67 + animation,
  68 + secondaryAnimation,
  69 + popGesture ?? Get.defaultPopGesture
  70 + ? _CupertinoBackGestureDetector<T>(
  71 + enabledCallback: () => _isPopGestureEnabled<T>(this),
  72 + onStartPopGesture: () => _startPopGesture<T>(this),
  73 + child: child)
  74 + : child);
138 } 75 }
139 76
140 - /// True if an iOS-style back swipe pop gesture is currently underway for [route].  
141 - ///  
142 - /// This just check the route's [NavigatorState.userGestureInProgress].  
143 - ///  
144 - /// See also:  
145 - ///  
146 - /// * [popGestureEnabled], which returns true if a user-triggered pop gesture  
147 - /// would be allowed.  
148 - static bool isPopGestureInProgress(PageRoute<dynamic> route) {  
149 - return route.navigator.userGestureInProgress; 77 + if (transition == Transition.native) {
  78 + return Theme.of(context).pageTransitionsTheme.buildTransitions(
  79 + this,
  80 + context,
  81 + animation,
  82 + secondaryAnimation,
  83 + GetPlatform.isIOS
  84 + ? _CupertinoBackGestureDetector<T>(
  85 + enabledCallback: () => _isPopGestureEnabled<T>(this),
  86 + onStartPopGesture: () => _startPopGesture<T>(this),
  87 + child: child)
  88 + : child);
150 } 89 }
151 90
152 - /// True if an iOS-style back swipe pop gesture is currently underway for this route.  
153 - ///  
154 - /// See also:  
155 - ///  
156 - /// * [isPopGestureInProgress], which returns true if a Cupertino pop gesture  
157 - /// is currently underway for specific route.  
158 - /// * [popGestureEnabled], which returns true if a user-triggered pop gesture  
159 - /// would be allowed.  
160 - bool get popGestureInProgress => isPopGestureInProgress(this); 91 + final curvedAnimation = CurvedAnimation(
  92 + parent: animation,
  93 + curve: this.curve ?? Curves.linear,
  94 + );
161 95
162 - /// Whether a pop gesture can be started by the user.  
163 - ///  
164 - /// Returns true if the user can edge-swipe to a previous route.  
165 - ///  
166 - /// Returns false once [isPopGestureInProgress] is true, but  
167 - /// [isPopGestureInProgress] can only become true if [popGestureEnabled] was  
168 - /// true first.  
169 - ///  
170 - /// This should only be used between frames, not during build.  
171 - bool get popGestureEnabled => _isPopGestureEnabled(this); 96 + return TransitionFilter.newTransitionComponent(transition)
  97 + .buildChildWithTransition(
  98 + context,
  99 + curvedAnimation,
  100 + secondaryAnimation,
  101 + popGesture ?? Get.defaultPopGesture
  102 + ? _CupertinoBackGestureDetector<T>(
  103 + enabledCallback: () => _isPopGestureEnabled<T>(this),
  104 + onStartPopGesture: () => _startPopGesture<T>(this),
  105 + child: child)
  106 + : child);
  107 + }
  108 +
  109 + @override
  110 + Duration get transitionDuration =>
  111 + this.duration ?? Duration(milliseconds: 300);
172 112
173 static bool _isPopGestureEnabled<T>(PageRoute<T> route) { 113 static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
174 - // If there's nothing to go back to, then obviously we don't support  
175 - // the back gesture.  
176 if (route.isFirst) return false; 114 if (route.isFirst) return false;
177 - // If the route wouldn't actually pop if we popped it, then the gesture  
178 - // would be really confusing (or would skip internal routes), so disallow it. 115 +
179 if (route.willHandlePopInternally) return false; 116 if (route.willHandlePopInternally) return false;
180 - // If attempts to dismiss this route might be vetoed such as in a page  
181 - // with forms, then do not allow the user to dismiss the route with a swipe. 117 +
182 if (route.hasScopedWillPopCallback) return false; 118 if (route.hasScopedWillPopCallback) return false;
183 - // Fullscreen dialogs aren't dismissible by back swipe. 119 +
184 if (route.fullscreenDialog) return false; 120 if (route.fullscreenDialog) return false;
185 - // If we're in an animation already, we cannot be manually swiped. 121 +
186 if (route.animation.status != AnimationStatus.completed) return false; 122 if (route.animation.status != AnimationStatus.completed) return false;
187 - // If we're being popped into, we also cannot be swiped until the pop above  
188 - // it completes. This translates to our secondary animation being  
189 - // dismissed. 123 +
190 if (route.secondaryAnimation.status != AnimationStatus.dismissed) 124 if (route.secondaryAnimation.status != AnimationStatus.dismissed)
191 return false; 125 return false;
192 - // If we're in a gesture already, we cannot start another. 126 +
193 if (isPopGestureInProgress(route)) return false; 127 if (isPopGestureInProgress(route)) return false;
194 128
195 - // Looks like a back gesture would be welcome!  
196 return true; 129 return true;
197 } 130 }
198 131
199 - @override  
200 - Widget buildPage(BuildContext context, Animation<double> animation,  
201 - Animation<double> secondaryAnimation) {  
202 - final Widget result = Semantics(  
203 - scopesRoute: true,  
204 - explicitChildNodes: true,  
205 - child: (route == null ? page : route()),  
206 - );  
207 - assert(() {  
208 - if (route == null && page == null) {  
209 - throw FlutterError.fromParts(<DiagnosticsNode>[  
210 - ErrorSummary(  
211 - 'The builder for route "${settings.name}" returned null.'),  
212 - ErrorDescription('Route builders must never return null.'),  
213 - ]);  
214 - }  
215 - return true;  
216 - }());  
217 - return result;  
218 - }  
219 -  
220 - // Called by _CupertinoBackGestureDetector when a pop ("back") drag start  
221 - // gesture is detected. The returned controller handles all of the subsequent  
222 - // drag events.  
223 static _CupertinoBackGestureController<T> _startPopGesture<T>( 132 static _CupertinoBackGestureController<T> _startPopGesture<T>(
224 PageRoute<T> route) { 133 PageRoute<T> route) {
225 assert(_isPopGestureEnabled(route)); 134 assert(_isPopGestureEnabled(route));
226 135
227 return _CupertinoBackGestureController<T>( 136 return _CupertinoBackGestureController<T>(
228 navigator: route.navigator, 137 navigator: route.navigator,
229 - controller: route.controller, // protected access  
230 - );  
231 - }  
232 -  
233 - /// Returns a [CupertinoFullscreenDialogTransition] if [route] is a full  
234 - /// screen dialog, otherwise a [CupertinoPageTransition] is returned.  
235 - ///  
236 - /// Used by [GetRoute.buildTransitions].  
237 - ///  
238 - /// This method can be applied to any [PageRoute], not just  
239 - /// [GetRoute]. It's typically used to provide a Cupertino style  
240 - /// horizontal transition for material widgets when the target platform  
241 - /// is [TargetPlatform.iOS].  
242 - ///  
243 - /// See also:  
244 - ///  
245 - /// * [CupertinoPageTransitionsBuilder], which uses this method to define a  
246 - /// [PageTransitionsBuilder] for the [PageTransitionsTheme].  
247 - Widget buildPageTransitions<T>(  
248 - PageRoute<T> route,  
249 - BuildContext context,  
250 - bool popGesture,  
251 - Animation<double> animation,  
252 - Animation<double> secondaryAnimation,  
253 - Widget child,  
254 - Transition tr,  
255 - Curve curve,  
256 - Alignment alignment,  
257 - ) {  
258 - Transition transition = (tr ?? Get.defaultTransition);  
259 -  
260 - if (route.fullscreenDialog) {  
261 - final bool linearTransition = isPopGestureInProgress(route);  
262 - return CupertinoFullscreenDialogTransition(  
263 - primaryRouteAnimation: animation,  
264 - secondaryRouteAnimation: secondaryAnimation,  
265 - child: child,  
266 - linearTransition: linearTransition,  
267 - );  
268 - } else {  
269 - switch (transition) {  
270 - case Transition.fade:  
271 - final PageTransitionsBuilder matchingBuilder =  
272 - FadeUpwardsPageTransitionsBuilder();  
273 - return matchingBuilder.buildTransitions<T>(  
274 - route,  
275 - context,  
276 - animation,  
277 - secondaryAnimation,  
278 - popGesture  
279 - ? _CupertinoBackGestureDetector<T>(  
280 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
281 - onStartPopGesture: () => _startPopGesture<T>(route),  
282 - child: child)  
283 - : child);  
284 - break;  
285 - case Transition.rightToLeft:  
286 - return SlideTransition(  
287 - transformHitTests: false,  
288 - position: new Tween<Offset>(  
289 - begin: const Offset(1.0, 0.0),  
290 - end: Offset.zero,  
291 - ).animate(animation),  
292 - child: new SlideTransition(  
293 - position: new Tween<Offset>(  
294 - begin: Offset.zero,  
295 - end: const Offset(-1.0, 0.0),  
296 - ).animate(secondaryAnimation),  
297 - child: popGesture  
298 - ? _CupertinoBackGestureDetector<T>(  
299 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
300 - onStartPopGesture: () => _startPopGesture<T>(route),  
301 - child: child)  
302 - : child),  
303 - );  
304 - break;  
305 - case Transition.leftToRight:  
306 - return SlideTransition(  
307 - transformHitTests: false,  
308 - position: Tween<Offset>(  
309 - begin: const Offset(-1.0, 0.0),  
310 - end: Offset.zero,  
311 - ).animate(animation),  
312 - child: new SlideTransition(  
313 - position: new Tween<Offset>(  
314 - begin: Offset.zero,  
315 - end: const Offset(1.0, 0.0),  
316 - ).animate(secondaryAnimation),  
317 - child: popGesture  
318 - ? _CupertinoBackGestureDetector<T>(  
319 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
320 - onStartPopGesture: () => _startPopGesture<T>(route),  
321 - child: child)  
322 - : child),  
323 - );  
324 - break;  
325 - case Transition.upToDown:  
326 - return SlideTransition(  
327 - transformHitTests: false,  
328 - position: Tween<Offset>(  
329 - begin: const Offset(0.0, -1.0),  
330 - end: Offset.zero,  
331 - ).animate(animation),  
332 - child: new SlideTransition(  
333 - position: new Tween<Offset>(  
334 - begin: Offset.zero,  
335 - end: const Offset(0.0, 1.0),  
336 - ).animate(secondaryAnimation),  
337 - child: popGesture  
338 - ? _CupertinoBackGestureDetector<T>(  
339 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
340 - onStartPopGesture: () => _startPopGesture<T>(route),  
341 - child: child)  
342 - : child),  
343 - );  
344 - break;  
345 - case Transition.downToUp:  
346 - return SlideTransition(  
347 - transformHitTests: false,  
348 - position: Tween<Offset>(  
349 - begin: const Offset(0.0, 1.0),  
350 - end: Offset.zero,  
351 - ).animate(animation),  
352 - child: new SlideTransition(  
353 - position: new Tween<Offset>(  
354 - begin: Offset.zero,  
355 - end: const Offset(0.0, -1.0),  
356 - ).animate(secondaryAnimation),  
357 - child: popGesture  
358 - ? _CupertinoBackGestureDetector<T>(  
359 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
360 - onStartPopGesture: () => _startPopGesture<T>(route),  
361 - child: child)  
362 - : child),  
363 - );  
364 - break;  
365 - case Transition.scale:  
366 - return ScaleTransition(  
367 - alignment: alignment,  
368 - scale: CurvedAnimation(  
369 - parent: animation,  
370 - curve: Interval(  
371 - 0.00,  
372 - 0.50,  
373 - curve: curve,  
374 - ),  
375 - ),  
376 - child: popGesture  
377 - ? _CupertinoBackGestureDetector<T>(  
378 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
379 - onStartPopGesture: () => _startPopGesture<T>(route),  
380 - child: child)  
381 - : child);  
382 - break;  
383 - case Transition.rotate:  
384 - return RotationTransition(  
385 - alignment: alignment,  
386 - turns: animation,  
387 - child: ScaleTransition(  
388 - alignment: alignment,  
389 - scale: animation,  
390 - child: FadeTransition(  
391 - opacity: animation,  
392 - child: popGesture  
393 - ? _CupertinoBackGestureDetector<T>(  
394 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
395 - onStartPopGesture: () => _startPopGesture<T>(route),  
396 - child: child)  
397 - : child),  
398 - ),  
399 - );  
400 - break;  
401 -  
402 - case Transition.rightToLeftWithFade:  
403 - return SlideTransition(  
404 - position: Tween<Offset>(  
405 - begin: const Offset(1.0, 0.0),  
406 - end: Offset.zero,  
407 - ).animate(animation),  
408 - child: FadeTransition(  
409 - opacity: animation,  
410 - child: SlideTransition(  
411 - position: Tween<Offset>(  
412 - begin: Offset.zero,  
413 - end: const Offset(-1.0, 0.0),  
414 - ).animate(secondaryAnimation),  
415 - child: popGesture  
416 - ? _CupertinoBackGestureDetector<T>(  
417 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
418 - onStartPopGesture: () => _startPopGesture<T>(route),  
419 - child: child)  
420 - : child),  
421 - ),  
422 - );  
423 - break;  
424 - case Transition.leftToRightWithFade:  
425 - return SlideTransition(  
426 - position: Tween<Offset>(  
427 - begin: const Offset(-1.0, 0.0),  
428 - end: Offset.zero,  
429 - ).animate(animation),  
430 - child: FadeTransition(  
431 - opacity: animation,  
432 - child: SlideTransition(  
433 - position: Tween<Offset>(  
434 - begin: Offset.zero,  
435 - end: const Offset(1.0, 0.0),  
436 - ).animate(secondaryAnimation),  
437 - child: popGesture  
438 - ? _CupertinoBackGestureDetector<T>(  
439 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
440 - onStartPopGesture: () => _startPopGesture<T>(route),  
441 - child: child)  
442 - : child),  
443 - ), 138 + controller: route.controller,
444 ); 139 );
445 - break;  
446 - case Transition.cupertino:  
447 - return CupertinoPageTransition(  
448 - primaryRouteAnimation: animation,  
449 - secondaryRouteAnimation: secondaryAnimation,  
450 - // Check if the route has an animation that's currently participating  
451 - // in a back swipe gesture.  
452 - //  
453 - // In the middle of a back gesture drag, let the transition be linear to  
454 - // match finger motions.  
455 - linearTransition: isPopGestureInProgress(route),  
456 - child: _CupertinoBackGestureDetector<T>(  
457 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
458 - onStartPopGesture: () => _startPopGesture<T>(route),  
459 - child: child,  
460 - ),  
461 - );  
462 - break;  
463 - default:  
464 - return CupertinoPageTransition(  
465 - primaryRouteAnimation: animation,  
466 - secondaryRouteAnimation: secondaryAnimation,  
467 - // Check if the route has an animation that's currently participating  
468 - // in a back swipe gesture.  
469 - //  
470 - // In the middle of a back gesture drag, let the transition be linear to  
471 - // match finger motions.  
472 - linearTransition: isPopGestureInProgress(route),  
473 - child: popGesture  
474 - ? _CupertinoBackGestureDetector<T>(  
475 - enabledCallback: () => _isPopGestureEnabled<T>(route),  
476 - onStartPopGesture: () => _startPopGesture<T>(route),  
477 - child: child)  
478 - : child,  
479 - );  
480 - }  
481 - }  
482 } 140 }
483 141
484 - @override  
485 - Widget buildTransitions(BuildContext context, Animation<double> animation,  
486 - Animation<double> secondaryAnimation, Widget child) {  
487 - if (customBuildPageTransitions != null) {  
488 - return customBuildPageTransitions;  
489 - } else {  
490 - return buildPageTransitions<T>(  
491 - this,  
492 - context,  
493 - popGesture ?? GetPlatform.isIOS,  
494 - animation,  
495 - secondaryAnimation,  
496 - child,  
497 - transition,  
498 - curve,  
499 - alignment);  
500 - } 142 + static bool isPopGestureInProgress(PageRoute<dynamic> route) {
  143 + return route.navigator.userGestureInProgress;
501 } 144 }
502 145
503 - @override  
504 - String get debugLabel => '${super.debugLabel}(${settings.name})'; 146 + bool get popGestureInProgress => isPopGestureInProgress(this);
505 } 147 }
506 148
  149 +const double _kBackGestureWidth = 20.0;
  150 +const double _kMinFlingVelocity = 1.0;
  151 +const int _kMaxDroppedSwipePageForwardAnimationTime = 800; // Milliseconds.
  152 +
  153 +// The maximum time for a page to get reset to it's original position if the
  154 +// user releases a page mid swipe.
  155 +const int _kMaxPageBackAnimationTime = 300;
  156 +
507 class _CupertinoBackGestureDetector<T> extends StatefulWidget { 157 class _CupertinoBackGestureDetector<T> extends StatefulWidget {
508 const _CupertinoBackGestureDetector({ 158 const _CupertinoBackGestureDetector({
509 Key key, 159 Key key,
@@ -655,10 +305,11 @@ class _CupertinoBackGestureController<T> { @@ -655,10 +305,11 @@ class _CupertinoBackGestureController<T> {
655 // If the user releases the page before mid screen with sufficient velocity, 305 // If the user releases the page before mid screen with sufficient velocity,
656 // or after mid screen, we should animate the page out. Otherwise, the page 306 // or after mid screen, we should animate the page out. Otherwise, the page
657 // should be animated back in. 307 // should be animated back in.
658 - if (velocity.abs() >= _kMinFlingVelocity) 308 + if (velocity.abs() >= _kMinFlingVelocity) {
659 animateForward = velocity <= 0; 309 animateForward = velocity <= 0;
660 - else 310 + } else {
661 animateForward = controller.value > 0.5; 311 animateForward = controller.value > 0.5;
  312 + }
662 313
663 if (animateForward) { 314 if (animateForward) {
664 // The closer the panel is to dismissing, the shorter the animation is. 315 // The closer the panel is to dismissing, the shorter the animation is.
@@ -704,3 +355,655 @@ class _CupertinoBackGestureController<T> { @@ -704,3 +355,655 @@ class _CupertinoBackGestureController<T> {
704 } 355 }
705 } 356 }
706 } 357 }
  358 +
  359 +// import 'package:flutter/cupertino.dart';
  360 +// import 'package:flutter/foundation.dart';
  361 +// import 'package:flutter/gestures.dart';
  362 +// import 'package:flutter/material.dart';
  363 +// import 'package:get/src/get_main.dart';
  364 +// import 'package:get/src/routes/bindings_interface.dart';
  365 +
  366 +// import '../platform/platform.dart';
  367 +// import 'transitions_type.dart';
  368 +
  369 +// const double _kBackGestureWidth = 20.0;
  370 +// const double _kMinFlingVelocity = 1.0;
  371 +// const int _kMaxDroppedSwipePageForwardAnimationTime = 800; // Milliseconds.
  372 +
  373 +// // The maximum time for a page to get reset to it's original position if the
  374 +// // user releases a page mid swipe.
  375 +// const int _kMaxPageBackAnimationTime = 300;
  376 +
  377 +// class GetPageRoute<T> extends PageRoute<T> {
  378 +// /// The [builder], [maintainState], and [fullscreenDialog] arguments must not
  379 +// /// be null.
  380 +// GetPageRoute({
  381 +// @required this.page,
  382 +// this.title,
  383 +// RouteSettings settings,
  384 +// this.maintainState = true,
  385 +// this.curve = Curves.linear,
  386 +// this.alignment,
  387 +// this.parameter,
  388 +// this.binding,
  389 +// this.route,
  390 +// this.bindings,
  391 +// this.customBuildPageTransitions,
  392 +// this.opaque = true,
  393 +// this.transitionDuration = const Duration(milliseconds: 400),
  394 +// this.popGesture,
  395 +// this.transition,
  396 +// // this.duration = const Duration(milliseconds: 400),
  397 +// bool fullscreenDialog = false,
  398 +// }) : // assert(page != null),
  399 +// assert(maintainState != null),
  400 +// assert(fullscreenDialog != null),
  401 +// // assert(opaque),
  402 +// super(settings: settings, fullscreenDialog: fullscreenDialog) {
  403 +// /// prebuild dependencies
  404 +// if (binding != null) {
  405 +// binding.dependencies();
  406 +// }
  407 +// if (bindings != null) {
  408 +// bindings.forEach((element) => element.dependencies());
  409 +// }
  410 +// }
  411 +
  412 +// /// Builds the primary contents of the route.
  413 +// final Widget page;
  414 +
  415 +// final GetPageBuilder route;
  416 +
  417 +// final Widget customBuildPageTransitions;
  418 +
  419 +// final bool popGesture;
  420 +
  421 +// final Bindings binding;
  422 +
  423 +// final List<Bindings> bindings;
  424 +
  425 +// // final Duration duration;
  426 +
  427 +// final Map<String, String> parameter;
  428 +
  429 +// final String title;
  430 +
  431 +// final Transition transition;
  432 +
  433 +// final Curve curve;
  434 +
  435 +// final Alignment alignment;
  436 +
  437 +// ValueNotifier<String> _previousTitle;
  438 +
  439 +// /// The title string of the previous [GetRoute].
  440 +// ///
  441 +// /// The [ValueListenable]'s value is readable after the route is installed
  442 +// /// onto a [Navigator]. The [ValueListenable] will also notify its listeners
  443 +// /// if the value changes (such as by replacing the previous route).
  444 +// ///
  445 +// /// The [ValueListenable] itself will be null before the route is installed.
  446 +// /// Its content value will be null if the previous route has no title or
  447 +// /// is not a [GetRoute].
  448 +// ///
  449 +// /// See also:
  450 +// ///
  451 +// /// * [ValueListenableBuilder], which can be used to listen and rebuild
  452 +// /// widgets based on a ValueListenable.
  453 +// ValueListenable<String> get previousTitle {
  454 +// assert(
  455 +// _previousTitle != null,
  456 +// 'Cannot read the previousTitle for a route that has not yet been installed',
  457 +// );
  458 +// return _previousTitle;
  459 +// }
  460 +
  461 +// @override
  462 +// void didChangePrevious(Route<dynamic> previousRoute) {
  463 +// final String previousTitleString =
  464 +// previousRoute is GetPageRoute ? previousRoute.title : null;
  465 +// if (_previousTitle == null) {
  466 +// _previousTitle = ValueNotifier<String>(previousTitleString);
  467 +// } else {
  468 +// _previousTitle.value = previousTitleString;
  469 +// }
  470 +// super.didChangePrevious(previousRoute);
  471 +// }
  472 +
  473 +// @override
  474 +// final bool maintainState;
  475 +
  476 +// /// Allows you to set opaque to false to prevent route reconstruction.
  477 +// @override
  478 +// final bool opaque;
  479 +
  480 +// @override
  481 +// final Duration transitionDuration;
  482 +
  483 +// @override
  484 +// Color get barrierColor => null; //Color(0x00FFFFFF);
  485 +
  486 +// @override
  487 +// String get barrierLabel => null;
  488 +
  489 +// @override
  490 +// bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
  491 +// // Don't perform outgoing animation if the next route is a fullscreen dialog.
  492 +// return nextRoute is GetPageRoute && !nextRoute.fullscreenDialog;
  493 +// }
  494 +
  495 +// /// True if an iOS-style back swipe pop gesture is currently underway for [route].
  496 +// ///
  497 +// /// This just check the route's [NavigatorState.userGestureInProgress].
  498 +// ///
  499 +// /// See also:
  500 +// ///
  501 +// /// * [popGestureEnabled], which returns true if a user-triggered pop gesture
  502 +// /// would be allowed.
  503 +// static bool isPopGestureInProgress(PageRoute<dynamic> route) {
  504 +// return route.navigator.userGestureInProgress;
  505 +// }
  506 +
  507 +// /// True if an iOS-style back swipe pop gesture is currently underway for this route.
  508 +// ///
  509 +// /// See also:
  510 +// ///
  511 +// /// * [isPopGestureInProgress], which returns true if a Cupertino pop gesture
  512 +// /// is currently underway for specific route.
  513 +// /// * [popGestureEnabled], which returns true if a user-triggered pop gesture
  514 +// /// would be allowed.
  515 +// bool get popGestureInProgress => isPopGestureInProgress(this);
  516 +
  517 +// /// Whether a pop gesture can be started by the user.
  518 +// ///
  519 +// /// Returns true if the user can edge-swipe to a previous route.
  520 +// ///
  521 +// /// Returns false once [isPopGestureInProgress] is true, but
  522 +// /// [isPopGestureInProgress] can only become true if [popGestureEnabled] was
  523 +// /// true first.
  524 +// ///
  525 +// /// This should only be used between frames, not during build.
  526 +// bool get popGestureEnabled => _isPopGestureEnabled(this);
  527 +
  528 +// static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
  529 +// // If there's nothing to go back to, then obviously we don't support
  530 +// // the back gesture.
  531 +// if (route.isFirst) return false;
  532 +// // If the route wouldn't actually pop if we popped it, then the gesture
  533 +// // would be really confusing (or would skip internal routes), so disallow it.
  534 +// if (route.willHandlePopInternally) return false;
  535 +// // If attempts to dismiss this route might be vetoed such as in a page
  536 +// // with forms, then do not allow the user to dismiss the route with a swipe.
  537 +// if (route.hasScopedWillPopCallback) return false;
  538 +// // Fullscreen dialogs aren't dismissible by back swipe.
  539 +// if (route.fullscreenDialog) return false;
  540 +// // If we're in an animation already, we cannot be manually swiped.
  541 +// if (route.animation.status != AnimationStatus.completed) return false;
  542 +// // If we're being popped into, we also cannot be swiped until the pop above
  543 +// // it completes. This translates to our secondary animation being
  544 +// // dismissed.
  545 +// if (route.secondaryAnimation.status != AnimationStatus.dismissed)
  546 +// return false;
  547 +// // If we're in a gesture already, we cannot start another.
  548 +// if (isPopGestureInProgress(route)) return false;
  549 +
  550 +// // Looks like a back gesture would be welcome!
  551 +// return true;
  552 +// }
  553 +
  554 +// @override
  555 +// Widget buildPage(BuildContext context, Animation<double> animation,
  556 +// Animation<double> secondaryAnimation) {
  557 +// final Widget result = Semantics(
  558 +// scopesRoute: true,
  559 +// explicitChildNodes: true,
  560 +// child: (route == null ? page : route()),
  561 +// );
  562 +// assert(() {
  563 +// if (route == null && page == null) {
  564 +// throw FlutterError.fromParts(<DiagnosticsNode>[
  565 +// ErrorSummary(
  566 +// 'The builder for route "${settings.name}" returned null.'),
  567 +// ErrorDescription('Route builders must never return null.'),
  568 +// ]);
  569 +// }
  570 +// return true;
  571 +// }());
  572 +// return result;
  573 +// }
  574 +
  575 +// // Called by _CupertinoBackGestureDetector when a pop ("back") drag start
  576 +// // gesture is detected. The returned controller handles all of the subsequent
  577 +// // drag events.
  578 +// static _CupertinoBackGestureController<T> _startPopGesture<T>(
  579 +// PageRoute<T> route) {
  580 +// assert(_isPopGestureEnabled(route));
  581 +
  582 +// return _CupertinoBackGestureController<T>(
  583 +// navigator: route.navigator,
  584 +// controller: route.controller, // protected access
  585 +// );
  586 +// }
  587 +
  588 +// /// Returns a [CupertinoFullscreenDialogTransition] if [route] is a full
  589 +// /// screen dialog, otherwise a [CupertinoPageTransition] is returned.
  590 +// ///
  591 +// /// Used by [GetRoute.buildTransitions].
  592 +// ///
  593 +// /// This method can be applied to any [PageRoute], not just
  594 +// /// [GetRoute]. It's typically used to provide a Cupertino style
  595 +// /// horizontal transition for material widgets when the target platform
  596 +// /// is [TargetPlatform.iOS].
  597 +// ///
  598 +// /// See also:
  599 +// ///
  600 +// /// * [CupertinoPageTransitionsBuilder], which uses this method to define a
  601 +// /// [PageTransitionsBuilder] for the [PageTransitionsTheme].
  602 +// Widget buildPageTransitions<T>(
  603 +// PageRoute<T> route,
  604 +// BuildContext context,
  605 +// bool popGesture,
  606 +// Animation<double> animation,
  607 +// Animation<double> secondaryAnimation,
  608 +// Widget child,
  609 +// Transition tr,
  610 +// Curve curve,
  611 +// Alignment alignment,
  612 +// ) {
  613 +// Transition transition = (tr ?? Get.defaultTransition);
  614 +
  615 +// if (route.fullscreenDialog) {
  616 +// final bool linearTransition = isPopGestureInProgress(route);
  617 +// return CupertinoFullscreenDialogTransition(
  618 +// primaryRouteAnimation: animation,
  619 +// secondaryRouteAnimation: secondaryAnimation,
  620 +// child: child,
  621 +// linearTransition: linearTransition,
  622 +// );
  623 +// } else {
  624 +// switch (transition) {
  625 +// case Transition.fade:
  626 +// final PageTransitionsBuilder matchingBuilder =
  627 +// FadeUpwardsPageTransitionsBuilder();
  628 +// return matchingBuilder.buildTransitions<T>(
  629 +// route,
  630 +// context,
  631 +// animation,
  632 +// secondaryAnimation,
  633 +// popGesture
  634 +// ? _CupertinoBackGestureDetector<T>(
  635 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  636 +// onStartPopGesture: () => _startPopGesture<T>(route),
  637 +// child: child)
  638 +// : child);
  639 +// break;
  640 +// case Transition.rightToLeft:
  641 +// return SlideTransition(
  642 +// transformHitTests: false,
  643 +// position: new Tween<Offset>(
  644 +// begin: const Offset(1.0, 0.0),
  645 +// end: Offset.zero,
  646 +// ).animate(animation),
  647 +// child: new SlideTransition(
  648 +// position: new Tween<Offset>(
  649 +// begin: Offset.zero,
  650 +// end: const Offset(-1.0, 0.0),
  651 +// ).animate(secondaryAnimation),
  652 +// child: popGesture
  653 +// ? _CupertinoBackGestureDetector<T>(
  654 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  655 +// onStartPopGesture: () => _startPopGesture<T>(route),
  656 +// child: child)
  657 +// : child),
  658 +// );
  659 +// break;
  660 +// case Transition.leftToRight:
  661 +// return SlideTransition(
  662 +// transformHitTests: false,
  663 +// position: Tween<Offset>(
  664 +// begin: const Offset(-1.0, 0.0),
  665 +// end: Offset.zero,
  666 +// ).animate(animation),
  667 +// child: new SlideTransition(
  668 +// position: new Tween<Offset>(
  669 +// begin: Offset.zero,
  670 +// end: const Offset(1.0, 0.0),
  671 +// ).animate(secondaryAnimation),
  672 +// child: popGesture
  673 +// ? _CupertinoBackGestureDetector<T>(
  674 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  675 +// onStartPopGesture: () => _startPopGesture<T>(route),
  676 +// child: child)
  677 +// : child),
  678 +// );
  679 +// break;
  680 +// case Transition.upToDown:
  681 +// return SlideTransition(
  682 +// transformHitTests: false,
  683 +// position: Tween<Offset>(
  684 +// begin: const Offset(0.0, -1.0),
  685 +// end: Offset.zero,
  686 +// ).animate(animation),
  687 +// child: new SlideTransition(
  688 +// position: new Tween<Offset>(
  689 +// begin: Offset.zero,
  690 +// end: const Offset(0.0, 1.0),
  691 +// ).animate(secondaryAnimation),
  692 +// child: popGesture
  693 +// ? _CupertinoBackGestureDetector<T>(
  694 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  695 +// onStartPopGesture: () => _startPopGesture<T>(route),
  696 +// child: child)
  697 +// : child),
  698 +// );
  699 +// break;
  700 +// case Transition.downToUp:
  701 +// return SlideTransition(
  702 +// transformHitTests: false,
  703 +// position: Tween<Offset>(
  704 +// begin: const Offset(0.0, 1.0),
  705 +// end: Offset.zero,
  706 +// ).animate(animation),
  707 +// child: new SlideTransition(
  708 +// position: new Tween<Offset>(
  709 +// begin: Offset.zero,
  710 +// end: const Offset(0.0, -1.0),
  711 +// ).animate(secondaryAnimation),
  712 +// child: popGesture
  713 +// ? _CupertinoBackGestureDetector<T>(
  714 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  715 +// onStartPopGesture: () => _startPopGesture<T>(route),
  716 +// child: child)
  717 +// : child),
  718 +// );
  719 +// break;
  720 +
  721 +// case Transition.rightToLeftWithFade:
  722 +// return SlideTransition(
  723 +// position: Tween<Offset>(
  724 +// begin: const Offset(1.0, 0.0),
  725 +// end: Offset.zero,
  726 +// ).animate(animation),
  727 +// child: FadeTransition(
  728 +// opacity: animation,
  729 +// child: SlideTransition(
  730 +// position: Tween<Offset>(
  731 +// begin: Offset.zero,
  732 +// end: const Offset(-1.0, 0.0),
  733 +// ).animate(secondaryAnimation),
  734 +// child: popGesture
  735 +// ? _CupertinoBackGestureDetector<T>(
  736 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  737 +// onStartPopGesture: () => _startPopGesture<T>(route),
  738 +// child: child)
  739 +// : child),
  740 +// ),
  741 +// );
  742 +// break;
  743 +// case Transition.leftToRightWithFade:
  744 +// return SlideTransition(
  745 +// position: Tween<Offset>(
  746 +// begin: const Offset(-1.0, 0.0),
  747 +// end: Offset.zero,
  748 +// ).animate(animation),
  749 +// child: FadeTransition(
  750 +// opacity: animation,
  751 +// child: SlideTransition(
  752 +// position: Tween<Offset>(
  753 +// begin: Offset.zero,
  754 +// end: const Offset(1.0, 0.0),
  755 +// ).animate(secondaryAnimation),
  756 +// child: popGesture
  757 +// ? _CupertinoBackGestureDetector<T>(
  758 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  759 +// onStartPopGesture: () => _startPopGesture<T>(route),
  760 +// child: child)
  761 +// : child),
  762 +// ),
  763 +// );
  764 +// break;
  765 +
  766 +// default:
  767 +// return CupertinoPageTransition(
  768 +// primaryRouteAnimation: animation,
  769 +// secondaryRouteAnimation: secondaryAnimation,
  770 +// // Check if the route has an animation that's currently participating
  771 +// // in a back swipe gesture.
  772 +// //
  773 +// // In the middle of a back gesture drag, let the transition be linear to
  774 +// // match finger motions.
  775 +// linearTransition: isPopGestureInProgress(route),
  776 +// child: popGesture
  777 +// ? _CupertinoBackGestureDetector<T>(
  778 +// enabledCallback: () => _isPopGestureEnabled<T>(route),
  779 +// onStartPopGesture: () => _startPopGesture<T>(route),
  780 +// child: child)
  781 +// : child,
  782 +// );
  783 +// }
  784 +// }
  785 +// }
  786 +
  787 +// @override
  788 +// Widget buildTransitions(BuildContext context, Animation<double> animation,
  789 +// Animation<double> secondaryAnimation, Widget child) {
  790 +// if (customBuildPageTransitions != null) {
  791 +// return customBuildPageTransitions;
  792 +// } else {
  793 +// return buildPageTransitions<T>(
  794 +// this,
  795 +// context,
  796 +// popGesture ?? GetPlatform.isIOS,
  797 +// animation,
  798 +// secondaryAnimation,
  799 +// child,
  800 +// transition,
  801 +// curve,
  802 +// alignment);
  803 +// }
  804 +// }
  805 +
  806 +// @override
  807 +// String get debugLabel => '${super.debugLabel}(${settings.name})';
  808 +// }
  809 +
  810 +// class _CupertinoBackGestureDetector<T> extends StatefulWidget {
  811 +// const _CupertinoBackGestureDetector({
  812 +// Key key,
  813 +// @required this.enabledCallback,
  814 +// @required this.onStartPopGesture,
  815 +// @required this.child,
  816 +// }) : assert(enabledCallback != null),
  817 +// assert(onStartPopGesture != null),
  818 +// assert(child != null),
  819 +// super(key: key);
  820 +
  821 +// final Widget child;
  822 +
  823 +// final ValueGetter<bool> enabledCallback;
  824 +
  825 +// final ValueGetter<_CupertinoBackGestureController<T>> onStartPopGesture;
  826 +
  827 +// @override
  828 +// _CupertinoBackGestureDetectorState<T> createState() =>
  829 +// _CupertinoBackGestureDetectorState<T>();
  830 +// }
  831 +
  832 +// class _CupertinoBackGestureDetectorState<T>
  833 +// extends State<_CupertinoBackGestureDetector<T>> {
  834 +// _CupertinoBackGestureController<T> _backGestureController;
  835 +
  836 +// HorizontalDragGestureRecognizer _recognizer;
  837 +
  838 +// @override
  839 +// void initState() {
  840 +// super.initState();
  841 +// _recognizer = HorizontalDragGestureRecognizer(debugOwner: this)
  842 +// ..onStart = _handleDragStart
  843 +// ..onUpdate = _handleDragUpdate
  844 +// ..onEnd = _handleDragEnd
  845 +// ..onCancel = _handleDragCancel;
  846 +// }
  847 +
  848 +// @override
  849 +// void dispose() {
  850 +// _recognizer.dispose();
  851 +// super.dispose();
  852 +// }
  853 +
  854 +// void _handleDragStart(DragStartDetails details) {
  855 +// assert(mounted);
  856 +// assert(_backGestureController == null);
  857 +// _backGestureController = widget.onStartPopGesture();
  858 +// }
  859 +
  860 +// void _handleDragUpdate(DragUpdateDetails details) {
  861 +// assert(mounted);
  862 +// assert(_backGestureController != null);
  863 +// _backGestureController.dragUpdate(
  864 +// _convertToLogical(details.primaryDelta / context.size.width));
  865 +// }
  866 +
  867 +// void _handleDragEnd(DragEndDetails details) {
  868 +// assert(mounted);
  869 +// assert(_backGestureController != null);
  870 +// _backGestureController.dragEnd(_convertToLogical(
  871 +// details.velocity.pixelsPerSecond.dx / context.size.width));
  872 +// _backGestureController = null;
  873 +// }
  874 +
  875 +// void _handleDragCancel() {
  876 +// assert(mounted);
  877 +// // This can be called even if start is not called, paired with the "down" event
  878 +// // that we don't consider here.
  879 +// _backGestureController?.dragEnd(0.0);
  880 +// _backGestureController = null;
  881 +// }
  882 +
  883 +// void _handlePointerDown(PointerDownEvent event) {
  884 +// if (widget.enabledCallback()) _recognizer.addPointer(event);
  885 +// }
  886 +
  887 +// double _convertToLogical(double value) {
  888 +// switch (Directionality.of(context)) {
  889 +// case TextDirection.rtl:
  890 +// return -value;
  891 +// case TextDirection.ltr:
  892 +// return value;
  893 +// }
  894 +// return null;
  895 +// }
  896 +
  897 +// @override
  898 +// Widget build(BuildContext context) {
  899 +// assert(debugCheckHasDirectionality(context));
  900 +// // For devices with notches, the drag area needs to be larger on the side
  901 +// // that has the notch.
  902 +// double dragAreaWidth = Directionality.of(context) == TextDirection.ltr
  903 +// ? MediaQuery.of(context).padding.left
  904 +// : MediaQuery.of(context).padding.right;
  905 +// dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
  906 +// return Stack(
  907 +// fit: StackFit.passthrough,
  908 +// children: <Widget>[
  909 +// widget.child,
  910 +// PositionedDirectional(
  911 +// start: 0.0,
  912 +// width: dragAreaWidth,
  913 +// top: 0.0,
  914 +// bottom: 0.0,
  915 +// child: Listener(
  916 +// onPointerDown: _handlePointerDown,
  917 +// behavior: HitTestBehavior.translucent,
  918 +// ),
  919 +// ),
  920 +// ],
  921 +// );
  922 +// }
  923 +// }
  924 +
  925 +// class _CupertinoBackGestureController<T> {
  926 +// /// Creates a controller for an iOS-style back gesture.
  927 +// ///
  928 +// /// The [navigator] and [controller] arguments must not be null.
  929 +// _CupertinoBackGestureController({
  930 +// @required this.navigator,
  931 +// @required this.controller,
  932 +// }) : assert(navigator != null),
  933 +// assert(controller != null) {
  934 +// navigator.didStartUserGesture();
  935 +// }
  936 +
  937 +// final AnimationController controller;
  938 +// final NavigatorState navigator;
  939 +
  940 +// /// The drag gesture has changed by [fractionalDelta]. The total range of the
  941 +// /// drag should be 0.0 to 1.0.
  942 +// void dragUpdate(double delta) {
  943 +// controller.value -= delta;
  944 +// }
  945 +
  946 +// /// The drag gesture has ended with a horizontal motion of
  947 +// /// [fractionalVelocity] as a fraction of screen width per second.
  948 +// void dragEnd(double velocity) {
  949 +// // Fling in the appropriate direction.
  950 +// // AnimationController.fling is guaranteed to
  951 +// // take at least one frame.
  952 +// //
  953 +// // This curve has been determined through rigorously eyeballing native iOS
  954 +// // animations.
  955 +// const Curve animationCurve = Curves.fastLinearToSlowEaseIn;
  956 +// bool animateForward;
  957 +
  958 +// // If the user releases the page before mid screen with sufficient velocity,
  959 +// // or after mid screen, we should animate the page out. Otherwise, the page
  960 +// // should be animated back in.
  961 +// if (velocity.abs() >= _kMinFlingVelocity)
  962 +// animateForward = velocity <= 0;
  963 +// else
  964 +// animateForward = controller.value > 0.5;
  965 +
  966 +// if (animateForward) {
  967 +// // The closer the panel is to dismissing, the shorter the animation is.
  968 +// // We want to cap the animation time, but we want to use a linear curve
  969 +// // to determine it.
  970 +// final int droppedPageForwardAnimationTime = min(
  971 +// lerpDouble(
  972 +// _kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)
  973 +// .floor(),
  974 +// _kMaxPageBackAnimationTime,
  975 +// );
  976 +// controller.animateTo(1.0,
  977 +// duration: Duration(milliseconds: droppedPageForwardAnimationTime),
  978 +// curve: animationCurve);
  979 +// } else {
  980 +// // This route is destined to pop at this point. Reuse navigator's pop.
  981 +// navigator.pop();
  982 +
  983 +// // The popping may have finished inline if already at the target destination.
  984 +// if (controller.isAnimating) {
  985 +// // Otherwise, use a custom popping animation duration and curve.
  986 +// final int droppedPageBackAnimationTime = lerpDouble(
  987 +// 0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)
  988 +// .floor();
  989 +// controller.animateBack(0.0,
  990 +// duration: Duration(milliseconds: droppedPageBackAnimationTime),
  991 +// curve: animationCurve);
  992 +// }
  993 +// }
  994 +
  995 +// if (controller.isAnimating) {
  996 +// // Keep the userGestureInProgress in true state so we don't change the
  997 +// // curve of the page transition mid-flight since CupertinoPageTransition
  998 +// // depends on userGestureInProgress.
  999 +// AnimationStatusListener animationStatusCallback;
  1000 +// animationStatusCallback = (AnimationStatus status) {
  1001 +// navigator.didStopUserGesture();
  1002 +// controller.removeStatusListener(animationStatusCallback);
  1003 +// };
  1004 +// controller.addStatusListener(animationStatusCallback);
  1005 +// } else {
  1006 +// navigator.didStopUserGesture();
  1007 +// }
  1008 +// }
  1009 +// }
  1 +import 'package:flutter/cupertino.dart';
  2 +import 'package:flutter/material.dart';
  3 +import 'transitions_component.dart';
  4 +
  5 +class LeftToRightFadeTransition extends TransitionInterface {
  6 + LeftToRightFadeTransition({
  7 + TransitionComponent transitionComponent,
  8 + }) : super(transitionComponent: transitionComponent);
  9 +
  10 + @override
  11 + Widget buildChildWithTransition(
  12 + BuildContext context,
  13 + Animation<double> animation,
  14 + Animation<double> secondaryAnimation,
  15 + Widget child) {
  16 + return SlideTransition(
  17 + position: Tween<Offset>(
  18 + begin: const Offset(-1.0, 0.0),
  19 + end: Offset.zero,
  20 + ).animate(animation),
  21 + child: FadeTransition(
  22 + opacity: animation,
  23 + child: SlideTransition(
  24 + position: Tween<Offset>(
  25 + begin: Offset.zero,
  26 + end: const Offset(1.0, 0.0),
  27 + ).animate(secondaryAnimation),
  28 + child: child),
  29 + ),
  30 + );
  31 + }
  32 +}
  33 +
  34 +class RightToLeftFadeTransition extends TransitionInterface {
  35 + RightToLeftFadeTransition({
  36 + TransitionComponent transitionComponent,
  37 + }) : super(transitionComponent: transitionComponent);
  38 +
  39 + @override
  40 + Widget buildChildWithTransition(
  41 + BuildContext context,
  42 + Animation<double> animation,
  43 + Animation<double> secondaryAnimation,
  44 + Widget child) {
  45 + return SlideTransition(
  46 + position: Tween<Offset>(
  47 + begin: const Offset(1.0, 0.0),
  48 + end: Offset.zero,
  49 + ).animate(animation),
  50 + child: FadeTransition(
  51 + opacity: animation,
  52 + child: SlideTransition(
  53 + position: Tween<Offset>(
  54 + begin: Offset.zero,
  55 + end: const Offset(-1.0, 0.0),
  56 + ).animate(secondaryAnimation),
  57 + child: child),
  58 + ),
  59 + );
  60 + }
  61 +}
  62 +
  63 +class NoTransition extends TransitionInterface {
  64 + NoTransition({
  65 + TransitionComponent transitionComponent,
  66 + }) : super(transitionComponent: transitionComponent);
  67 +
  68 + @override
  69 + Widget buildChildWithTransition(
  70 + BuildContext context,
  71 + Animation<double> animation,
  72 + Animation<double> secondaryAnimation,
  73 + Widget child) {
  74 + return transitionComponent.buildChildWithTransition(
  75 + context, animation, secondaryAnimation, child);
  76 + }
  77 +}
  78 +
  79 +class FadeInTransition extends TransitionInterface {
  80 + FadeInTransition({
  81 + TransitionComponent transitionComponent,
  82 + }) : super(transitionComponent: transitionComponent);
  83 +
  84 + @override
  85 + Widget buildChildWithTransition(
  86 + BuildContext context,
  87 + Animation<double> animation,
  88 + Animation<double> secondaryAnimation,
  89 + Widget child) {
  90 + return FadeTransition(
  91 + opacity: animation,
  92 + child: transitionComponent.buildChildWithTransition(
  93 + context, animation, secondaryAnimation, child),
  94 + );
  95 + }
  96 +}
  97 +
  98 +class SlideDownTransition extends TransitionInterface {
  99 + SlideDownTransition({
  100 + TransitionComponent transitionComponent,
  101 + }) : super(transitionComponent: transitionComponent);
  102 +
  103 + @override
  104 + Widget buildChildWithTransition(
  105 + BuildContext context,
  106 + Animation<double> animation,
  107 + Animation<double> secondaryAnimation,
  108 + Widget child) {
  109 + return SlideTransition(
  110 + position: Tween<Offset>(
  111 + begin: Offset(0.0, 1.0),
  112 + end: Offset.zero,
  113 + ).animate(animation),
  114 + child: transitionComponent.buildChildWithTransition(
  115 + context, animation, secondaryAnimation, child),
  116 + );
  117 + }
  118 +}
  119 +
  120 +class SlideLeftTransition extends TransitionInterface {
  121 + SlideLeftTransition({
  122 + TransitionComponent transitionComponent,
  123 + }) : super(transitionComponent: transitionComponent);
  124 +
  125 + @override
  126 + Widget buildChildWithTransition(
  127 + BuildContext context,
  128 + Animation<double> animation,
  129 + Animation<double> secondaryAnimation,
  130 + Widget child) {
  131 + return SlideTransition(
  132 + position: Tween<Offset>(
  133 + begin: Offset(-1.0, 0.0),
  134 + end: Offset.zero,
  135 + ).animate(animation),
  136 + child: transitionComponent.buildChildWithTransition(
  137 + context, animation, secondaryAnimation, child),
  138 + );
  139 + }
  140 +}
  141 +
  142 +class SlideRightTransition extends TransitionInterface {
  143 + SlideRightTransition({
  144 + TransitionComponent transitionComponent,
  145 + }) : super(transitionComponent: transitionComponent);
  146 +
  147 + @override
  148 + Widget buildChildWithTransition(
  149 + BuildContext context,
  150 + Animation<double> animation,
  151 + Animation<double> secondaryAnimation,
  152 + Widget child) {
  153 + return SlideTransition(
  154 + position: Tween<Offset>(
  155 + begin: Offset(1.0, 0.0),
  156 + end: Offset.zero,
  157 + ).animate(animation),
  158 + child: transitionComponent.buildChildWithTransition(
  159 + context, animation, secondaryAnimation, child),
  160 + );
  161 + }
  162 +}
  163 +
  164 +class SlideTopTransition extends TransitionInterface {
  165 + SlideTopTransition({
  166 + TransitionComponent transitionComponent,
  167 + }) : super(transitionComponent: transitionComponent);
  168 +
  169 + @override
  170 + Widget buildChildWithTransition(
  171 + BuildContext context,
  172 + Animation<double> animation,
  173 + Animation<double> secondaryAnimation,
  174 + Widget child) {
  175 + return SlideTransition(
  176 + position: Tween<Offset>(
  177 + begin: Offset(0.0, -1.0),
  178 + end: Offset.zero,
  179 + ).animate(animation),
  180 + child: transitionComponent.buildChildWithTransition(
  181 + context, animation, secondaryAnimation, child),
  182 + );
  183 + }
  184 +}
  185 +
  186 +class ZoomInTransition extends TransitionInterface {
  187 + ZoomInTransition({
  188 + TransitionComponent transitionComponent,
  189 + }) : super(transitionComponent: transitionComponent);
  190 +
  191 + @override
  192 + Widget buildChildWithTransition(
  193 + BuildContext context,
  194 + Animation<double> animation,
  195 + Animation<double> secondaryAnimation,
  196 + Widget child) {
  197 + return ScaleTransition(
  198 + scale: animation,
  199 + child: transitionComponent.buildChildWithTransition(
  200 + context, animation, secondaryAnimation, child),
  201 + );
  202 + }
  203 +}
  204 +
  205 +abstract class TransitionInterface implements TransitionComponent {
  206 + TransitionComponent transitionComponent;
  207 + TransitionInterface({this.transitionComponent});
  208 +}
@@ -2,47 +2,6 @@ import 'package:flutter/widgets.dart'; @@ -2,47 +2,6 @@ import 'package:flutter/widgets.dart';
2 import 'package:get/src/routes/bindings_interface.dart'; 2 import 'package:get/src/routes/bindings_interface.dart';
3 import 'transitions_type.dart'; 3 import 'transitions_type.dart';
4 4
5 -class GetRoute {  
6 - final Widget page;  
7 - final String name;  
8 - final bool popGesture;  
9 - final Map<String, String> parameter;  
10 - final String title;  
11 - final Transition transition;  
12 - final Curve curve;  
13 - final Alignment alignment;  
14 - final bool maintainState;  
15 - final GetPageBuilder route;  
16 - final bool opaque;  
17 - final Bindings binding;  
18 - final List<Bindings> bindings;  
19 - final Widget customTransition;  
20 - final Duration transitionDuration;  
21 - final bool fullscreenDialog;  
22 - final RouteSettings settings;  
23 -  
24 - const GetRoute({  
25 - @required this.page,  
26 - this.title,  
27 - this.name,  
28 - this.settings,  
29 - this.maintainState = true,  
30 - this.curve = Curves.linear,  
31 - this.alignment,  
32 - this.route,  
33 - this.parameter,  
34 - this.opaque = true,  
35 - this.transitionDuration = const Duration(milliseconds: 400),  
36 - this.popGesture,  
37 - this.binding,  
38 - this.bindings,  
39 - this.transition,  
40 - this.customTransition,  
41 - this.fullscreenDialog = false,  
42 - }) : assert(page != null),  
43 - assert(maintainState != null),  
44 - assert(fullscreenDialog != null);  
45 -}  
46 5
47 class GetPage { 6 class GetPage {
48 final String name; 7 final String name;
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +class TransitionComponent {
  4 + Widget buildChildWithTransition(
  5 + BuildContext context,
  6 + Animation<double> animation,
  7 + Animation<double> secondaryAnimation,
  8 + Widget child) {
  9 + return child;
  10 + }
  11 +}
  1 +import 'default_transitions.dart';
  2 +import 'transitions_component.dart';
  3 +import 'transitions_type.dart';
  4 +
  5 +class TransitionFilter {
  6 + static TransitionComponent newTransitionComponent(
  7 + Transition transition,
  8 + ) {
  9 + TransitionComponent transitionComponent = TransitionComponent();
  10 + switch (transition) {
  11 + case Transition.leftToRight:
  12 + return SlideLeftTransition(transitionComponent: transitionComponent);
  13 +
  14 + case Transition.downToUp:
  15 + return SlideDownTransition(transitionComponent: transitionComponent);
  16 +
  17 + case Transition.upToDown:
  18 + return SlideTopTransition(transitionComponent: transitionComponent);
  19 +
  20 + case Transition.rightToLeft:
  21 + return SlideRightTransition(transitionComponent: transitionComponent);
  22 +
  23 + case Transition.zoom:
  24 + return ZoomInTransition(transitionComponent: transitionComponent);
  25 +
  26 + case Transition.fadeIn:
  27 + return FadeInTransition(transitionComponent: transitionComponent);
  28 +
  29 + case Transition.rightToLeftWithFade:
  30 + return RightToLeftFadeTransition(
  31 + transitionComponent: transitionComponent);
  32 +
  33 + case Transition.leftToRightWithFade:
  34 + return LeftToRightFadeTransition(
  35 + transitionComponent: transitionComponent);
  36 + default:
  37 + return FadeInTransition(transitionComponent: transitionComponent);
  38 + }
  39 + }
  40 +}
@@ -2,17 +2,16 @@ import 'package:flutter/widgets.dart'; @@ -2,17 +2,16 @@ import 'package:flutter/widgets.dart';
2 2
3 enum Transition { 3 enum Transition {
4 fade, 4 fade,
  5 + fadeIn,
5 rightToLeft, 6 rightToLeft,
6 leftToRight, 7 leftToRight,
7 upToDown, 8 upToDown,
8 downToUp, 9 downToUp,
9 - scale,  
10 - rotate,  
11 - size,  
12 rightToLeftWithFade, 10 rightToLeftWithFade,
13 leftToRightWithFade, 11 leftToRightWithFade,
14 - cupertino,  
15 - custom 12 + zoom,
  13 + noTransition,
  14 + native
16 } 15 }
17 16
18 typedef GetPageBuilder = Widget Function(); 17 typedef GetPageBuilder = Widget Function();
1 -import 'package:flutter/material.dart';  
2 -  
3 -class ParseRoute {  
4 - final List<ParseRouteSplit> _routeSplits = <ParseRouteSplit>[];  
5 -  
6 - void addRoute(String routePath) {  
7 - String path = routePath;  
8 -  
9 - if (path == Navigator.defaultRouteName) {  
10 - var routeSplit = ParseRouteSplit(path, ParseRouteSplitType.component);  
11 - routeSplit.routes = [routePath];  
12 - _routeSplits.add(routeSplit);  
13 - return;  
14 - }  
15 - if (path.startsWith("/")) {  
16 - path = path.substring(1);  
17 - }  
18 - List<String> pathComponents = path.split('/');  
19 - ParseRouteSplit parent;  
20 - for (int i = 0; i < pathComponents.length; i++) {  
21 - String component = pathComponents[i];  
22 - ParseRouteSplit routeSplit = _routeSplitForComponent(component, parent);  
23 - if (routeSplit == null) {  
24 - ParseRouteSplitType type = _typeForComponent(component);  
25 - routeSplit = ParseRouteSplit(component, type);  
26 - routeSplit.parent = parent;  
27 - if (parent == null) {  
28 - _routeSplits.add(routeSplit);  
29 - } else {  
30 - parent.routeSplits.add(routeSplit);  
31 - }  
32 - }  
33 - if (i == pathComponents.length - 1) {  
34 - if (routeSplit.routes == null) {  
35 - routeSplit.routes = [routePath];  
36 - } else {  
37 - routeSplit.routes.add(routePath);  
38 - }  
39 - }  
40 - parent = routeSplit;  
41 - }  
42 - }  
43 -  
44 - AppRouteMatch split(String path) {  
45 - String usePath = path;  
46 - if (usePath.startsWith("/")) {  
47 - usePath = path.substring(1);  
48 - }  
49 - List<String> components = usePath.split("/");  
50 - if (path == Navigator.defaultRouteName) {  
51 - components = ["/"];  
52 - }  
53 -  
54 - Map<ParseRouteSplit, ParseRouteSplitMatch> routeSplitMatches =  
55 - <ParseRouteSplit, ParseRouteSplitMatch>{};  
56 - List<ParseRouteSplit> routeSplitsToCheck = _routeSplits;  
57 - for (String checkComponent in components) {  
58 - Map<ParseRouteSplit, ParseRouteSplitMatch> currentMatches =  
59 - <ParseRouteSplit, ParseRouteSplitMatch>{};  
60 - List<ParseRouteSplit> nextrouteSplits = <ParseRouteSplit>[];  
61 - for (ParseRouteSplit routeSplit in routeSplitsToCheck) {  
62 - String pathPart = checkComponent;  
63 - Map<String, String> queryMap = {};  
64 - if (checkComponent.contains("?") && !checkComponent.contains("=")) {  
65 - var splitParam = checkComponent.split("?");  
66 - pathPart = splitParam[0];  
67 - queryMap = {pathPart: splitParam[1]};  
68 - } else if (checkComponent.contains("?")) {  
69 - var splitParam = checkComponent.split("?");  
70 - var splitParam2 = splitParam[1].split("=");  
71 - if (!splitParam2[1].contains("&")) {  
72 - pathPart = splitParam[0];  
73 - queryMap = {splitParam2[0]: splitParam2[1]};  
74 - } else {  
75 - pathPart = splitParam[0];  
76 - final segunda = splitParam[1];  
77 - var other = segunda.split(RegExp(r"[&,=]"));  
78 - for (var i = 0; i < (other.length - 1); i++) {  
79 - bool impar = (i % 2 == 0);  
80 - if (impar) {  
81 - queryMap.addAll({other[0 + i]: other[1 + i]});  
82 - }  
83 - }  
84 - }  
85 - }  
86 - bool isMatch =  
87 - (routeSplit.part == pathPart || routeSplit.isParameter());  
88 - if (isMatch) {  
89 - ParseRouteSplitMatch parentMatch =  
90 - routeSplitMatches[routeSplit.parent];  
91 - ParseRouteSplitMatch match =  
92 - ParseRouteSplitMatch.fromMatch(parentMatch, routeSplit);  
93 - if (routeSplit.isParameter()) {  
94 - String paramKey = routeSplit.part.substring(1);  
95 - match.parameters[paramKey] = pathPart;  
96 - }  
97 - if (queryMap != null) {  
98 - match.parameters.addAll(queryMap);  
99 - }  
100 -  
101 - currentMatches[routeSplit] = match;  
102 - if (routeSplit.routeSplits != null) {  
103 - nextrouteSplits.addAll(routeSplit.routeSplits);  
104 - }  
105 - }  
106 - }  
107 - routeSplitMatches = currentMatches;  
108 - routeSplitsToCheck = nextrouteSplits;  
109 - if (currentMatches.values.length == 0) {  
110 - return null;  
111 - }  
112 - }  
113 - List<ParseRouteSplitMatch> matches = routeSplitMatches.values.toList();  
114 - if (matches.length > 0) {  
115 - ParseRouteSplitMatch match = matches.first;  
116 - ParseRouteSplit routeSplitToUse = match.routeSplit;  
117 -  
118 - if (routeSplitToUse != null &&  
119 - routeSplitToUse.routes != null &&  
120 - routeSplitToUse.routes.length > 0) {  
121 - AppRouteMatch routeMatch = AppRouteMatch();  
122 - routeMatch.parameters = match.parameters;  
123 - if (routeSplitToUse.isParameter()) {  
124 - routeMatch.route = match.routeSplit.parent.part;  
125 - } else {  
126 - routeMatch.route = match.routeSplit.part;  
127 - }  
128 - return routeMatch;  
129 - }  
130 - }  
131 - return null;  
132 - }  
133 -  
134 - ParseRouteSplit _routeSplitForComponent(  
135 - String component, ParseRouteSplit parent) {  
136 - List<ParseRouteSplit> routeSplits = _routeSplits;  
137 - if (parent != null) {  
138 - routeSplits = parent.routeSplits;  
139 - }  
140 - for (ParseRouteSplit routeSplit in routeSplits) {  
141 - if (routeSplit.part == component) {  
142 - return routeSplit;  
143 - }  
144 - }  
145 - return null;  
146 - }  
147 -  
148 - ParseRouteSplitType _typeForComponent(String component) {  
149 - ParseRouteSplitType type = ParseRouteSplitType.component;  
150 - if (_isParameterComponent(component)) {  
151 - type = ParseRouteSplitType.parameter;  
152 - }  
153 - return type;  
154 - }  
155 -  
156 - bool _isParameterComponent(String component) {  
157 - return component.startsWith(":");  
158 - }  
159 -}  
160 -  
161 -enum ParseRouteSplitType {  
162 - component,  
163 - parameter,  
164 -}  
165 -  
166 -class AppRouteMatch {  
167 - Map<String, String> parameters = <String, String>{};  
168 - String route = '/';  
169 -}  
170 -  
171 -class ParseRouteSplitMatch {  
172 - ParseRouteSplitMatch(this.routeSplit);  
173 -  
174 - ParseRouteSplitMatch.fromMatch(ParseRouteSplitMatch match, this.routeSplit) {  
175 - parameters = <String, String>{};  
176 - if (match != null) {  
177 - parameters.addAll(match.parameters);  
178 - }  
179 - }  
180 -  
181 - ParseRouteSplit routeSplit;  
182 - Map<String, String> parameters = <String, String>{};  
183 -}  
184 -  
185 -class ParseRouteSplit {  
186 - ParseRouteSplit(this.part, this.type);  
187 -  
188 - String part;  
189 - ParseRouteSplitType type;  
190 - List<String> routes = [];  
191 - List<ParseRouteSplit> routeSplits = <ParseRouteSplit>[];  
192 - ParseRouteSplit parent;  
193 -  
194 - bool isParameter() {  
195 - return type == ParseRouteSplitType.parameter;  
196 - }  
197 -}  
1 -typedef void ValueCallback<T>(T v); 1 +typedef ValueCallback<T> = Function(T v);
@@ -12,6 +12,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget { @@ -12,6 +12,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
12 final bool autoRemove; 12 final bool autoRemove;
13 final bool assignId; 13 final bool assignId;
14 final void Function(State state) initState, dispose, didChangeDependencies; 14 final void Function(State state) initState, dispose, didChangeDependencies;
  15 + final void Function(GetX oldWidget, State state) didUpdateWidget;
15 final T init; 16 final T init;
16 const GetX({ 17 const GetX({
17 this.builder, 18 this.builder,
@@ -22,6 +23,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget { @@ -22,6 +23,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
22 // this.stream, 23 // this.stream,
23 this.dispose, 24 this.dispose,
24 this.didChangeDependencies, 25 this.didChangeDependencies,
  26 + this.didUpdateWidget,
25 this.init, 27 this.init,
26 // this.streamController 28 // this.streamController
27 }); 29 });
@@ -66,6 +68,20 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> { @@ -66,6 +68,20 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
66 } 68 }
67 69
68 @override 70 @override
  71 + void didChangeDependencies() {
  72 + super.didChangeDependencies();
  73 + if (widget.didChangeDependencies != null) {
  74 + widget.didChangeDependencies(this);
  75 + }
  76 + }
  77 +
  78 + @override
  79 + void didUpdateWidget(GetX oldWidget) {
  80 + super.didUpdateWidget(oldWidget as GetX<T>);
  81 + if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
  82 + }
  83 +
  84 + @override
69 void dispose() { 85 void dispose() {
70 if (widget.dispose != null) widget.dispose(this); 86 if (widget.dispose != null) widget.dispose(this);
71 if (isCreator || widget.assignId) { 87 if (isCreator || widget.assignId) {
@@ -51,25 +51,26 @@ class _RxImpl<T> implements RxInterface<T> { @@ -51,25 +51,26 @@ class _RxImpl<T> implements RxInterface<T> {
51 Stream<R> map<R>(R mapper(T data)) => stream.map(mapper); 51 Stream<R> map<R>(R mapper(T data)) => stream.map(mapper);
52 } 52 }
53 53
54 -class StringX<String> extends _RxImpl<String> {  
55 - StringX([String initial]) { 54 +class RxString<String> extends _RxImpl<String> {
  55 + RxString([String initial]) {
56 _value = initial; 56 _value = initial;
57 } 57 }
58 } 58 }
59 59
60 -class IntX<int> extends _RxImpl<int> {  
61 - IntX([int initial]) { 60 +class RxInt<int> extends _RxImpl<int> {
  61 + RxInt([int initial]) {
62 _value = initial; 62 _value = initial;
63 } 63 }
64 } 64 }
65 65
66 -class MapX<K, V> extends RxInterface implements Map<K, V> {  
67 - MapX([Map<K, V> initial]) { 66 +class RxMap<K, V> extends RxInterface implements Map<K, V> {
  67 + RxMap([Map<K, V> initial]) {
68 _value = initial; 68 _value = initial;
69 } 69 }
70 70
  71 + @override
71 StreamController subject = StreamController<Map<K, V>>.broadcast(); 72 StreamController subject = StreamController<Map<K, V>>.broadcast();
72 - Map<Stream<Map<K, V>>, StreamSubscription> _subscriptions = Map(); 73 + final Map<Stream<Map<K, V>>, StreamSubscription> _subscriptions = {};
73 74
74 Map<K, V> _value; 75 Map<K, V> _value;
75 Map<K, V> get value { 76 Map<K, V> get value {
@@ -81,7 +82,8 @@ class MapX<K, V> extends RxInterface implements Map<K, V> { @@ -81,7 +82,8 @@ class MapX<K, V> extends RxInterface implements Map<K, V> {
81 82
82 String get string => value.toString(); 83 String get string => value.toString();
83 84
84 - close() { 85 + @override
  86 + void close() {
85 _subscriptions.forEach((observable, subscription) { 87 _subscriptions.forEach((observable, subscription) {
86 subscription.cancel(); 88 subscription.cancel();
87 }); 89 });
@@ -89,7 +91,8 @@ class MapX<K, V> extends RxInterface implements Map<K, V> { @@ -89,7 +91,8 @@ class MapX<K, V> extends RxInterface implements Map<K, V> {
89 subject.close(); 91 subject.close();
90 } 92 }
91 93
92 - addListener(Stream rxGetx) { 94 + @override
  95 + void addListener(Stream rxGetx) {
93 if (_subscriptions.containsKey(rxGetx)) { 96 if (_subscriptions.containsKey(rxGetx)) {
94 return; 97 return;
95 } 98 }
@@ -118,7 +121,7 @@ class MapX<K, V> extends RxInterface implements Map<K, V> { @@ -118,7 +121,7 @@ class MapX<K, V> extends RxInterface implements Map<K, V> {
118 subject.add(_value); 121 subject.add(_value);
119 } 122 }
120 123
121 - void addIf(/* bool | Condition */ condition, K key, V value) { 124 + void addIf(condition, K key, V value) {
122 if (condition is Condition) condition = condition(); 125 if (condition is Condition) condition = condition();
123 if (condition is bool && condition) { 126 if (condition is bool && condition) {
124 _value[key] = value; 127 _value[key] = value;
@@ -126,7 +129,7 @@ class MapX<K, V> extends RxInterface implements Map<K, V> { @@ -126,7 +129,7 @@ class MapX<K, V> extends RxInterface implements Map<K, V> {
126 } 129 }
127 } 130 }
128 131
129 - void addAllIf(/* bool | Condition */ condition, Map<K, V> values) { 132 + void addAllIf(condition, Map<K, V> values) {
130 if (condition is Condition) condition = condition(); 133 if (condition is Condition) condition = condition();
131 if (condition is bool && condition) addAll(values); 134 if (condition is bool && condition) addAll(values);
132 } 135 }
@@ -234,8 +237,8 @@ class MapX<K, V> extends RxInterface implements Map<K, V> { @@ -234,8 +237,8 @@ class MapX<K, V> extends RxInterface implements Map<K, V> {
234 } 237 }
235 238
236 /// Create a list similar to `List<T>` 239 /// Create a list similar to `List<T>`
237 -class ListX<E> extends Iterable<E> implements RxInterface<E> {  
238 - ListX([List<E> initial]) { 240 +class RxList<E> extends Iterable<E> implements RxInterface<E> {
  241 + RxList([List<E> initial]) {
239 _list = initial; 242 _list = initial;
240 } 243 }
241 244
@@ -411,20 +414,20 @@ typedef bool Condition(); @@ -411,20 +414,20 @@ typedef bool Condition();
411 414
412 typedef E ChildrenListComposer<S, E>(S value); 415 typedef E ChildrenListComposer<S, E>(S value);
413 416
414 -class BoolX<bool> extends _RxImpl<bool> {  
415 - BoolX([bool initial]) { 417 +class RxBool<bool> extends _RxImpl<bool> {
  418 + RxBool([bool initial]) {
416 _value = initial; 419 _value = initial;
417 } 420 }
418 } 421 }
419 422
420 -class DoubleX<double> extends _RxImpl<double> {  
421 - DoubleX([double initial]) { 423 +class RxDouble<double> extends _RxImpl<double> {
  424 + RxDouble([double initial]) {
422 _value = initial; 425 _value = initial;
423 } 426 }
424 } 427 }
425 428
426 -class NumX<num> extends _RxImpl<num> {  
427 - NumX([num initial]) { 429 +class RxNum<num> extends _RxImpl<num> {
  430 + RxNum([num initial]) {
428 _value = initial; 431 _value = initial;
429 } 432 }
430 } 433 }
@@ -436,36 +439,36 @@ class Rx<T> extends _RxImpl<T> { @@ -436,36 +439,36 @@ class Rx<T> extends _RxImpl<T> {
436 } 439 }
437 440
438 extension StringExtension on String { 441 extension StringExtension on String {
439 - StringX<String> get obs => StringX(this); 442 + RxString<String> get obs => RxString(this);
440 } 443 }
441 444
442 extension IntExtension on int { 445 extension IntExtension on int {
443 - IntX<int> get obs => IntX(this); 446 + RxInt<int> get obs => RxInt(this);
444 } 447 }
445 448
446 extension DoubleExtension on double { 449 extension DoubleExtension on double {
447 - DoubleX<double> get obs => DoubleX(this); 450 + RxDouble<double> get obs => RxDouble(this);
448 } 451 }
449 452
450 extension BoolExtension on bool { 453 extension BoolExtension on bool {
451 - BoolX<bool> get obs => BoolX(this); 454 + RxBool<bool> get obs => RxBool(this);
452 } 455 }
453 456
454 extension MapExtension<K, V> on Map<K, V> { 457 extension MapExtension<K, V> on Map<K, V> {
455 - MapX<K, V> get obs { 458 + RxMap<K, V> get obs {
456 if (this != null) 459 if (this != null)
457 - return MapX<K, V>({})..addAll(this); 460 + return RxMap<K, V>({})..addAll(this);
458 else 461 else
459 - return MapX<K, V>(null); 462 + return RxMap<K, V>(null);
460 } 463 }
461 } 464 }
462 465
463 extension ListExtension<E> on List<E> { 466 extension ListExtension<E> on List<E> {
464 - ListX<E> get obs { 467 + RxList<E> get obs {
465 if (this != null) 468 if (this != null)
466 - return ListX<E>([])..addAllNonNull(this); 469 + return RxList<E>([])..addAllNonNull(this);
467 else 470 else
468 - return ListX<E>(null); 471 + return RxList<E>(null);
469 } 472 }
470 } 473 }
471 474
@@ -25,17 +25,6 @@ abstract class RxInterface<T> { @@ -25,17 +25,6 @@ abstract class RxInterface<T> {
25 // Stream<S> map<S>(S mapper(T data)); 25 // Stream<S> map<S>(S mapper(T data));
26 } 26 }
27 27
28 -class RxController extends DisposableInterface {  
29 - @override  
30 - void onInit() async {}  
31 -  
32 - @override  
33 - void onReady() async {}  
34 -  
35 - @override  
36 - void onClose() async {}  
37 -}  
38 -  
39 abstract class DisposableInterface { 28 abstract class DisposableInterface {
40 /// Called at the exact moment that the widget is allocated in memory. 29 /// Called at the exact moment that the widget is allocated in memory.
41 /// Do not overwrite this method. 30 /// Do not overwrite this method.
1 -// import 'dart:async';  
2 -// import 'package:flutter/widgets.dart';  
3 -// import 'package:get/src/get_main.dart';  
4 -// import 'rx_impl.dart';  
5 -// import 'rx_interface.dart';  
6 -  
7 -// class ListViewX<T extends RxController> extends StatefulWidget {  
8 -// final Widget Function(T, int) builder;  
9 -// final bool global;  
10 -// final ListX Function(T) list;  
11 -// final bool autoRemove;  
12 -// final void Function(State state) initState, dispose, didChangeDependencies;  
13 -// final T init;  
14 -// final int itemCount;  
15 -// ListViewX({  
16 -// this.builder,  
17 -// this.global = true,  
18 -// this.autoRemove = true,  
19 -// this.initState,  
20 -// @required this.list,  
21 -// this.itemCount,  
22 -// this.dispose,  
23 -// this.didChangeDependencies,  
24 -// this.init,  
25 -// });  
26 -// _ListViewXState<T> createState() => _ListViewXState<T>();  
27 -// }  
28 -  
29 -// class _ListViewXState<T extends RxController> extends State<ListViewX<T>> {  
30 -// RxInterface _observer;  
31 -// StreamSubscription _listenSubscription;  
32 -// T controller;  
33 -  
34 -// _ListViewXState() {  
35 -// _observer = ListX();  
36 -// }  
37 -  
38 -// @override  
39 -// void initState() {  
40 -// if (widget.global) {  
41 -// if (Get.isRegistred<T>()) {  
42 -// controller = Get.find<T>();  
43 -// } else {  
44 -// controller = widget.init;  
45 -// Get.put<T>(controller);  
46 -// }  
47 -// } else {  
48 -// controller = widget.init;  
49 -// }  
50 -// if (widget.initState != null) widget.initState(this);  
51 -// try {  
52 -// controller?.onInit();  
53 -// } catch (e) {  
54 -// if (Get.isLogEnable) print("Failure on call onInit");  
55 -// }  
56 -  
57 -// _listenSubscription = widget.list.call(controller).listen((data) {  
58 -// setState(() {});  
59 -// });  
60 -// super.initState();  
61 -// }  
62 -  
63 -// @override  
64 -// void dispose() {  
65 -// controller?.onClose();  
66 -// _listenSubscription?.cancel();  
67 -// _observer?.close();  
68 -// super.dispose();  
69 -// }  
70 -  
71 -// @override  
72 -// Widget build(BuildContext context) {  
73 -// _observer.close();  
74 -// final observer = Get.obs;  
75 -// Get.obs = this._observer;  
76 -// final result = ListView.builder(  
77 -// itemCount: widget.itemCount ?? widget.list.call(controller).length,  
78 -// itemBuilder: (context, index) {  
79 -// return widget.builder(controller, index);  
80 -// });  
81 -// Get.obs = observer;  
82 -// return result;  
83 -// }  
84 -// }  
@@ -6,7 +6,7 @@ class Debouncer { @@ -6,7 +6,7 @@ class Debouncer {
6 6
7 Debouncer({this.delay}); 7 Debouncer({this.delay});
8 8
9 - call(Function action) { 9 + call(void Function() action) {
10 _timer?.cancel(); 10 _timer?.cancel();
11 _timer = Timer(delay, action); 11 _timer = Timer(delay, action);
12 } 12 }
1 -import 'dart:math' as math;  
2 -  
3 -class DelegatingList<E> extends DelegatingIterable<E> implements List<E> {  
4 - const DelegatingList(List<E> base) : super(base);  
5 -  
6 - List<E> get _listBase => _base;  
7 -  
8 - E operator [](int index) => _listBase[index];  
9 -  
10 - void operator []=(int index, E value) {  
11 - _listBase[index] = value;  
12 - }  
13 -  
14 - List<E> operator +(List<E> other) => _listBase + other;  
15 -  
16 - void add(E value) {  
17 - _listBase.add(value);  
18 - }  
19 -  
20 - void addAll(Iterable<E> iterable) {  
21 - _listBase.addAll(iterable);  
22 - }  
23 -  
24 - Map<int, E> asMap() => _listBase.asMap();  
25 -  
26 - List<T> cast<T>() => _listBase.cast<T>();  
27 -  
28 - void clear() {  
29 - _listBase.clear();  
30 - }  
31 -  
32 - void fillRange(int start, int end, [E fillValue]) {  
33 - _listBase.fillRange(start, end, fillValue);  
34 - }  
35 -  
36 - set first(E value) {  
37 - if (this.isEmpty) throw RangeError.index(0, this);  
38 - this[0] = value;  
39 - }  
40 -  
41 - Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end);  
42 -  
43 - int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start);  
44 -  
45 - int indexWhere(bool test(E element), [int start = 0]) =>  
46 - _listBase.indexWhere(test, start);  
47 -  
48 - void insert(int index, E element) {  
49 - _listBase.insert(index, element);  
50 - }  
51 -  
52 - insertAll(int index, Iterable<E> iterable) {  
53 - _listBase.insertAll(index, iterable);  
54 - }  
55 -  
56 - set last(E value) {  
57 - if (this.isEmpty) throw RangeError.index(0, this);  
58 - this[this.length - 1] = value;  
59 - }  
60 -  
61 - int lastIndexOf(E element, [int start]) =>  
62 - _listBase.lastIndexOf(element, start);  
63 -  
64 - int lastIndexWhere(bool test(E element), [int start]) =>  
65 - _listBase.lastIndexWhere(test, start);  
66 -  
67 - set length(int newLength) {  
68 - _listBase.length = newLength;  
69 - }  
70 -  
71 - bool remove(Object value) => _listBase.remove(value);  
72 -  
73 - E removeAt(int index) => _listBase.removeAt(index);  
74 -  
75 - E removeLast() => _listBase.removeLast();  
76 -  
77 - void removeRange(int start, int end) {  
78 - _listBase.removeRange(start, end);  
79 - }  
80 -  
81 - void removeWhere(bool test(E element)) {  
82 - _listBase.removeWhere(test);  
83 - }  
84 -  
85 - void replaceRange(int start, int end, Iterable<E> iterable) {  
86 - _listBase.replaceRange(start, end, iterable);  
87 - }  
88 -  
89 - void retainWhere(bool test(E element)) {  
90 - _listBase.retainWhere(test);  
91 - }  
92 -  
93 - @deprecated  
94 - List<T> retype<T>() => cast<T>();  
95 -  
96 - Iterable<E> get reversed => _listBase.reversed;  
97 -  
98 - void setAll(int index, Iterable<E> iterable) {  
99 - _listBase.setAll(index, iterable);  
100 - }  
101 -  
102 - void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {  
103 - _listBase.setRange(start, end, iterable, skipCount);  
104 - }  
105 -  
106 - void shuffle([math.Random random]) {  
107 - _listBase.shuffle(random);  
108 - }  
109 -  
110 - void sort([int compare(E a, E b)]) {  
111 - _listBase.sort(compare);  
112 - }  
113 -  
114 - List<E> sublist(int start, [int end]) => _listBase.sublist(start, end);  
115 -}  
116 -  
117 -class DelegatingIterable<E> extends _DelegatingIterableBase<E> {  
118 - final Iterable<E> _base;  
119 -  
120 - const DelegatingIterable(Iterable<E> base) : _base = base;  
121 -}  
122 -  
123 -abstract class _DelegatingIterableBase<E> implements Iterable<E> {  
124 - Iterable<E> get _base;  
125 -  
126 - const _DelegatingIterableBase();  
127 -  
128 - bool any(bool test(E element)) => _base.any(test);  
129 -  
130 - Iterable<T> cast<T>() => _base.cast<T>();  
131 -  
132 - bool contains(Object element) => _base.contains(element);  
133 -  
134 - E elementAt(int index) => _base.elementAt(index);  
135 -  
136 - bool every(bool test(E element)) => _base.every(test);  
137 -  
138 - Iterable<T> expand<T>(Iterable<T> f(E element)) => _base.expand(f);  
139 -  
140 - E get first => _base.first;  
141 -  
142 - E firstWhere(bool test(E element), {E orElse()}) =>  
143 - _base.firstWhere(test, orElse: orElse);  
144 -  
145 - T fold<T>(T initialValue, T combine(T previousValue, E element)) =>  
146 - _base.fold(initialValue, combine);  
147 -  
148 - Iterable<E> followedBy(Iterable<E> other) => _base.followedBy(other);  
149 -  
150 - void forEach(void f(E element)) => _base.forEach(f);  
151 -  
152 - bool get isEmpty => _base.isEmpty;  
153 -  
154 - bool get isNotEmpty => _base.isNotEmpty;  
155 -  
156 - Iterator<E> get iterator => _base.iterator;  
157 -  
158 - String join([String separator = ""]) => _base.join(separator);  
159 -  
160 - E get last => _base.last;  
161 -  
162 - E lastWhere(bool test(E element), {E orElse()}) =>  
163 - _base.lastWhere(test, orElse: orElse);  
164 -  
165 - int get length => _base.length;  
166 -  
167 - Iterable<T> map<T>(T f(E element)) => _base.map(f);  
168 -  
169 - E reduce(E combine(E value, E element)) => _base.reduce(combine);  
170 -  
171 - @deprecated  
172 - Iterable<T> retype<T>() => cast<T>();  
173 -  
174 - E get single => _base.single;  
175 -  
176 - E singleWhere(bool test(E element), {E orElse()}) {  
177 - return _base.singleWhere(test, orElse: orElse);  
178 - }  
179 -  
180 - Iterable<E> skip(int n) => _base.skip(n);  
181 -  
182 - Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test);  
183 -  
184 - Iterable<E> take(int n) => _base.take(n);  
185 -  
186 - Iterable<E> takeWhile(bool test(E value)) => _base.takeWhile(test);  
187 -  
188 - List<E> toList({bool growable = true}) => _base.toList(growable: growable);  
189 -  
190 - Set<E> toSet() => _base.toSet();  
191 -  
192 - Iterable<E> where(bool test(E element)) => _base.where(test);  
193 -  
194 - Iterable<T> whereType<T>() => _base.whereType<T>();  
195 -  
196 - String toString() => _base.toString();  
197 -}  
@@ -215,7 +215,7 @@ class GetBar<T extends Object> extends StatefulWidget { @@ -215,7 +215,7 @@ class GetBar<T extends Object> extends StatefulWidget {
215 Future<T> show() async { 215 Future<T> show() async {
216 _snackRoute = route.showSnack<T>( 216 _snackRoute = route.showSnack<T>(
217 snack: this, 217 snack: this,
218 - ); 218 + ) as SnackRoute<T>;
219 return await Get.key.currentState.push(_snackRoute); 219 return await Get.key.currentState.push(_snackRoute);
220 } 220 }
221 221
@@ -3,8 +3,8 @@ import 'package:get/src/get_instance.dart'; @@ -3,8 +3,8 @@ import 'package:get/src/get_instance.dart';
3 import 'package:get/src/root/smart_management.dart'; 3 import 'package:get/src/root/smart_management.dart';
4 import 'package:get/src/rx/rx_interface.dart'; 4 import 'package:get/src/rx/rx_interface.dart';
5 5
6 -class GetController extends DisposableInterface {  
7 - List<Updater> _updaters = []; 6 +class GetxController extends DisposableInterface {
  7 + final List<Updater> _updaters = [];
8 8
9 /// Update GetBuilder with update(); 9 /// Update GetBuilder with update();
10 void update([List<String> ids, bool condition = true]) { 10 void update([List<String> ids, bool condition = true]) {
@@ -18,15 +18,17 @@ class GetController extends DisposableInterface { @@ -18,15 +18,17 @@ class GetController extends DisposableInterface {
18 .forEach((rs) => rs.updater(() {})); 18 .forEach((rs) => rs.updater(() {}));
19 } 19 }
20 20
  21 + @override
21 void onInit() async {} 22 void onInit() async {}
22 23
  24 + @override
23 void onReady() async {} 25 void onReady() async {}
24 26
  27 + @override
25 void onClose() async {} 28 void onClose() async {}
26 } 29 }
27 30
28 -class GetBuilder<T extends GetController> extends StatefulWidget {  
29 - @required 31 +class GetBuilder<T extends GetxController> extends StatefulWidget {
30 final Widget Function(T) builder; 32 final Widget Function(T) builder;
31 final bool global; 33 final bool global;
32 final String id; 34 final String id;
@@ -40,7 +42,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget { @@ -40,7 +42,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget {
40 Key key, 42 Key key,
41 this.init, 43 this.init,
42 this.global = true, 44 this.global = true,
43 - this.builder, 45 + @required this.builder,
44 this.autoRemove = true, 46 this.autoRemove = true,
45 this.assignId = false, 47 this.assignId = false,
46 this.initState, 48 this.initState,
@@ -55,7 +57,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget { @@ -55,7 +57,7 @@ class GetBuilder<T extends GetController> extends StatefulWidget {
55 _GetBuilderState<T> createState() => _GetBuilderState<T>(); 57 _GetBuilderState<T> createState() => _GetBuilderState<T>();
56 } 58 }
57 59
58 -class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> { 60 +class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
59 T controller; 61 T controller;
60 Updater real; 62 Updater real;
61 bool isCreator = false; 63 bool isCreator = false;
@@ -64,8 +66,8 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> { @@ -64,8 +66,8 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> {
64 super.initState(); 66 super.initState();
65 67
66 if (widget.global) { 68 if (widget.global) {
67 - bool isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);  
68 - bool isRegistred = GetInstance().isRegistred<T>(tag: widget.tag); 69 + final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
  70 + final isRegistred = GetInstance().isRegistred<T>(tag: widget.tag);
69 71
70 if (isPrepared) { 72 if (isPrepared) {
71 if (GetConfig.smartManagement != SmartManagement.keepFactory) { 73 if (GetConfig.smartManagement != SmartManagement.keepFactory) {
@@ -116,13 +118,14 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> { @@ -116,13 +118,14 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> {
116 @override 118 @override
117 void didChangeDependencies() { 119 void didChangeDependencies() {
118 super.didChangeDependencies(); 120 super.didChangeDependencies();
119 - if (widget.didChangeDependencies != null) 121 + if (widget.didChangeDependencies != null) {
120 widget.didChangeDependencies(this); 122 widget.didChangeDependencies(this);
121 } 123 }
  124 + }
122 125
123 @override 126 @override
124 void didUpdateWidget(GetBuilder oldWidget) { 127 void didUpdateWidget(GetBuilder oldWidget) {
125 - super.didUpdateWidget(oldWidget); 128 + super.didUpdateWidget(oldWidget as GetBuilder<T>);
126 if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this); 129 if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
127 } 130 }
128 131
  1 +import 'package:flutter/widgets.dart';
  2 +import 'package:get/src/get_instance.dart';
  3 +
  4 +abstract class GetView<T> extends StatelessWidget {
  5 + const GetView({Key key}) : super(key: key);
  6 + T get controller => GetInstance().find();
  7 +
  8 + @override
  9 + Widget build(BuildContext context);
  10 +}
@@ -2,7 +2,7 @@ import 'package:flutter/widgets.dart'; @@ -2,7 +2,7 @@ import 'package:flutter/widgets.dart';
2 import 'package:get/src/rx/rx_obx.dart'; 2 import 'package:get/src/rx/rx_obx.dart';
3 import 'get_state.dart'; 3 import 'get_state.dart';
4 4
5 -class MixinBuilder<T extends GetController> extends StatelessWidget { 5 +class MixinBuilder<T extends GetxController> extends StatelessWidget {
6 @required 6 @required
7 final Widget Function(T) builder; 7 final Widget Function(T) builder;
8 final bool global; 8 final bool global;
@@ -15,6 +15,13 @@ packages: @@ -15,6 +15,13 @@ packages:
15 url: "https://pub.dartlang.org" 15 url: "https://pub.dartlang.org"
16 source: hosted 16 source: hosted
17 version: "2.0.0" 17 version: "2.0.0"
  18 + characters:
  19 + dependency: transitive
  20 + description:
  21 + name: characters
  22 + url: "https://pub.dartlang.org"
  23 + source: hosted
  24 + version: "1.0.0"
18 charcode: 25 charcode:
19 dependency: transitive 26 dependency: transitive
20 description: 27 description:
@@ -35,7 +42,7 @@ packages: @@ -35,7 +42,7 @@ packages:
35 name: collection 42 name: collection
36 url: "https://pub.dartlang.org" 43 url: "https://pub.dartlang.org"
37 source: hosted 44 source: hosted
38 - version: "1.14.12" 45 + version: "1.14.13"
39 fake_async: 46 fake_async:
40 dependency: transitive 47 dependency: transitive
41 description: 48 description:
@@ -59,7 +66,7 @@ packages: @@ -59,7 +66,7 @@ packages:
59 name: matcher 66 name: matcher
60 url: "https://pub.dartlang.org" 67 url: "https://pub.dartlang.org"
61 source: hosted 68 source: hosted
62 - version: "0.12.6" 69 + version: "0.12.8"
63 meta: 70 meta:
64 dependency: transitive 71 dependency: transitive
65 description: 72 description:
@@ -120,7 +127,7 @@ packages: @@ -120,7 +127,7 @@ packages:
120 name: test_api 127 name: test_api
121 url: "https://pub.dartlang.org" 128 url: "https://pub.dartlang.org"
122 source: hosted 129 source: hosted
123 - version: "0.2.16" 130 + version: "0.2.17"
124 typed_data: 131 typed_data:
125 dependency: transitive 132 dependency: transitive
126 description: 133 description:
1 name: get 1 name: get
2 description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get. 2 description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
3 -version: 2.14.0 3 +version: 3.0.1
4 homepage: https://github.com/jonataslaw/get 4 homepage: https://github.com/jonataslaw/get
5 5
6 environment: 6 environment:
@@ -242,7 +242,7 @@ void main() { @@ -242,7 +242,7 @@ void main() {
242 await tester.pumpWidget( 242 await tester.pumpWidget(
243 Wrapper( 243 Wrapper(
244 child: Container(), 244 child: Container(),
245 - defaultTransition: Transition.cupertino, 245 + defaultTransition: Transition.fadeIn,
246 ), 246 ),
247 ); 247 );
248 248
@@ -77,7 +77,7 @@ void main() { @@ -77,7 +77,7 @@ void main() {
77 ); 77 );
78 } 78 }
79 79
80 -class Controller extends GetController { 80 +class Controller extends GetxController {
81 static Controller get to => Get.find(); 81 static Controller get to => Get.find();
82 int count = 0; 82 int count = 0;
83 var counter = 0.obs; 83 var counter = 0.obs;
@@ -4,7 +4,7 @@ import 'package:get/get.dart'; @@ -4,7 +4,7 @@ import 'package:get/get.dart';
4 4
5 void main() { 5 void main() {
6 Controller controller = Get.put<Controller>(Controller()); 6 Controller controller = Get.put<Controller>(Controller());
7 - testWidgets("GetController smoke test", (tester) async { 7 + testWidgets("GetxController smoke test", (tester) async {
8 await tester.pumpWidget( 8 await tester.pumpWidget(
9 MaterialApp( 9 MaterialApp(
10 home: Column( 10 home: Column(
@@ -65,7 +65,7 @@ void main() { @@ -65,7 +65,7 @@ void main() {
65 }); 65 });
66 } 66 }
67 67
68 -class Controller extends RxController { 68 +class Controller extends GetxController {
69 static Controller get to => Get.find(); 69 static Controller get to => Get.find();
70 70
71 var counter = 0.obs; 71 var counter = 0.obs;
@@ -4,7 +4,7 @@ import 'package:get/get.dart'; @@ -4,7 +4,7 @@ import 'package:get/get.dart';
4 4
5 void main() { 5 void main() {
6 Get.lazyPut<Controller2>(() => Controller2()); 6 Get.lazyPut<Controller2>(() => Controller2());
7 - testWidgets("GetController smoke test", (tester) async { 7 + testWidgets("GetxController smoke test", (tester) async {
8 await tester.pumpWidget( 8 await tester.pumpWidget(
9 MaterialApp( 9 MaterialApp(
10 home: GetX<Controller>( 10 home: GetX<Controller>(
@@ -76,15 +76,15 @@ void main() { @@ -76,15 +76,15 @@ void main() {
76 }); 76 });
77 } 77 }
78 78
79 -class Controller2 extends RxController { 79 +class Controller2 extends GetxController {
80 int lazy = 0; 80 int lazy = 0;
81 } 81 }
82 82
83 -class ControllerNonGlobal extends RxController { 83 +class ControllerNonGlobal extends GetxController {
84 int nonGlobal = 0; 84 int nonGlobal = 0;
85 } 85 }
86 86
87 -class Controller extends RxController { 87 +class Controller extends GetxController {
88 static Controller get to => Get.find(); 88 static Controller get to => Get.find();
89 89
90 var counter = 0.obs; 90 var counter = 0.obs;
@@ -4,7 +4,7 @@ import 'package:get/get.dart'; @@ -4,7 +4,7 @@ import 'package:get/get.dart';
4 4
5 void main() { 5 void main() {
6 Get.lazyPut<Controller2>(() => Controller2()); 6 Get.lazyPut<Controller2>(() => Controller2());
7 - testWidgets("GetController smoke test", (test) async { 7 + testWidgets("GetxController smoke test", (test) async {
8 await test.pumpWidget( 8 await test.pumpWidget(
9 MaterialApp( 9 MaterialApp(
10 home: GetBuilder<Controller>( 10 home: GetBuilder<Controller>(
@@ -81,7 +81,7 @@ void main() { @@ -81,7 +81,7 @@ void main() {
81 ); 81 );
82 } 82 }
83 83
84 -class Controller extends GetController { 84 +class Controller extends GetxController {
85 static Controller get to => Get.find(); 85 static Controller get to => Get.find();
86 86
87 int counter = 0; 87 int counter = 0;
@@ -96,10 +96,10 @@ class Controller extends GetController { @@ -96,10 +96,10 @@ class Controller extends GetController {
96 } 96 }
97 } 97 }
98 98
99 -class Controller2 extends GetController { 99 +class Controller2 extends GetxController {
100 int test = 0; 100 int test = 0;
101 } 101 }
102 102
103 -class ControllerNonGlobal extends GetController { 103 +class ControllerNonGlobal extends GetxController {
104 int nonGlobal = 0; 104 int nonGlobal = 0;
105 } 105 }
@@ -4,16 +4,18 @@ import 'package:get/src/routes/get_route.dart'; @@ -4,16 +4,18 @@ import 'package:get/src/routes/get_route.dart';
4 4
5 void main() { 5 void main() {
6 testWidgets( 6 testWidgets(
7 - "GetRoute page null", 7 + 'GetPage page null',
8 (WidgetTester testr) async { 8 (WidgetTester testr) async {
9 - expect(() => GetRoute(page: null), throwsAssertionError); 9 + expect(() => GetPage(page: null, name: null), throwsAssertionError);
10 }, 10 },
11 ); 11 );
12 12
13 testWidgets( 13 testWidgets(
14 "GetRoute maintainState null", 14 "GetRoute maintainState null",
15 (WidgetTester testr) async { 15 (WidgetTester testr) async {
16 - expect(() => GetRoute(page: Scaffold(), maintainState: null), 16 + expect(
  17 + () =>
  18 + GetPage(page: () => Scaffold(), maintainState: null, name: null),
17 throwsAssertionError); 19 throwsAssertionError);
18 }, 20 },
19 ); 21 );
@@ -21,7 +23,9 @@ void main() { @@ -21,7 +23,9 @@ void main() {
21 testWidgets( 23 testWidgets(
22 "GetRoute fullscreenDialog null", 24 "GetRoute fullscreenDialog null",
23 (WidgetTester testr) async { 25 (WidgetTester testr) async {
24 - expect(() => GetRoute(page: Scaffold(), fullscreenDialog: null), 26 + expect(
  27 + () => GetPage(
  28 + page: () => Scaffold(), fullscreenDialog: null, name: null),
25 throwsAssertionError); 29 throwsAssertionError);
26 }, 30 },
27 ); 31 );
@@ -4,9 +4,9 @@ import 'package:get/get.dart'; @@ -4,9 +4,9 @@ import 'package:get/get.dart';
4 void main() { 4 void main() {
5 test('once', () async { 5 test('once', () async {
6 final count = 0.obs; 6 final count = 0.obs;
7 - int result = -1; 7 + var result = -1;
8 once(count, (_) { 8 once(count, (_) {
9 - result = _; 9 + result = _ as int;
10 }); 10 });
11 count.value++; 11 count.value++;
12 await Future.delayed(Duration.zero); 12 await Future.delayed(Duration.zero);
@@ -21,9 +21,9 @@ void main() { @@ -21,9 +21,9 @@ void main() {
21 21
22 test('ever', () async { 22 test('ever', () async {
23 final count = 0.obs; 23 final count = 0.obs;
24 - int result = -1; 24 + var result = -1;
25 ever(count, (_) { 25 ever(count, (_) {
26 - result = _; 26 + result = _ as int;
27 }); 27 });
28 count.value++; 28 count.value++;
29 await Future.delayed(Duration.zero); 29 await Future.delayed(Duration.zero);
@@ -38,10 +38,10 @@ void main() { @@ -38,10 +38,10 @@ void main() {
38 38
39 test('debounce', () async { 39 test('debounce', () async {
40 final count = 0.obs; 40 final count = 0.obs;
41 - int result = -1; 41 + var result = -1;
42 debounce(count, (_) { 42 debounce(count, (_) {
43 print(_); 43 print(_);
44 - result = _; 44 + result = _ as int;
45 }, time: Duration(milliseconds: 100)); 45 }, time: Duration(milliseconds: 100));
46 46
47 count.value++; 47 count.value++;
@@ -56,10 +56,10 @@ void main() { @@ -56,10 +56,10 @@ void main() {
56 56
57 test('interval', () async { 57 test('interval', () async {
58 final count = 0.obs; 58 final count = 0.obs;
59 - int result = -1; 59 + var result = -1;
60 interval(count, (_) { 60 interval(count, (_) {
61 print(_); 61 print(_);
62 - result = _; 62 + result = _ as int;
63 }, time: Duration(milliseconds: 100)); 63 }, time: Duration(milliseconds: 100));
64 64
65 count.value++; 65 count.value++;