Showing
42 changed files
with
2011 additions
and
1293 deletions
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 | -[](#contributors-) | 13 | +[](#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,20 +238,14 @@ void main() { | @@ -237,20 +238,14 @@ 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 | - ), | ||
248 | - GetPage( | ||
249 | - name: '/third', | ||
250 | - page: () => Third(), | ||
251 | - transition: Transition.cupertino | ||
252 | - ), | ||
253 | - ], | 241 | + GetPage(name: '/', page: () => MyHomePage()), |
242 | + GetPage(name: '/second', page: () => Second()), | ||
243 | + GetPage( | ||
244 | + name: '/third', | ||
245 | + page: () => Third(), | ||
246 | + transition: Transition.zoom | ||
247 | + ), | ||
248 | + ], | ||
254 | ) | 249 | ) |
255 | ); | 250 | ); |
256 | } | 251 | } |
@@ -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,13 +139,21 @@ class GetImpl implements GetService { | @@ -128,13 +139,21 @@ 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 | } |
137 | - if (global(id).currentState.canPop()) { | 152 | + if (canPop) { |
153 | + if (global(id).currentState.canPop()) { | ||
154 | + global(id).currentState.pop(result); | ||
155 | + } | ||
156 | + } else { | ||
138 | global(id).currentState.pop(result); | 157 | global(id).currentState.pop(result); |
139 | } | 158 | } |
140 | } | 159 | } |
@@ -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) { |
lib/src/queue/get_queue.dart
0 → 100644
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 | +} |
lib/src/regex/get_utils.dart
0 → 100644
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 | +} |
lib/src/regex/regex.dart
0 → 100644
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\.\,\;\?\'\\\+&%\$#\=~_\-]+))*$"; | ||
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; | ||
143 | + } | ||
144 | + if (translationsKeys != null) { | ||
145 | + Get.translations = translationsKeys; | ||
244 | } | 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 | +} |
lib/src/routes/custom_transition.dart
0 → 100644
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 | ||
49 | - if (binding != null) { | ||
50 | - binding.dependencies(); | ||
51 | - } | ||
52 | - if (bindings != null) { | ||
53 | - bindings.forEach((element) => element.dependencies()); | ||
54 | - } | ||
55 | - } | ||
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', | ||
102 | - ); | ||
103 | - return _previousTitle; | ||
104 | - } | 38 | + this.customTransition, |
39 | + }) : super( | ||
40 | + pageBuilder: (context, anim1, anim2) { | ||
41 | + if (binding != null) { | ||
42 | + binding.dependencies(); | ||
43 | + } | ||
44 | + if (bindings != null) { | ||
45 | + for (Bindings element in bindings) { | ||
46 | + element.dependencies(); | ||
47 | + } | ||
48 | + } | ||
49 | + GetConfig.currentRoute = settings.name; | ||
50 | + return page(); | ||
51 | + }, | ||
52 | + settings: settings, | ||
53 | + ); | ||
105 | 54 | ||
106 | @override | 55 | @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 | - | ||
121 | - /// Allows you to set opaque to false to prevent route reconstruction. | ||
122 | - @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); | 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); | ||
75 | + } | ||
130 | 76 | ||
131 | - @override | ||
132 | - String get barrierLabel => null; | 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); | ||
89 | + } | ||
133 | 90 | ||
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; | ||
138 | - } | 91 | + final curvedAnimation = CurvedAnimation( |
92 | + parent: animation, | ||
93 | + curve: this.curve ?? Curves.linear, | ||
94 | + ); | ||
139 | 95 | ||
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; | 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); | ||
150 | } | 107 | } |
151 | 108 | ||
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); | ||
161 | - | ||
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); | 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 | 138 | + controller: route.controller, |
230 | ); | 139 | ); |
231 | } | 140 | } |
232 | 141 | ||
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 | - ), | ||
444 | - ); | ||
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 | - } | ||
483 | - | ||
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 | +// } |
lib/src/routes/default_transitions.dart
0 → 100644
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; |
lib/src/routes/transitions_component.dart
0 → 100644
lib/src/routes/transitions_filter.dart
0 → 100644
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 | -} |
@@ -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. |
@@ -53,5 +42,5 @@ abstract class DisposableInterface { | @@ -53,5 +42,5 @@ abstract class DisposableInterface { | ||
53 | 42 | ||
54 | /// Called before the onDelete method. onClose is used to close events | 43 | /// Called before the onDelete method. onClose is used to close events |
55 | /// before the controller is destroyed, such as closing streams, for example. | 44 | /// before the controller is destroyed, such as closing streams, for example. |
56 | - onClose() async {} | 45 | + onClose() async {} |
57 | } | 46 | } |
lib/src/rx/rx_listview_builder.dart
deleted
100644 → 0
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 | } |
lib/src/rx/utils/delegate_list.dart
deleted
100644 → 0
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); |
123 | + } | ||
121 | } | 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 |
lib/src/state/get_view.dart
0 → 100644
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++; |
-
Please register or login to post a comment