Jonny Borges
Committed by GitHub

Merge branch 'master' into master

Showing 65 changed files with 1291 additions and 1307 deletions

Too many changes to show.

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

No preview for this file type
1 -## [4.5.1] - Big Update 1 +## [4.6.1]
  2 +Fix GetConnect on Flutter web
  3 +
  4 +## [4.6.0]
  5 +Add useInheritedMediaQuery to GetMaterialApp and GetCupertinoApp (@davidhole)
  6 +Add Circular reveal Transition (@parmarravi)
  7 +Add request to failed response (@heftekharm)
  8 +Fix internationalization with only country code (@codercengiz)
  9 +Add GetTickerProviderStateMixin when multiple AnimationController objects are used (@NatsuOnFire)
  10 +Add the followRedirects and maxRedirects fields to the Request object (@wei53881)
  11 +Fix to rx.trigger fires twice (@gslender)
  12 +Add proxy setting support to GetConnect (@jtans)
  13 +Fix markAsDirty used on permanent controllers (@zenalex)
  14 +Update Korean readme (@dumbokim)
  15 +
  16 +
  17 +## [4.5.1]
2 Fix Snackbar when it have action and icon the same time 18 Fix Snackbar when it have action and icon the same time
3 19
4 ## [4.5.0] - Big Update 20 ## [4.5.0] - Big Update
5 -To have a context-free, page-agnostic snackbar, we used OverlayRoute to display a partial route. 21 +To have a page-agnostic snackbar, we used OverlayRoute to display a partial route.
6 However this had several problems: 22 However this had several problems:
7 23
8 1: There was no possibility to close the page without closing the snackbar 24 1: There was no possibility to close the page without closing the snackbar
@@ -37,6 +37,17 @@ _语言: 中文, [英文](README.md), [越南文](README-vi.md), [印度尼西 @@ -37,6 +37,17 @@ _语言: 中文, [英文](README.md), [越南文](README-vi.md), [印度尼西
37 - [改变语言](#改变语言) 37 - [改变语言](#改变语言)
38 - [系统语言](#系统语言) 38 - [系统语言](#系统语言)
39 - [改变主题](#改变主题) 39 - [改变主题](#改变主题)
  40 + - [GetConnect](#getconnect)
  41 + - [默认配置](#默认配置)
  42 + - [自定义配置](#自定义配置)
  43 + - [GetPage 中间件](#getpage-中间件)
  44 + - [优先级](#优先级)
  45 + - [Redirect](#redirect)
  46 + - [onPageCalled](#onpagecalled)
  47 + - [OnBindingsStart](#onbindingsstart)
  48 + - [OnPageBuildStart](#onpagebuildstart)
  49 + - [OnPageBuilt](#onpagebuilt)
  50 + - [OnPageDispose](#onpagedispose)
40 - [其他高级API](#其他高级api) 51 - [其他高级API](#其他高级api)
41 - [可选的全局设置和手动配置](#可选的全局设置和手动配置) 52 - [可选的全局设置和手动配置](#可选的全局设置和手动配置)
42 - [局部状态组件](#局部状态组件) 53 - [局部状态组件](#局部状态组件)
@@ -394,6 +405,163 @@ Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark()); @@ -394,6 +405,163 @@ Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());
394 405
395 `.darkmode`被激活时,它将切换到light主题,当light主题被激活时,它将切换到dark主题。 406 `.darkmode`被激活时,它将切换到light主题,当light主题被激活时,它将切换到dark主题。
396 407
  408 +## GetConnect
  409 +
  410 +GetConnect可以便捷的通过http或websockets进行前后台通信。
  411 +
  412 +### 默认配置
  413 +
  414 +你能轻松的通过extend GetConnect就能使用GET/POST/PUT/DELETE/SOCKET方法与你的Rest API或websockets通信。
  415 +
  416 +```dart
  417 +class UserProvider extends GetConnect {
  418 + // Get request
  419 + Future<Response> getUser(int id) => get('http://youapi/users/$id');
  420 + // Post request
  421 + Future<Response> postUser(Map data) => post('http://youapi/users', body: data);
  422 + // Post request with File
  423 + Future<Response<CasesModel>> postCases(List<int> image) {
  424 + final form = FormData({
  425 + 'file': MultipartFile(image, filename: 'avatar.png'),
  426 + 'otherFile': MultipartFile(image, filename: 'cover.png'),
  427 + });
  428 + return post('http://youapi/users/upload', form);
  429 + }
  430 +
  431 + GetSocket userMessages() {
  432 + return socket('https://yourapi/users/socket');
  433 + }
  434 +}
  435 +```
  436 +
  437 +### 自定义配置
  438 +
  439 +GetConnect具有多种自定义配置。你可以配置base Url,配置响应,配置请求,添加权限验证,甚至是尝试认证的次数,除此之外,还可以定义一个标准的解码器,该解码器将把您的所有请求转换为您的模型,而不需要任何额外的配置。
  440 +
  441 +```dart
  442 +class HomeProvider extends GetConnect {
  443 + @override
  444 + void onInit() {
  445 + // All request will pass to jsonEncode so CasesModel.fromJson()
  446 + httpClient.defaultDecoder = CasesModel.fromJson;
  447 + httpClient.baseUrl = 'https://api.covid19api.com';
  448 + // baseUrl = 'https://api.covid19api.com'; // It define baseUrl to
  449 + // Http and websockets if used with no [httpClient] instance
  450 +
  451 + // It's will attach 'apikey' property on header from all requests
  452 + httpClient.addRequestModifier((request) {
  453 + request.headers['apikey'] = '12345678';
  454 + return request;
  455 + });
  456 +
  457 + // Even if the server sends data from the country "Brazil",
  458 + // it will never be displayed to users, because you remove
  459 + // that data from the response, even before the response is delivered
  460 + httpClient.addResponseModifier<CasesModel>((request, response) {
  461 + CasesModel model = response.body;
  462 + if (model.countries.contains('Brazil')) {
  463 + model.countries.remove('Brazilll');
  464 + }
  465 + });
  466 +
  467 + httpClient.addAuthenticator((request) async {
  468 + final response = await get("http://yourapi/token");
  469 + final token = response.body['token'];
  470 + // Set the header
  471 + request.headers['Authorization'] = "$token";
  472 + return request;
  473 + });
  474 +
  475 + //Autenticator will be called 3 times if HttpStatus is
  476 + //HttpStatus.unauthorized
  477 + httpClient.maxAuthRetries = 3;
  478 + }
  479 + }
  480 +
  481 + @override
  482 + Future<Response<CasesModel>> getCases(String path) => get(path);
  483 +}
  484 +```
  485 +
  486 +## GetPage 中间件
  487 +
  488 +GetPage现在有个新的参数可以把列表中的Get中间件按指定顺序执行。
  489 +
  490 +**注意**: 当GetPage有中间件时,所有的子page会自动有相同的中间件。
  491 +
  492 +### 优先级
  493 +
  494 +设置中间件的优先级定义Get中间件的执行顺序。
  495 +
  496 +```dart
  497 +final middlewares = [
  498 + GetMiddleware(priority: 2),
  499 + GetMiddleware(priority: 5),
  500 + GetMiddleware(priority: 4),
  501 + GetMiddleware(priority: -8),
  502 +];
  503 +```
  504 +
  505 +这些中间件会按这个顺序执行 **-8 => 2 => 4 => 5**
  506 +
  507 +### Redirect
  508 +
  509 +当被调用路由的页面被搜索时,这个函数将被调用。它将RouteSettings作为重定向的结果。或者给它null,就没有重定向了。
  510 +
  511 +```dart
  512 +RouteSettings redirect(String route) {
  513 + final authService = Get.find<AuthService>();
  514 + return authService.authed.value ? null : RouteSettings(name: '/login')
  515 +}
  516 +```
  517 +
  518 +### onPageCalled
  519 +
  520 +在调用页面时,创建任何东西之前,这个函数会先被调用。
  521 +您可以使用它来更改页面的某些内容或给它一个新页面。
  522 +
  523 +```dart
  524 +GetPage onPageCalled(GetPage page) {
  525 + final authService = Get.find<AuthService>();
  526 + return page.copyWith(title: 'Welcome ${authService.UserName}');
  527 +}
  528 +```
  529 +
  530 +### OnBindingsStart
  531 +
  532 +这个函数将在绑定初始化之前被调用。
  533 +在这里,您可以更改此页面的绑定。
  534 +
  535 +```dart
  536 +List<Bindings> onBindingsStart(List<Bindings> bindings) {
  537 + final authService = Get.find<AuthService>();
  538 + if (authService.isAdmin) {
  539 + bindings.add(AdminBinding());
  540 + }
  541 + return bindings;
  542 +}
  543 +```
  544 +
  545 +### OnPageBuildStart
  546 +
  547 +这个函数将在绑定初始化之后被调用。
  548 +在这里,您可以在创建绑定之后和创建页面widget之前执行一些操作。
  549 +
  550 +```dart
  551 +GetPageBuilder onPageBuildStart(GetPageBuilder page) {
  552 + print('bindings are ready');
  553 + return page;
  554 +}
  555 +```
  556 +
  557 +### OnPageBuilt
  558 +
  559 +这个函数将在GetPage.page调用后被调用,并给出函数的结果,并获取将要显示的widget。
  560 +
  561 +### OnPageDispose
  562 +
  563 +这个函数将在处理完页面的所有相关对象(Controllers, views, ...)之后被调用。
  564 +
397 ## 其他高级API 565 ## 其他高级API
398 566
399 ```dart 567 ```dart
@@ -59,11 +59,11 @@ var name = 'Jonatas Borges'.obs; @@ -59,11 +59,11 @@ var name = 'Jonatas Borges'.obs;
59 59
60 就这么简单! 60 就这么简单!
61 61
62 -我们把这个reactive-".obs"(ervables)变量称为_Rx_ 62 +我们把这个reactive-".obs"(ervables)变量称为 _Rx_
63 63
64 我们做了什么?我们创建了一个 "Stream "的 "String",分配了初始值 "Jonatas Borges",我们通知所有使用 "Jonatas Borges "的widgets,它们现在 "属于 "这个变量,当_Rx_的值发生变化时,它们也要随之改变。 64 我们做了什么?我们创建了一个 "Stream "的 "String",分配了初始值 "Jonatas Borges",我们通知所有使用 "Jonatas Borges "的widgets,它们现在 "属于 "这个变量,当_Rx_的值发生变化时,它们也要随之改变。
65 65
66 -这就是GetX**的**魔力,这要归功于Dart的能力。 66 +这就是GetX **的** 魔力,这要归功于Dart的能力。
67 67
68 但是,我们知道,一个`Widget`只有在函数里面才能改变,因为静态类没有 "自动改变 "的能力。 68 但是,我们知道,一个`Widget`只有在函数里面才能改变,因为静态类没有 "自动改变 "的能力。
69 69
@@ -80,15 +80,15 @@ var name = 'Jonatas Borges'.obs; @@ -80,15 +80,15 @@ var name = 'Jonatas Borges'.obs;
80 Obx (() => Text (controller.name)); 80 Obx (() => Text (controller.name));
81 ``` 81 ```
82 82
83 -_你只需记住 `Obx(()=>` 83 +你只需记住 `Obx(()=>`
84 84
85 -你只需将Widget通过一个箭头函数传递给 `Obx()`(_Rx_的 "观察者")。 85 +你只需将Widget通过一个箭头函数传递给 `Obx()`( _Rx_ 的 "观察者")。
86 86
87 `Obx`是相当聪明的,只有当`controller.name`的值发生变化时才会改变。 87 `Obx`是相当聪明的,只有当`controller.name`的值发生变化时才会改变。
88 88
89 如果`name`是`"John"`,你把它改成了`"John"`(`name.value="John"`),因为它和之前的`value`是一样的,所以界面上不会有任何变化,而`Obx`为了节省资源,会直接忽略新的值,不重建Widget。**这是不是很神奇** 89 如果`name`是`"John"`,你把它改成了`"John"`(`name.value="John"`),因为它和之前的`value`是一样的,所以界面上不会有任何变化,而`Obx`为了节省资源,会直接忽略新的值,不重建Widget。**这是不是很神奇**
90 90
91 -> 那么,如果我在一个`Obx`里有5个_Rx_(可观察的)变量呢? 91 +> 那么,如果我在一个`Obx`里有5个 _Rx_ (可观察的)变量呢?
92 92
93 当其中**任何**一个变量发生变化时,它就会更新。 93 当其中**任何**一个变量发生变化时,它就会更新。
94 94
@@ -96,7 +96,7 @@ _你只需记住 `Obx(()=>` @@ -96,7 +96,7 @@ _你只需记住 `Obx(()=>`
96 96
97 不会,只会更新使用那个 _Rx_ 变量的**特定 Widget** 97 不会,只会更新使用那个 _Rx_ 变量的**特定 Widget**
98 98
99 -所以,只有当_Rx_变量的值发生变化时,**GetX**才会更新界面。 99 +所以,只有当 _Rx_ 变量的值发生变化时,**GetX**才会更新界面。
100 100
101 ``` 101 ```
102 final isOpen = false.obs; 102 final isOpen = false.obs;
@@ -114,13 +114,13 @@ void onButtonTap() => isOpen.value=false; @@ -114,13 +114,13 @@ void onButtonTap() => isOpen.value=false;
114 114
115 如果你需要一个**强大的**状态管理器,用**GetX**是不会错的。 115 如果你需要一个**强大的**状态管理器,用**GetX**是不会错的。
116 116
117 -它不能和变量一起工作,除了__flows__,它里面的东西本质都是`Streams`  
118 -你可以将_rxDart_与它结合使用,因为所有的东西都是`Streams`  
119 -你可以监听每个"_Rx_变量 "的 "事件"。 117 +它不能和变量一起工作,除了 __flows__ ,它里面的东西本质都是`Streams`
  118 +你可以将 _rxDart_ 与它结合使用,因为所有的东西都是`Streams`
  119 +你可以监听每个" _Rx_ 变量 "的 "事件"。
120 因为里面的所有东西都是 "Streams"。 120 因为里面的所有东西都是 "Streams"。
121 121
122 -这实际上是一种_BLoC_方法,比_MobX_更容易,而且没有代码生成器或装饰。  
123 -你可以把**任何东西**变成一个_"Observable"_,只需要在它末尾加上`.obs` 122 +这实际上是一种 _BLoC_ 方法,比 _MobX_ 更容易,而且没有代码生成器或装饰。
  123 +你可以把**任何东西**变成一个 _"Observable"_ ,只需要在它末尾加上`.obs`
124 124
125 ### 最高性能 125 ### 最高性能
126 126
@@ -129,8 +129,8 @@ void onButtonTap() => isOpen.value=false; @@ -129,8 +129,8 @@ void onButtonTap() => isOpen.value=false;
129 如果你的应用程序中遇到错误,并发送重复的状态变更,**GetX**将确保它不会崩溃。 129 如果你的应用程序中遇到错误,并发送重复的状态变更,**GetX**将确保它不会崩溃。
130 130
131 使用**GetX**,只有当`value`改变时,状态才会改变。 131 使用**GetX**,只有当`value`改变时,状态才会改变。
132 -这就是**GetX**,和使用MobX_的_`computed`的主要区别。  
133 -当加入两个__observable__,其中一个发生变化时,该_observable_的监听器也会发生变化。 132 +这就是**GetX**,和使用MobX _的_ `computed`的主要区别。
  133 +当加入两个 __observable__ ,其中一个发生变化时,该 _observable_ 的监听器也会发生变化。
134 134
135 使用**GetX**,如果你连接了两个变量,`GetX()`(类似于`Observer()`)只有在它的状态真正变化时才会重建。 135 使用**GetX**,如果你连接了两个变量,`GetX()`(类似于`Observer()`)只有在它的状态真正变化时才会重建。
136 136
@@ -183,13 +183,13 @@ final user = User().obs; @@ -183,13 +183,13 @@ final user = User().obs;
183 183
184 ##### 有一个反应的状态,很容易。 184 ##### 有一个反应的状态,很容易。
185 185
186 -我们知道,_Dart_现在正朝着_null safety_的方向发展。  
187 -为了做好准备,从现在开始,你应该总是用一个**初始值**来开始你的_Rx_变量。 186 +我们知道, _Dart_ 现在正朝着 _null safety_ 的方向发展。
  187 +为了做好准备,从现在开始,你应该总是用一个**初始值**来开始你的 _Rx_ 变量。
188 188
189 -> 用**GetX**将一个变量转化为一个_observable_ + _initial value_是最简单,也是最实用的方法。 189 +> 用**GetX**将一个变量转化为一个 _observable_ + _initial value_ 是最简单,也是最实用的方法。
190 190
191 你只需在变量的末尾添加一个"`.obs`",即可把它变成可观察的变量, 191 你只需在变量的末尾添加一个"`.obs`",即可把它变成可观察的变量,
192 -然后它的`.value`就是_初始值_)。 192 +然后它的`.value`就是 _初始值_ )。
193 193
194 194
195 ### 使用视图中的值 195 ### 使用视图中的值
@@ -411,17 +411,17 @@ interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1)); @@ -411,17 +411,17 @@ interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
411 所有worker都会返回一个`Worker`实例,你可以用它来取消(通过`dispose()`)worker。 411 所有worker都会返回一个`Worker`实例,你可以用它来取消(通过`dispose()`)worker。
412 412
413 - **`ever`** 413 - **`ever`**
414 - 每当_Rx_变量发出一个新的值时,就会被调用。 414 + 每当 _Rx_ 变量发出一个新的值时,就会被调用。
415 415
416 - **`everAll`** 416 - **`everAll`**
417 - 和 "ever "很像,但它需要一个_Rx_值的 "List",每次它的变量被改变时都会被调用。就是这样。 417 + 和 "ever "很像,但它需要一个 _Rx_ 值的 "List",每次它的变量被改变时都会被调用。就是这样。
418 418
419 419
420 - **`once`** 420 - **`once`**
421 'once'只在变量第一次被改变时被调用。 421 'once'只在变量第一次被改变时被调用。
422 422
423 - **`debounce`** 423 - **`debounce`**
424 -debounce'在搜索函数中非常有用,你只希望API在用户完成输入时被调用。如果用户输入 "Jonny",你将在API中进行5次搜索,分别是字母J、o、n、n和y。使用Get不会发生这种情况,因为你将有一个 "debounce "Worker,它只会在输入结束时触发。 424 +'debounce'在搜索函数中非常有用,你只希望API在用户完成输入时被调用。如果用户输入 "Jonny",你将在API中进行5次搜索,分别是字母J、o、n、n和y。使用Get不会发生这种情况,因为你将有一个 "debounce "Worker,它只会在输入结束时触发。
425 425
426 - **`interval`** 426 - **`interval`**
427 'interval'与debouce不同,debouce如果用户在1秒内对一个变量进行了1000次修改,他将在规定的计时器(默认为800毫秒)后只发送最后一次修改。Interval则会忽略规定时间内的所有用户操作。如果你发送事件1分钟,每秒1000个,那么当用户停止DDOS事件时,debounce将只发送最后一个事件。建议这样做是为了避免滥用,在用户可以快速点击某样东西并获得一些好处的功能中(想象一下,用户点击某样东西可以赚取硬币,如果他在同一分钟内点击300次,他就会有300个硬币,使用间隔,你可以设置时间范围为3秒,无论是点击300次或100万次,1分钟内他最多获得20个硬币)。debounce适用于防DDOS,适用于搜索等功能,每次改变onChange都会调用你的api进行查询。Debounce会等待用户停止输入名称,进行请求。如果在上面提到的投币场景中使用它,用户只会赢得1个硬币,因为只有当用户 "暂停 "到既定时间时,它才会被执行。 427 'interval'与debouce不同,debouce如果用户在1秒内对一个变量进行了1000次修改,他将在规定的计时器(默认为800毫秒)后只发送最后一次修改。Interval则会忽略规定时间内的所有用户操作。如果你发送事件1分钟,每秒1000个,那么当用户停止DDOS事件时,debounce将只发送最后一个事件。建议这样做是为了避免滥用,在用户可以快速点击某样东西并获得一些好处的功能中(想象一下,用户点击某样东西可以赚取硬币,如果他在同一分钟内点击300次,他就会有300个硬币,使用间隔,你可以设置时间范围为3秒,无论是点击300次或100万次,1分钟内他最多获得20个硬币)。debounce适用于防DDOS,适用于搜索等功能,每次改变onChange都会调用你的api进行查询。Debounce会等待用户停止输入名称,进行请求。如果在上面提到的投币场景中使用它,用户只会赢得1个硬币,因为只有当用户 "暂停 "到既定时间时,它才会被执行。
1 -import 'package:flutter/foundation.dart';  
2 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
3 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
4 3
@@ -15,11 +14,11 @@ class MyApp extends StatelessWidget { @@ -15,11 +14,11 @@ class MyApp extends StatelessWidget {
15 14
16 @override 15 @override
17 Widget build(BuildContext context) { 16 Widget build(BuildContext context) {
18 - return GetMaterialApp.router( 17 + return GetMaterialApp(
19 debugShowCheckedModeBanner: false, 18 debugShowCheckedModeBanner: false,
20 enableLog: true, 19 enableLog: true,
21 logWriterCallback: Logger.write, 20 logWriterCallback: Logger.write,
22 - // initialRoute: AppPages.INITIAL, 21 + initialRoute: AppPages.INITIAL,
23 getPages: AppPages.routes, 22 getPages: AppPages.routes,
24 locale: TranslationService.locale, 23 locale: TranslationService.locale,
25 fallbackLocale: TranslationService.fallbackLocale, 24 fallbackLocale: TranslationService.fallbackLocale,
1 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
2 -import '../data/home_api_provider.dart';  
3 2
  3 +import '../data/home_api_provider.dart';
4 import '../data/home_repository.dart'; 4 import '../data/home_repository.dart';
5 import '../domain/adapters/repository_adapter.dart'; 5 import '../domain/adapters/repository_adapter.dart';
6 import '../presentation/controllers/home_controller.dart'; 6 import '../presentation/controllers/home_controller.dart';
1 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
  2 +
2 import '../domain/entity/cases_model.dart'; 3 import '../domain/entity/cases_model.dart';
3 4
4 // ignore: one_member_abstracts 5 // ignore: one_member_abstracts
@@ -12,6 +13,7 @@ class HomeProvider extends GetConnect implements IHomeProvider { @@ -12,6 +13,7 @@ class HomeProvider extends GetConnect implements IHomeProvider {
12 httpClient.defaultDecoder = 13 httpClient.defaultDecoder =
13 (val) => CasesModel.fromJson(val as Map<String, dynamic>); 14 (val) => CasesModel.fromJson(val as Map<String, dynamic>);
14 httpClient.baseUrl = 'https://api.covid19api.com'; 15 httpClient.baseUrl = 'https://api.covid19api.com';
  16 + super.onInit();
15 } 17 }
16 18
17 @override 19 @override
@@ -3,7 +3,7 @@ import 'package:get/get.dart'; @@ -3,7 +3,7 @@ import 'package:get/get.dart';
3 import '../../domain/adapters/repository_adapter.dart'; 3 import '../../domain/adapters/repository_adapter.dart';
4 import '../../domain/entity/cases_model.dart'; 4 import '../../domain/entity/cases_model.dart';
5 5
6 -class HomeController extends SuperController<CasesModel> { 6 +class HomeController extends StateController<CasesModel> {
7 HomeController({required this.homeRepository}); 7 HomeController({required this.homeRepository});
8 8
9 final IHomeRepository homeRepository; 9 final IHomeRepository homeRepository;
@@ -11,74 +11,12 @@ class HomeController extends SuperController<CasesModel> { @@ -11,74 +11,12 @@ class HomeController extends SuperController<CasesModel> {
11 @override 11 @override
12 void onInit() { 12 void onInit() {
13 super.onInit(); 13 super.onInit();
14 -  
15 //Loading, Success, Error handle with 1 line of code 14 //Loading, Success, Error handle with 1 line of code
16 - append(() => homeRepository.getCases); 15 + futurize(() => homeRepository.getCases);
17 } 16 }
18 17
19 Country getCountryById(String id) { 18 Country getCountryById(String id) {
20 final index = int.tryParse(id); 19 final index = int.tryParse(id);
21 - if (index != null) {  
22 - return state!.countries[index];  
23 - }  
24 -  
25 - return state!.countries.first;  
26 - }  
27 -  
28 - @override  
29 - void onReady() {  
30 - print('The build method is done. '  
31 - 'Your controller is ready to call dialogs and snackbars');  
32 - super.onReady();  
33 - }  
34 -  
35 - @override  
36 - void onClose() {  
37 - print('onClose called');  
38 - super.onClose();  
39 - }  
40 -  
41 - @override  
42 - void didChangeMetrics() {  
43 - print('the window size did change');  
44 - super.didChangeMetrics();  
45 - }  
46 -  
47 - @override  
48 - void didChangePlatformBrightness() {  
49 - print('platform change ThemeMode');  
50 - super.didChangePlatformBrightness();  
51 - }  
52 -  
53 - @override  
54 - Future<bool> didPushRoute(String route) {  
55 - print('the route $route will be open');  
56 - return super.didPushRoute(route);  
57 - }  
58 -  
59 - @override  
60 - Future<bool> didPopRoute() {  
61 - print('the current route will be closed');  
62 - return super.didPopRoute();  
63 - }  
64 -  
65 - @override  
66 - void onDetached() {  
67 - print('onDetached called');  
68 - }  
69 -  
70 - @override  
71 - void onInactive() {  
72 - print('onInative called');  
73 - }  
74 -  
75 - @override  
76 - void onPaused() {  
77 - print('onPaused called');  
78 - }  
79 -  
80 - @override  
81 - void onResumed() {  
82 - print('onResumed called'); 20 + return index != null ? state.countries[index] : state.countries.first;
83 } 21 }
84 } 22 }
@@ -6,6 +6,7 @@ import 'package:get/get.dart'; @@ -6,6 +6,7 @@ import 'package:get/get.dart';
6 import '../controllers/home_controller.dart'; 6 import '../controllers/home_controller.dart';
7 7
8 class CountryView extends GetView<HomeController> { 8 class CountryView extends GetView<HomeController> {
  9 + const CountryView({Key? key}) : super(key: key);
9 @override 10 @override
10 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
11 return Container( 12 return Container(
@@ -28,14 +29,15 @@ class CountryView extends GetView<HomeController> { @@ -28,14 +29,15 @@ class CountryView extends GetView<HomeController> {
28 ), 29 ),
29 body: Center( 30 body: Center(
30 child: ListView.builder( 31 child: ListView.builder(
31 - itemCount: controller.state!.countries.length, 32 + itemCount: controller.state.countries.length,
32 itemBuilder: (context, index) { 33 itemBuilder: (context, index) {
33 - final country = controller.state!.countries[index]; 34 + final country = controller.state.countries[index];
34 return ListTile( 35 return ListTile(
35 - onTap: () { 36 + onTap: () async {
36 //Get.rootDelegate.toNamed('/home/country'); 37 //Get.rootDelegate.toNamed('/home/country');
37 - Get.rootDelegate  
38 - .toNamed('/home/country/details?id=$index'); 38 + final data = await Get.toNamed(
  39 + '/home/country/details?id=$index');
  40 + print(data);
39 }, 41 },
40 trailing: CircleAvatar( 42 trailing: CircleAvatar(
41 backgroundImage: NetworkImage( 43 backgroundImage: NetworkImage(
@@ -2,12 +2,14 @@ import 'dart:ui'; @@ -2,12 +2,14 @@ import 'dart:ui';
2 2
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 4 import 'package:get/get.dart';
  5 +
5 import '../controllers/home_controller.dart'; 6 import '../controllers/home_controller.dart';
6 7
7 class DetailsView extends GetView<HomeController> { 8 class DetailsView extends GetView<HomeController> {
  9 + const DetailsView({Key? key}) : super(key: key);
8 @override 10 @override
9 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
10 - final parameter = Get.rootDelegate.parameters; 12 + final parameter = context.params; //Get.parameters;
11 final country = controller.getCountryById(parameter['id'] ?? ''); 13 final country = controller.getCountryById(parameter['id'] ?? '');
12 return Container( 14 return Container(
13 decoration: BoxDecoration( 15 decoration: BoxDecoration(
@@ -76,6 +78,11 @@ class DetailsView extends GetView<HomeController> { @@ -76,6 +78,11 @@ class DetailsView extends GetView<HomeController> {
76 '${country.totalRecovered}', 78 '${country.totalRecovered}',
77 style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold), 79 style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
78 ), 80 ),
  81 + TextButton(
  82 + onPressed: () {
  83 + Get.back(result: 'djsoidjsoidj');
  84 + },
  85 + child: Text('back'))
79 ], 86 ],
80 )), 87 )),
81 ), 88 ),
1 -import 'dart:ui';  
2 -  
3 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
5 3
6 import '../controllers/home_controller.dart'; 4 import '../controllers/home_controller.dart';
7 5
8 class HomeView extends GetView<HomeController> { 6 class HomeView extends GetView<HomeController> {
  7 + const HomeView({Key? key}) : super(key: key);
  8 +
9 @override 9 @override
10 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
11 return Container( 11 return Container(
@@ -77,9 +77,8 @@ class HomeView extends GetView<HomeController> { @@ -77,9 +77,8 @@ class HomeView extends GetView<HomeController> {
77 shape: StadiumBorder(), 77 shape: StadiumBorder(),
78 ), 78 ),
79 onPressed: () async { 79 onPressed: () async {
80 - final data =  
81 - await Get.rootDelegate.toNamed('/home/country');  
82 - print('DATA: $data'); 80 + //await Navigation Get.rootDelegate.toNamed('/home/country');
  81 + Get.toNamed('/home/country');
83 }, 82 },
84 child: Text( 83 child: Text(
85 'fetch_country'.tr, 84 'fetch_country'.tr,
@@ -15,7 +15,7 @@ class AppPages { @@ -15,7 +15,7 @@ class AppPages {
15 GetPage( 15 GetPage(
16 name: Routes.HOME, 16 name: Routes.HOME,
17 page: () => HomeView(), 17 page: () => HomeView(),
18 - binding: HomeBinding(), 18 + bindings: [HomeBinding()],
19 children: [ 19 children: [
20 GetPage( 20 GetPage(
21 name: Routes.COUNTRY, 21 name: Routes.COUNTRY,
@@ -27,6 +27,7 @@ class AppPages { @@ -27,6 +27,7 @@ class AppPages {
27 ), 27 ),
28 ], 28 ],
29 ), 29 ),
30 - ]), 30 + ],
  31 + ),
31 ]; 32 ];
32 } 33 }
@@ -4,4 +4,8 @@ abstract class Routes { @@ -4,4 +4,8 @@ abstract class Routes {
4 static const HOME = '/home'; 4 static const HOME = '/home';
5 static const COUNTRY = '/country'; 5 static const COUNTRY = '/country';
6 static const DETAILS = '/details'; 6 static const DETAILS = '/details';
  7 +
  8 + static const DASHBOARD = '/dashboard';
  9 + static const PROFILE = '/profile';
  10 + static const PRODUCTS = '/products';
7 } 11 }
1 -class Logger { 1 +mixin Logger {
2 // Sample of abstract logging function 2 // Sample of abstract logging function
3 static void write(String text, {bool isError = false}) { 3 static void write(String text, {bool isError = false}) {
4 Future.microtask(() => print('** $text. isError: [$isError]')); 4 Future.microtask(() => print('** $text. isError: [$isError]'));
@@ -20,6 +20,10 @@ version: 1.0.0+1 @@ -20,6 +20,10 @@ version: 1.0.0+1
20 environment: 20 environment:
21 sdk: ">=2.12.0 <3.0.0" 21 sdk: ">=2.12.0 <3.0.0"
22 22
  23 +dependency_overrides:
  24 + get:
  25 + path: ../
  26 +
23 dependencies: 27 dependencies:
24 flutter: 28 flutter:
25 sdk: flutter 29 sdk: flutter
@@ -33,6 +37,7 @@ dependencies: @@ -33,6 +37,7 @@ dependencies:
33 dev_dependencies: 37 dev_dependencies:
34 flutter_test: 38 flutter_test:
35 sdk: flutter 39 sdk: flutter
  40 + get_test: 4.0.1
36 41
37 # For information on the generic Dart part of this file, see the 42 # For information on the generic Dart part of this file, see the
38 # following page: https://dart.dev/tools/pub/pubspec 43 # following page: https://dart.dev/tools/pub/pubspec
1 import 'dart:io'; 1 import 'dart:io';
2 -import 'dart:math'; 2 +
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:flutter_test/flutter_test.dart'; 4 import 'package:flutter_test/flutter_test.dart';
5 import 'package:get/get.dart'; 5 import 'package:get/get.dart';
@@ -7,16 +7,16 @@ import 'package:get/get.dart'; @@ -7,16 +7,16 @@ import 'package:get/get.dart';
7 // import 'package:get_test/get_test.dart'; 7 // import 'package:get_test/get_test.dart';
8 import 'package:matcher/matcher.dart' as m; 8 import 'package:matcher/matcher.dart' as m;
9 9
  10 +
10 import '../lib/pages/home/domain/adapters/repository_adapter.dart'; 11 import '../lib/pages/home/domain/adapters/repository_adapter.dart';
11 import '../lib/pages/home/domain/entity/cases_model.dart'; 12 import '../lib/pages/home/domain/entity/cases_model.dart';
12 import '../lib/pages/home/presentation/controllers/home_controller.dart'; 13 import '../lib/pages/home/presentation/controllers/home_controller.dart';
13 14
14 -class MockRepository implements IHomeRepository { 15 +
  16 +class MockRepositorySuccess implements IHomeRepository {
  17 +
15 @override 18 @override
16 Future<CasesModel> getCases() async { 19 Future<CasesModel> getCases() async {
17 - await Future.delayed(Duration(milliseconds: 100));  
18 -  
19 - if (Random().nextBool()) {  
20 return CasesModel( 20 return CasesModel(
21 global: Global( 21 global: Global(
22 totalDeaths: 100, 22 totalDeaths: 100,
@@ -32,7 +32,11 @@ class MockRepository implements IHomeRepository { @@ -32,7 +32,11 @@ class MockRepository implements IHomeRepository {
32 message: '', 32 message: '',
33 ); 33 );
34 } 34 }
  35 +}
35 36
  37 +class MockRepositoryFailure implements IHomeRepository {
  38 + @override
  39 + Future<CasesModel> getCases() async {
36 return Future<CasesModel>.error('error'); 40 return Future<CasesModel>.error('error');
37 } 41 }
38 } 42 }
@@ -41,28 +45,18 @@ void main() { @@ -41,28 +45,18 @@ void main() {
41 WidgetsFlutterBinding.ensureInitialized(); 45 WidgetsFlutterBinding.ensureInitialized();
42 setUpAll(() => HttpOverrides.global = null); 46 setUpAll(() => HttpOverrides.global = null);
43 final binding = BindingsBuilder(() { 47 final binding = BindingsBuilder(() {
44 - Get.lazyPut<IHomeRepository>(() => MockRepository()); 48 + Get.lazyPut<IHomeRepository>(() => MockRepositorySuccess());
45 Get.lazyPut<HomeController>( 49 Get.lazyPut<HomeController>(
46 - () => HomeController(homeRepository: Get.find())); 50 + () => HomeController(homeRepository: Get.find()),
  51 + );
47 }); 52 });
48 53
49 - test('Test Binding', () {  
50 - expect(Get.isPrepared<HomeController>(), false);  
51 - expect(Get.isPrepared<IHomeRepository>(), false);  
52 -  
53 - /// test you Binding class with BindingsBuilder  
54 - binding.builder();  
55 -  
56 - expect(Get.isPrepared<HomeController>(), true);  
57 - expect(Get.isPrepared<IHomeRepository>(), true);  
58 -  
59 - Get.reset();  
60 - });  
61 test('Test Controller', () async { 54 test('Test Controller', () async {
62 /// Controller can't be on memory 55 /// Controller can't be on memory
63 - expect(() => Get.find<HomeController>(), throwsA(m.TypeMatcher<String>())); 56 + expect(() => Get.find<HomeController>(tag: 'success'),
  57 + throwsA(m.TypeMatcher<String>()));
64 58
65 - /// build Binding 59 + /// binding will put the controller on memory
66 binding.builder(); 60 binding.builder();
67 61
68 /// recover your controller 62 /// recover your controller
@@ -77,24 +71,15 @@ void main() { @@ -77,24 +71,15 @@ void main() {
77 /// await time request 71 /// await time request
78 await Future.delayed(Duration(milliseconds: 100)); 72 await Future.delayed(Duration(milliseconds: 100));
79 73
80 - if (controller.status.isError) {  
81 - expect(controller.state, null);  
82 - } 74 + /// test if status is success
  75 + expect(controller.status.isSuccess, true);
  76 + expect(controller.state.global.totalDeaths, 100);
  77 + expect(controller.state.global.totalConfirmed, 200);
83 78
84 - if (controller.status.isSuccess) {  
85 - expect(controller.state!.global.totalDeaths, 100);  
86 - expect(controller.state!.global.totalConfirmed, 200);  
87 - }  
88 - });  
89 -  
90 - test('ever', () async {  
91 - final count = ''.obs;  
92 - var result = '';  
93 - ever<String>(count, (value) {  
94 - result = value;  
95 - });  
96 - count.value = '1';  
97 - expect('1', result); 79 + /// test if status is error
  80 + Get.lazyReplace<IHomeRepository>(() => MockRepositoryFailure());
  81 + expect(controller.status.isError, true);
  82 + expect(controller.state, null);
98 }); 83 });
99 84
100 /// Tests with GetTests 85 /// Tests with GetTests
@@ -151,26 +136,3 @@ void main() { @@ -151,26 +136,3 @@ void main() {
151 }, 136 },
152 );*/ 137 );*/
153 } 138 }
154 -  
155 -class Controller extends GetxController {  
156 - final count = 0.obs;  
157 - void increment() => count.value++;  
158 -  
159 - @override  
160 - void onInit() {  
161 - print('inittt');  
162 - super.onInit();  
163 - }  
164 -  
165 - @override  
166 - void onReady() {  
167 - print('onReady');  
168 - super.onReady();  
169 - }  
170 -  
171 - @override  
172 - void onClose() {  
173 - super.onClose();  
174 - print('onClose');  
175 - }  
176 -}  
@@ -21,6 +21,6 @@ @@ -21,6 +21,6 @@
21 <key>CFBundleVersion</key> 21 <key>CFBundleVersion</key>
22 <string>1.0</string> 22 <string>1.0</string>
23 <key>MinimumOSVersion</key> 23 <key>MinimumOSVersion</key>
24 - <string>8.0</string> 24 + <string>9.0</string>
25 </dict> 25 </dict>
26 </plist> 26 </plist>
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 archiveVersion = 1; 3 archiveVersion = 1;
4 classes = { 4 classes = {
5 }; 5 };
6 - objectVersion = 46; 6 + objectVersion = 50;
7 objects = { 7 objects = {
8 8
9 /* Begin PBXBuildFile section */ 9 /* Begin PBXBuildFile section */
@@ -127,7 +127,7 @@ @@ -127,7 +127,7 @@
127 97C146E61CF9000F007C117D /* Project object */ = { 127 97C146E61CF9000F007C117D /* Project object */ = {
128 isa = PBXProject; 128 isa = PBXProject;
129 attributes = { 129 attributes = {
130 - LastUpgradeCheck = 1020; 130 + LastUpgradeCheck = 1300;
131 ORGANIZATIONNAME = ""; 131 ORGANIZATIONNAME = "";
132 TargetAttributes = { 132 TargetAttributes = {
133 97C146ED1CF9000F007C117D = { 133 97C146ED1CF9000F007C117D = {
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <Scheme 2 <Scheme
3 - LastUpgradeVersion = "1020" 3 + LastUpgradeVersion = "1300"
4 version = "1.3"> 4 version = "1.3">
5 <BuildAction 5 <BuildAction
6 parallelizeBuildables = "YES" 6 parallelizeBuildables = "YES"
@@ -5,14 +5,14 @@ import '../routes/app_pages.dart'; @@ -5,14 +5,14 @@ import '../routes/app_pages.dart';
5 5
6 class EnsureAuthMiddleware extends GetMiddleware { 6 class EnsureAuthMiddleware extends GetMiddleware {
7 @override 7 @override
8 - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async { 8 + Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
9 // you can do whatever you want here 9 // you can do whatever you want here
10 // but it's preferable to make this method fast 10 // but it's preferable to make this method fast
11 // await Future.delayed(Duration(milliseconds: 500)); 11 // await Future.delayed(Duration(milliseconds: 500));
12 12
13 if (!AuthService.to.isLoggedInValue) { 13 if (!AuthService.to.isLoggedInValue) {
14 - final newRoute = Routes.LOGIN_THEN(route.location!);  
15 - return GetNavConfig.fromRoute(newRoute); 14 + final newRoute = Routes.LOGIN_THEN(route.pageSettings!.name);
  15 + return RouteDecoder.fromRoute(newRoute);
16 } 16 }
17 return await super.redirectDelegate(route); 17 return await super.redirectDelegate(route);
18 } 18 }
@@ -20,13 +20,13 @@ class EnsureAuthMiddleware extends GetMiddleware { @@ -20,13 +20,13 @@ class EnsureAuthMiddleware extends GetMiddleware {
20 20
21 class EnsureNotAuthedMiddleware extends GetMiddleware { 21 class EnsureNotAuthedMiddleware extends GetMiddleware {
22 @override 22 @override
23 - Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async { 23 + Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
24 if (AuthService.to.isLoggedInValue) { 24 if (AuthService.to.isLoggedInValue) {
25 //NEVER navigate to auth screen, when user is already authed 25 //NEVER navigate to auth screen, when user is already authed
26 return null; 26 return null;
27 27
28 //OR redirect user to another screen 28 //OR redirect user to another screen
29 - //return GetNavConfig.fromRoute(Routes.PROFILE); 29 + //return RouteDecoder.fromRoute(Routes.PROFILE);
30 } 30 }
31 return await super.redirectDelegate(route); 31 return await super.redirectDelegate(route);
32 } 32 }
@@ -2,11 +2,13 @@ import 'package:get/get.dart'; @@ -2,11 +2,13 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/dashboard_controller.dart'; 3 import '../controllers/dashboard_controller.dart';
4 4
5 -class DashboardBinding extends Bindings { 5 +class DashboardBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.lazyPut<DashboardController>( 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.lazyPut<DashboardController>(
9 () => DashboardController(), 10 () => DashboardController(),
10 - ); 11 + )
  12 + ];
11 } 13 }
12 } 14 }
@@ -2,11 +2,13 @@ import 'package:get/get.dart'; @@ -2,11 +2,13 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/home_controller.dart'; 3 import '../controllers/home_controller.dart';
4 4
5 -class HomeBinding extends Bindings { 5 +class HomeBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.lazyPut<HomeController>( 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.lazyPut<HomeController>(
9 () => HomeController(), 10 () => HomeController(),
10 - ); 11 + )
  12 + ];
11 } 13 }
12 } 14 }
@@ -5,24 +5,29 @@ import '../../../routes/app_pages.dart'; @@ -5,24 +5,29 @@ import '../../../routes/app_pages.dart';
5 import '../controllers/home_controller.dart'; 5 import '../controllers/home_controller.dart';
6 6
7 class HomeView extends GetView<HomeController> { 7 class HomeView extends GetView<HomeController> {
  8 + const HomeView({Key? key}) : super(key: key);
8 @override 9 @override
9 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
10 return GetRouterOutlet.builder( 11 return GetRouterOutlet.builder(
11 - builder: (context, delegate, currentRoute) { 12 + routerDelegate: Get.nestedKey(Routes.HOME),
  13 + builder: (context) {
  14 + final delegate = context.navigation;
12 //This router outlet handles the appbar and the bottom navigation bar 15 //This router outlet handles the appbar and the bottom navigation bar
13 - final currentLocation = currentRoute?.location; 16 + final currentLocation = context.location;
14 var currentIndex = 0; 17 var currentIndex = 0;
15 - if (currentLocation?.startsWith(Routes.PRODUCTS) == true) { 18 + if (currentLocation.startsWith(Routes.PRODUCTS) == true) {
16 currentIndex = 2; 19 currentIndex = 2;
17 } 20 }
18 - if (currentLocation?.startsWith(Routes.PROFILE) == true) { 21 + if (currentLocation.startsWith(Routes.PROFILE) == true) {
19 currentIndex = 1; 22 currentIndex = 1;
20 } 23 }
21 return Scaffold( 24 return Scaffold(
22 body: GetRouterOutlet( 25 body: GetRouterOutlet(
23 initialRoute: Routes.DASHBOARD, 26 initialRoute: Routes.DASHBOARD,
24 - // anchorRoute: Routes.HOME,  
25 - key: Get.nestedKey(Routes.HOME), 27 + anchorRoute: Routes.HOME,
  28 +
  29 + //delegate: Get.nestedKey(Routes.HOME),
  30 + // key: Get.nestedKey(Routes.HOME),
26 ), 31 ),
27 bottomNavigationBar: BottomNavigationBar( 32 bottomNavigationBar: BottomNavigationBar(
28 currentIndex: currentIndex, 33 currentIndex: currentIndex,
@@ -2,11 +2,11 @@ import 'package:get/get.dart'; @@ -2,11 +2,11 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/login_controller.dart'; 3 import '../controllers/login_controller.dart';
4 4
5 -class LoginBinding extends Bindings { 5 +class LoginBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.lazyPut<LoginController>(  
9 - () => LoginController(),  
10 - ); 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.lazyPut(() => LoginController()),
  10 + ];
11 } 11 }
12 } 12 }
@@ -31,9 +31,8 @@ class LoginView extends GetView<LoginController> { @@ -31,9 +31,8 @@ class LoginView extends GetView<LoginController> {
31 ), 31 ),
32 onPressed: () { 32 onPressed: () {
33 AuthService.to.login(); 33 AuthService.to.login();
34 - final thenTo = Get.rootDelegate.currentConfiguration!  
35 - .currentPage!.parameters?['then'];  
36 - Get.rootDelegate.offNamed(thenTo ?? Routes.HOME); 34 + final thenTo = context.params['then'];
  35 + Get.offNamed(thenTo ?? Routes.HOME);
37 }, 36 },
38 ), 37 ),
39 ], 38 ],
@@ -2,13 +2,15 @@ import 'package:get/get.dart'; @@ -2,13 +2,15 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/product_details_controller.dart'; 3 import '../controllers/product_details_controller.dart';
4 4
5 -class ProductDetailsBinding extends Bindings { 5 +class ProductDetailsBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.create<ProductDetailsController>( 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.create<ProductDetailsController>(
9 () => ProductDetailsController( 10 () => ProductDetailsController(
10 Get.parameters['productId'] ?? '', 11 Get.parameters['productId'] ?? '',
11 ), 12 ),
12 - ); 13 + )
  14 + ];
13 } 15 }
14 } 16 }
@@ -13,6 +13,7 @@ class ProductDetailsController extends GetxController { @@ -13,6 +13,7 @@ class ProductDetailsController extends GetxController {
13 @override 13 @override
14 void onClose() { 14 void onClose() {
15 Get.log('ProductDetailsController close with id: $productId'); 15 Get.log('ProductDetailsController close with id: $productId');
  16 +
16 super.onClose(); 17 super.onClose();
17 } 18 }
18 } 19 }
@@ -5,11 +5,12 @@ import '../../../routes/app_pages.dart'; @@ -5,11 +5,12 @@ import '../../../routes/app_pages.dart';
5 import '../controllers/products_controller.dart'; 5 import '../controllers/products_controller.dart';
6 6
7 class ProductsView extends GetView<ProductsController> { 7 class ProductsView extends GetView<ProductsController> {
  8 + const ProductsView({Key? key}) : super(key: key);
8 @override 9 @override
9 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
10 return Scaffold( 11 return Scaffold(
11 floatingActionButton: FloatingActionButton.extended( 12 floatingActionButton: FloatingActionButton.extended(
12 - onPressed: controller.loadDemoProductsFromSomeWhere, 13 + onPressed: () => controller.loadDemoProductsFromSomeWhere(),
13 label: Text('Add'), 14 label: Text('Add'),
14 ), 15 ),
15 body: Column( 16 body: Column(
@@ -31,8 +32,7 @@ class ProductsView extends GetView<ProductsController> { @@ -31,8 +32,7 @@ class ProductsView extends GetView<ProductsController> {
31 final item = controller.products[index]; 32 final item = controller.products[index];
32 return ListTile( 33 return ListTile(
33 onTap: () { 34 onTap: () {
34 - Get.rootDelegate  
35 - .toNamed(Routes.PRODUCT_DETAILS(item.id)); 35 + Get.toNamed(Routes.PRODUCT_DETAILS(item.id));
36 }, 36 },
37 title: Text(item.name), 37 title: Text(item.name),
38 subtitle: Text(item.id), 38 subtitle: Text(item.id),
@@ -2,11 +2,13 @@ import 'package:get/get.dart'; @@ -2,11 +2,13 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/profile_controller.dart'; 3 import '../controllers/profile_controller.dart';
4 4
5 -class ProfileBinding extends Bindings { 5 +class ProfileBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.lazyPut<ProfileController>( 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.lazyPut<ProfileController>(
9 () => ProfileController(), 10 () => ProfileController(),
10 - ); 11 + )
  12 + ];
11 } 13 }
12 } 14 }
@@ -39,7 +39,8 @@ class ProfileView extends GetView<ProfileController> { @@ -39,7 +39,8 @@ class ProfileView extends GetView<ProfileController> {
39 Get.defaultDialog( 39 Get.defaultDialog(
40 title: 'Test Dialog In Home Outlet !!', 40 title: 'Test Dialog In Home Outlet !!',
41 barrierDismissible: true, 41 barrierDismissible: true,
42 - navigatorKey: Get.nestedKey(Routes.HOME), 42 + id: Routes.HOME,
  43 + // navigatorKey: Get.nestedKey(Routes.HOME),
43 ); 44 );
44 }, 45 },
45 ) 46 )
@@ -2,11 +2,13 @@ import 'package:get/get.dart'; @@ -2,11 +2,13 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/root_controller.dart'; 3 import '../controllers/root_controller.dart';
4 4
5 -class RootBinding extends Bindings { 5 +class RootBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.lazyPut<RootController>( 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.lazyPut<RootController>(
9 () => RootController(), 10 () => RootController(),
10 - ); 11 + )
  12 + ];
11 } 13 }
12 } 14 }
@@ -21,7 +21,7 @@ class DrawerWidget extends StatelessWidget { @@ -21,7 +21,7 @@ class DrawerWidget extends StatelessWidget {
21 ListTile( 21 ListTile(
22 title: Text('Home'), 22 title: Text('Home'),
23 onTap: () { 23 onTap: () {
24 - Get.rootDelegate.toNamed(Routes.HOME); 24 + Get.toNamed(Routes.HOME);
25 //to close the drawer 25 //to close the drawer
26 26
27 Navigator.of(context).pop(); 27 Navigator.of(context).pop();
@@ -30,7 +30,7 @@ class DrawerWidget extends StatelessWidget { @@ -30,7 +30,7 @@ class DrawerWidget extends StatelessWidget {
30 ListTile( 30 ListTile(
31 title: Text('Settings'), 31 title: Text('Settings'),
32 onTap: () { 32 onTap: () {
33 - Get.rootDelegate.toNamed(Routes.SETTINGS); 33 + Get.toNamed(Routes.SETTINGS);
34 //to close the drawer 34 //to close the drawer
35 35
36 Navigator.of(context).pop(); 36 Navigator.of(context).pop();
@@ -46,7 +46,7 @@ class DrawerWidget extends StatelessWidget { @@ -46,7 +46,7 @@ class DrawerWidget extends StatelessWidget {
46 ), 46 ),
47 onTap: () { 47 onTap: () {
48 AuthService.to.logout(); 48 AuthService.to.logout();
49 - Get.rootDelegate.toNamed(Routes.LOGIN); 49 + Get.toNamed(Routes.LOGIN);
50 //to close the drawer 50 //to close the drawer
51 51
52 Navigator.of(context).pop(); 52 Navigator.of(context).pop();
@@ -61,7 +61,7 @@ class DrawerWidget extends StatelessWidget { @@ -61,7 +61,7 @@ class DrawerWidget extends StatelessWidget {
61 ), 61 ),
62 ), 62 ),
63 onTap: () { 63 onTap: () {
64 - Get.rootDelegate.toNamed(Routes.LOGIN); 64 + Get.toNamed(Routes.LOGIN);
65 //to close the drawer 65 //to close the drawer
66 66
67 Navigator.of(context).pop(); 67 Navigator.of(context).pop();
@@ -8,21 +8,28 @@ import 'drawer.dart'; @@ -8,21 +8,28 @@ import 'drawer.dart';
8 class RootView extends GetView<RootController> { 8 class RootView extends GetView<RootController> {
9 @override 9 @override
10 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
11 - return GetRouterOutlet.builder(  
12 - builder: (context, delegate, current) {  
13 - final title = current?.location; 11 + return RouterOutlet.builder(
  12 + delegate: Get.nestedKey(null),
  13 + builder: (context) {
  14 + final title = context.location;
14 return Scaffold( 15 return Scaffold(
15 drawer: DrawerWidget(), 16 drawer: DrawerWidget(),
16 appBar: AppBar( 17 appBar: AppBar(
17 - title: Text(title ?? ''), 18 + title: Text(title),
18 centerTitle: true, 19 centerTitle: true,
19 ), 20 ),
  21 + //body: HomeView(),
  22 +
20 body: GetRouterOutlet( 23 body: GetRouterOutlet(
21 initialRoute: Routes.HOME, 24 initialRoute: Routes.HOME,
22 - // anchorRoute: '/',  
23 - // filterPages: (afterAnchor) {  
24 - // return afterAnchor.take(1);  
25 - // }, 25 + delegate: Get.nestedKey(null),
  26 + anchorRoute: '/',
  27 + filterPages: (afterAnchor) {
  28 + // print(afterAnchor);
  29 + // print('dddddddddddddddddd');
  30 + // print(afterAnchor.take(1));
  31 + return afterAnchor.take(1);
  32 + },
26 ), 33 ),
27 ); 34 );
28 }, 35 },
@@ -2,11 +2,13 @@ import 'package:get/get.dart'; @@ -2,11 +2,13 @@ import 'package:get/get.dart';
2 2
3 import '../controllers/settings_controller.dart'; 3 import '../controllers/settings_controller.dart';
4 4
5 -class SettingsBinding extends Bindings { 5 +class SettingsBinding extends Binding {
6 @override 6 @override
7 - void dependencies() {  
8 - Get.lazyPut<SettingsController>( 7 + List<Bind> dependencies() {
  8 + return [
  9 + Bind.lazyPut<SettingsController>(
9 () => SettingsController(), 10 () => SettingsController(),
10 - ); 11 + )
  12 + ];
11 } 13 }
12 } 14 }
  1 +import 'dart:async';
  2 +
  3 +import 'package:async/async.dart';
  4 +import 'package:get/get.dart';
  5 +
  6 +class SplashService extends GetxService {
  7 + final welcomeStr = ['GetX', 'Rules!'];
  8 + final activeStr = 0.obs;
  9 +
  10 + final memo = AsyncMemoizer<void>();
  11 + Future<void> init() {
  12 + return memo.runOnce(_initFunction);
  13 + }
  14 +
  15 + void _changeActiveString() {
  16 + activeStr.value = (activeStr.value + 1) % welcomeStr.length;
  17 + }
  18 +
  19 + Future<void> _initFunction() async {
  20 + final t = Timer.periodic(
  21 + Duration(milliseconds: 500),
  22 + (t) => _changeActiveString(),
  23 + );
  24 + //simulate some long running operation
  25 + await Future.delayed(Duration(seconds: 5));
  26 + //cancel the timer once we are done
  27 + t.cancel();
  28 + }
  29 +}
  1 +import 'package:flutter/material.dart';
  2 +
  3 +import 'package:get/get.dart';
  4 +
  5 +import '../controllers/splash_service.dart';
  6 +
  7 +class SplashView extends GetView<SplashService> {
  8 + @override
  9 + Widget build(BuildContext context) {
  10 + return Scaffold(
  11 + body: Center(
  12 + child: Column(
  13 + mainAxisSize: MainAxisSize.min,
  14 + children: [
  15 + Obx(
  16 + () => Text(
  17 + controller.welcomeStr[controller.activeStr.value],
  18 + style: TextStyle(fontSize: 20),
  19 + ),
  20 + ),
  21 + CircularProgressIndicator(),
  22 + ],
  23 + ),
  24 + ),
  25 + );
  26 + }
  27 +}
@@ -29,7 +29,7 @@ class AppPages { @@ -29,7 +29,7 @@ class AppPages {
29 GetPage( 29 GetPage(
30 name: '/', 30 name: '/',
31 page: () => RootView(), 31 page: () => RootView(),
32 - binding: RootBinding(), 32 + bindings: [RootBinding()],
33 participatesInRootNavigator: true, 33 participatesInRootNavigator: true,
34 preventDuplicates: true, 34 preventDuplicates: true,
35 children: [ 35 children: [
@@ -40,12 +40,12 @@ class AppPages { @@ -40,12 +40,12 @@ class AppPages {
40 ], 40 ],
41 name: _Paths.LOGIN, 41 name: _Paths.LOGIN,
42 page: () => LoginView(), 42 page: () => LoginView(),
43 - binding: LoginBinding(), 43 + bindings: [LoginBinding()],
44 ), 44 ),
45 GetPage( 45 GetPage(
46 preventDuplicates: true, 46 preventDuplicates: true,
47 name: _Paths.HOME, 47 name: _Paths.HOME,
48 - page: () => HomeView(), 48 + page: () => const HomeView(),
49 bindings: [ 49 bindings: [
50 HomeBinding(), 50 HomeBinding(),
51 ], 51 ],
@@ -54,7 +54,9 @@ class AppPages { @@ -54,7 +54,9 @@ class AppPages {
54 GetPage( 54 GetPage(
55 name: _Paths.DASHBOARD, 55 name: _Paths.DASHBOARD,
56 page: () => DashboardView(), 56 page: () => DashboardView(),
57 - binding: DashboardBinding(), 57 + bindings: [
  58 + DashboardBinding(),
  59 + ],
58 ), 60 ),
59 GetPage( 61 GetPage(
60 middlewares: [ 62 middlewares: [
@@ -65,19 +67,20 @@ class AppPages { @@ -65,19 +67,20 @@ class AppPages {
65 page: () => ProfileView(), 67 page: () => ProfileView(),
66 title: 'Profile', 68 title: 'Profile',
67 transition: Transition.size, 69 transition: Transition.size,
68 - binding: ProfileBinding(), 70 + bindings: [ProfileBinding()],
69 ), 71 ),
70 GetPage( 72 GetPage(
71 name: _Paths.PRODUCTS, 73 name: _Paths.PRODUCTS,
72 - page: () => ProductsView(), 74 + page: () => const ProductsView(),
73 title: 'Products', 75 title: 'Products',
74 transition: Transition.zoom, 76 transition: Transition.zoom,
75 - binding: ProductsBinding(), 77 + participatesInRootNavigator: false,
  78 + bindings: [ProductsBinding()],
76 children: [ 79 children: [
77 GetPage( 80 GetPage(
78 name: _Paths.PRODUCT_DETAILS, 81 name: _Paths.PRODUCT_DETAILS,
79 page: () => ProductDetailsView(), 82 page: () => ProductDetailsView(),
80 - binding: ProductDetailsBinding(), 83 + bindings: [ProductDetailsBinding()],
81 middlewares: [ 84 middlewares: [
82 //only enter this route when authed 85 //only enter this route when authed
83 EnsureAuthMiddleware(), 86 EnsureAuthMiddleware(),
@@ -90,7 +93,9 @@ class AppPages { @@ -90,7 +93,9 @@ class AppPages {
90 GetPage( 93 GetPage(
91 name: _Paths.SETTINGS, 94 name: _Paths.SETTINGS,
92 page: () => SettingsView(), 95 page: () => SettingsView(),
93 - binding: SettingsBinding(), 96 + bindings: [
  97 + SettingsBinding(),
  98 + ],
94 ), 99 ),
95 ], 100 ],
96 ), 101 ),
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 3
  4 +import 'app/modules/splash/controllers/splash_service.dart';
4 import 'app/routes/app_pages.dart'; 5 import 'app/routes/app_pages.dart';
5 import 'services/auth_service.dart'; 6 import 'services/auth_service.dart';
6 7
7 void main() { 8 void main() {
8 runApp( 9 runApp(
9 - GetMaterialApp.router( 10 + GetMaterialApp(
10 title: "Application", 11 title: "Application",
11 initialBinding: BindingsBuilder( 12 initialBinding: BindingsBuilder(
12 () { 13 () {
  14 + Get.put(SplashService());
13 Get.put(AuthService()); 15 Get.put(AuthService());
14 }, 16 },
15 ), 17 ),
16 getPages: AppPages.routes, 18 getPages: AppPages.routes,
  19 + initialRoute: AppPages.INITIAL,
  20 + // builder: (context, child) {
  21 + // return FutureBuilder<void>(
  22 + // key: ValueKey('initFuture'),
  23 + // future: Get.find<SplashService>().init(),
  24 + // builder: (context, snapshot) {
  25 + // if (snapshot.connectionState == ConnectionState.done) {
  26 + // return child ?? SizedBox.shrink();
  27 + // }
  28 + // return SplashView();
  29 + // },
  30 + // );
  31 + // },
17 // routeInformationParser: GetInformationParser( 32 // routeInformationParser: GetInformationParser(
18 // // initialRoute: Routes.HOME, 33 // // initialRoute: Routes.HOME,
19 // ), 34 // ),
@@ -7,12 +7,12 @@ environment: @@ -7,12 +7,12 @@ environment:
7 7
8 dependencies: 8 dependencies:
9 cupertino_icons: ^1.0.2 9 cupertino_icons: ^1.0.2
10 - effective_dart: 1.3.1  
11 # get: ^4.1.4 10 # get: ^4.1.4
12 get: 11 get:
13 path: ../ 12 path: ../
14 flutter: 13 flutter:
15 sdk: flutter 14 sdk: flutter
  15 + flutter_lints: ^1.0.4
16 16
17 dev_dependencies: 17 dev_dependencies:
18 flutter_test: 18 flutter_test:
@@ -12,7 +12,7 @@ export 'http/src/multipart/multipart_file.dart'; @@ -12,7 +12,7 @@ export 'http/src/multipart/multipart_file.dart';
12 export 'http/src/response/response.dart'; 12 export 'http/src/response/response.dart';
13 export 'sockets/sockets.dart'; 13 export 'sockets/sockets.dart';
14 14
15 -abstract class GetConnectInterface with GetLifeCycleBase { 15 +abstract class GetConnectInterface with GetLifeCycleMixin {
16 List<GetSocket>? sockets; 16 List<GetSocket>? sockets;
17 GetHttpClient get httpClient; 17 GetHttpClient get httpClient;
18 18
@@ -100,9 +100,7 @@ class GetConnect extends GetConnectInterface { @@ -100,9 +100,7 @@ class GetConnect extends GetConnectInterface {
100 this.maxAuthRetries = 1, 100 this.maxAuthRetries = 1,
101 this.allowAutoSignedCert = false, 101 this.allowAutoSignedCert = false,
102 this.withCredentials = false, 102 this.withCredentials = false,
103 - }) {  
104 - $configureLifeCycle();  
105 - } 103 + });
106 104
107 bool allowAutoSignedCert; 105 bool allowAutoSignedCert;
108 String userAgent; 106 String userAgent;
@@ -135,8 +133,7 @@ class GetConnect extends GetConnectInterface { @@ -135,8 +133,7 @@ class GetConnect extends GetConnectInterface {
135 baseUrl: baseUrl, 133 baseUrl: baseUrl,
136 trustedCertificates: trustedCertificates, 134 trustedCertificates: trustedCertificates,
137 withCredentials: withCredentials, 135 withCredentials: withCredentials,
138 - findProxy: findProxy  
139 - ); 136 + findProxy: findProxy);
140 137
141 @override 138 @override
142 Future<Response<T>> get<T>( 139 Future<Response<T>> get<T>(
@@ -28,6 +28,7 @@ class GetHttpClient { @@ -28,6 +28,7 @@ class GetHttpClient {
28 int maxAuthRetries; 28 int maxAuthRetries;
29 29
30 bool sendUserAgent; 30 bool sendUserAgent;
  31 + bool sendContentLength;
31 32
32 Decoder? defaultDecoder; 33 Decoder? defaultDecoder;
33 34
@@ -47,6 +48,7 @@ class GetHttpClient { @@ -47,6 +48,7 @@ class GetHttpClient {
47 this.followRedirects = true, 48 this.followRedirects = true,
48 this.maxRedirects = 5, 49 this.maxRedirects = 5,
49 this.sendUserAgent = false, 50 this.sendUserAgent = false,
  51 + this.sendContentLength = true,
50 this.maxAuthRetries = 1, 52 this.maxAuthRetries = 1,
51 bool allowAutoSignedCert = false, 53 bool allowAutoSignedCert = false,
52 this.baseUrl, 54 this.baseUrl,
@@ -111,7 +113,7 @@ class GetHttpClient { @@ -111,7 +113,7 @@ class GetHttpClient {
111 113
112 if (body is FormData) { 114 if (body is FormData) {
113 bodyBytes = await body.toBytes(); 115 bodyBytes = await body.toBytes();
114 - headers['content-length'] = bodyBytes.length.toString(); 116 + _setContentLenght(headers, bodyBytes.length);
115 headers['content-type'] = 117 headers['content-type'] =
116 'multipart/form-data; boundary=${body.boundary}'; 118 'multipart/form-data; boundary=${body.boundary}';
117 } else if (contentType != null && 119 } else if (contentType != null &&
@@ -124,21 +126,21 @@ class GetHttpClient { @@ -124,21 +126,21 @@ class GetHttpClient {
124 }); 126 });
125 var formData = parts.join('&'); 127 var formData = parts.join('&');
126 bodyBytes = utf8.encode(formData); 128 bodyBytes = utf8.encode(formData);
127 - headers['content-length'] = bodyBytes.length.toString(); 129 + _setContentLenght(headers, bodyBytes.length);
128 headers['content-type'] = contentType; 130 headers['content-type'] = contentType;
129 } else if (body is Map || body is List) { 131 } else if (body is Map || body is List) {
130 var jsonString = json.encode(body); 132 var jsonString = json.encode(body);
131 -  
132 bodyBytes = utf8.encode(jsonString); 133 bodyBytes = utf8.encode(jsonString);
133 - headers['content-length'] = bodyBytes.length.toString(); 134 + _setContentLenght(headers, bodyBytes.length);
134 headers['content-type'] = contentType ?? defaultContentType; 135 headers['content-type'] = contentType ?? defaultContentType;
135 } else if (body is String) { 136 } else if (body is String) {
136 bodyBytes = utf8.encode(body); 137 bodyBytes = utf8.encode(body);
137 - headers['content-length'] = bodyBytes.length.toString(); 138 + _setContentLenght(headers, bodyBytes.length);
  139 +
138 headers['content-type'] = contentType ?? defaultContentType; 140 headers['content-type'] = contentType ?? defaultContentType;
139 } else if (body == null) { 141 } else if (body == null) {
  142 + _setContentLenght(headers, 0);
140 headers['content-type'] = contentType ?? defaultContentType; 143 headers['content-type'] = contentType ?? defaultContentType;
141 - headers['content-length'] = '0';  
142 } else { 144 } else {
143 if (!errorSafety) { 145 if (!errorSafety) {
144 throw UnexpectedFormat('body cannot be ${body.runtimeType}'); 146 throw UnexpectedFormat('body cannot be ${body.runtimeType}');
@@ -162,6 +164,12 @@ class GetHttpClient { @@ -162,6 +164,12 @@ class GetHttpClient {
162 ); 164 );
163 } 165 }
164 166
  167 + void _setContentLenght(Map<String, String> headers, int contentLength) {
  168 + if (sendContentLength) {
  169 + headers['content-length'] = '$contentLength';
  170 + }
  171 + }
  172 +
165 Stream<List<int>> _trackProgress( 173 Stream<List<int>> _trackProgress(
166 List<int> bodyBytes, 174 List<int> bodyBytes,
167 Progress? uploadProgress, 175 Progress? uploadProgress,
@@ -14,6 +14,7 @@ class HttpRequestImpl implements HttpRequestBase { @@ -14,6 +14,7 @@ class HttpRequestImpl implements HttpRequestBase {
14 bool allowAutoSignedCert = true, 14 bool allowAutoSignedCert = true,
15 List<TrustedCertificate>? trustedCertificates, 15 List<TrustedCertificate>? trustedCertificates,
16 this.withCredentials = false, 16 this.withCredentials = false,
  17 + String Function(Uri url)? findProxy,
17 }); 18 });
18 19
19 /// The currently active XHRs. 20 /// The currently active XHRs.
@@ -110,11 +110,12 @@ class BaseWebSocket { @@ -110,11 +110,12 @@ class BaseWebSocket {
110 return true; 110 return true;
111 }; 111 };
112 112
113 - var request = await client.getUrl(Uri.parse(url));  
114 - request.headers.add('Connection', 'Upgrade');  
115 - request.headers.add('Upgrade', 'websocket');  
116 - request.headers.add('Sec-WebSocket-Version', '13');  
117 - request.headers.add('Sec-WebSocket-Key', key.toLowerCase()); 113 + var request = await client.getUrl(Uri.parse(url))
  114 + ..headers.add('Connection', 'Upgrade')
  115 + ..headers.add('Upgrade', 'websocket')
  116 + ..headers.add('Cache-Control', 'no-cache')
  117 + ..headers.add('Sec-WebSocket-Version', '13')
  118 + ..headers.add('Sec-WebSocket-Key', key.toLowerCase());
118 119
119 var response = await request.close(); 120 var response = await request.close();
120 // ignore: close_sinks 121 // ignore: close_sinks
1 typedef ValueUpdater<T> = T Function(); 1 typedef ValueUpdater<T> = T Function();
  2 +/// This allows a value of type T or T?
  3 +/// to be treated as a value of type T?.
  4 +///
  5 +/// We use this so that APIs that have become
  6 +/// non-nullable can still be used with `!` and `?`
  7 +/// to support older versions of the API as well.
  8 +T? ambiguate<T>(T? value) => value;
  1 +// ignore: one_member_abstracts
1 import 'get_instance.dart'; 2 import 'get_instance.dart';
2 3
  4 +// ignore: one_member_abstracts
  5 +abstract class BindingsInterface<T> {
  6 + T dependencies();
  7 +}
  8 +
3 /// [Bindings] should be extended or implemented. 9 /// [Bindings] should be extended or implemented.
4 /// When using `GetMaterialApp`, all `GetPage`s and navigation 10 /// When using `GetMaterialApp`, all `GetPage`s and navigation
5 /// methods (like Get.to()) have a `binding` property that takes an 11 /// methods (like Get.to()) have a `binding` property that takes an
6 /// instance of Bindings to manage the 12 /// instance of Bindings to manage the
7 /// dependencies() (via Get.put()) for the Route you are opening. 13 /// dependencies() (via Get.put()) for the Route you are opening.
8 // ignore: one_member_abstracts 14 // ignore: one_member_abstracts
9 -abstract class Bindings { 15 +@Deprecated('Use Binding instead')
  16 +abstract class Bindings extends BindingsInterface<void> {
  17 + @override
10 void dependencies(); 18 void dependencies();
11 } 19 }
12 20
@@ -58,8 +66,4 @@ class BindingsBuilder<T> extends Bindings { @@ -58,8 +66,4 @@ class BindingsBuilder<T> extends Bindings {
58 } 66 }
59 } 67 }
60 68
61 -// abstract class INavigation {}  
62 -// typedef Snack = Function();  
63 -// typedef Modal = Function();  
64 -// typedef Route = Function();  
65 typedef BindingBuilderCallback = void Function(); 69 typedef BindingBuilderCallback = void Function();
1 -import '../../get_core/src/get_interface.dart';  
2 import '../../route_manager.dart'; 1 import '../../route_manager.dart';
3 import 'get_instance.dart'; 2 import 'get_instance.dart';
4 3
@@ -162,30 +162,25 @@ class GetInstance { @@ -162,30 +162,25 @@ class GetInstance {
162 }) { 162 }) {
163 final key = _getKey(S, name); 163 final key = _getKey(S, name);
164 164
  165 + _InstanceBuilderFactory<S>? dep;
165 if (_singl.containsKey(key)) { 166 if (_singl.containsKey(key)) {
166 - final dep = _singl[key];  
167 - if (dep != null && dep.isDirty) {  
168 - _singl[key] = _InstanceBuilderFactory<S>(  
169 - isSingleton,  
170 - builder,  
171 - permanent,  
172 - false,  
173 - fenix,  
174 - name,  
175 - lateRemove: dep as _InstanceBuilderFactory<S>,  
176 - );  
177 - } 167 + final _dep = _singl[key];
  168 + if (_dep == null || !_dep.isDirty) {
  169 + return;
178 } else { 170 } else {
  171 + dep = _dep as _InstanceBuilderFactory<S>;
  172 + }
  173 + }
179 _singl[key] = _InstanceBuilderFactory<S>( 174 _singl[key] = _InstanceBuilderFactory<S>(
180 - isSingleton,  
181 - builder,  
182 - permanent,  
183 - false,  
184 - fenix,  
185 - name, 175 + isSingleton: isSingleton,
  176 + builderFunc: builder,
  177 + permanent: permanent,
  178 + isInit: false,
  179 + fenix: fenix,
  180 + tag: name,
  181 + lateRemove: dep,
186 ); 182 );
187 } 183 }
188 - }  
189 184
190 /// Initializes the dependencies for a Class Instance [S] (or tag), 185 /// Initializes the dependencies for a Class Instance [S] (or tag),
191 /// If its a Controller, it starts the lifecycle process. 186 /// If its a Controller, it starts the lifecycle process.
@@ -205,7 +200,8 @@ class GetInstance { @@ -205,7 +200,8 @@ class GetInstance {
205 if (_singl[key]!.isSingleton!) { 200 if (_singl[key]!.isSingleton!) {
206 _singl[key]!.isInit = true; 201 _singl[key]!.isInit = true;
207 if (Get.smartManagement != SmartManagement.onlyBuilder) { 202 if (Get.smartManagement != SmartManagement.onlyBuilder) {
208 - RouterReportManager.reportDependencyLinkedToRoute(_getKey(S, name)); 203 + RouterReportManager.instance
  204 + .reportDependencyLinkedToRoute(_getKey(S, name));
209 } 205 }
210 } 206 }
211 } 207 }
@@ -249,7 +245,7 @@ class GetInstance { @@ -249,7 +245,7 @@ class GetInstance {
249 S _startController<S>({String? tag}) { 245 S _startController<S>({String? tag}) {
250 final key = _getKey(S, tag); 246 final key = _getKey(S, tag);
251 final i = _singl[key]!.getDependency() as S; 247 final i = _singl[key]!.getDependency() as S;
252 - if (i is GetLifeCycleBase) { 248 + if (i is GetLifeCycleMixin) {
253 i.onStart(); 249 i.onStart();
254 if (tag == null) { 250 if (tag == null) {
255 Get.log('Instance "$S" has been initialized'); 251 Get.log('Instance "$S" has been initialized');
@@ -257,7 +253,7 @@ class GetInstance { @@ -257,7 +253,7 @@ class GetInstance {
257 Get.log('Instance "$S" with tag "$tag" has been initialized'); 253 Get.log('Instance "$S" with tag "$tag" has been initialized');
258 } 254 }
259 if (!_singl[key]!.isSingleton!) { 255 if (!_singl[key]!.isSingleton!) {
260 - RouterReportManager.appendRouteByCreate(i); 256 + RouterReportManager.instance.appendRouteByCreate(i);
261 } 257 }
262 } 258 }
263 return i; 259 return i;
@@ -323,7 +319,7 @@ class GetInstance { @@ -323,7 +319,7 @@ class GetInstance {
323 {@deprecated bool clearFactory = true, bool clearRouteBindings = true}) { 319 {@deprecated bool clearFactory = true, bool clearRouteBindings = true}) {
324 // if (clearFactory) _factory.clear(); 320 // if (clearFactory) _factory.clear();
325 // deleteAll(force: true); 321 // deleteAll(force: true);
326 - if (clearRouteBindings) RouterReportManager.clearRouteKeys(); 322 + if (clearRouteBindings) RouterReportManager.instance.clearRouteKeys();
327 _singl.clear(); 323 _singl.clear();
328 324
329 return true; 325 return true;
@@ -378,7 +374,7 @@ class GetInstance { @@ -378,7 +374,7 @@ class GetInstance {
378 return false; 374 return false;
379 } 375 }
380 376
381 - if (i is GetLifeCycleBase) { 377 + if (i is GetLifeCycleMixin) {
382 i.onDelete(); 378 i.onDelete();
383 Get.log('"$newKey" onDelete() called'); 379 Get.log('"$newKey" onDelete() called');
384 } 380 }
@@ -451,7 +447,7 @@ class GetInstance { @@ -451,7 +447,7 @@ class GetInstance {
451 return; 447 return;
452 } 448 }
453 449
454 - if (i is GetLifeCycleBase) { 450 + if (i is GetLifeCycleMixin) {
455 i.onDelete(); 451 i.onDelete();
456 Get.log('"$newKey" onDelete() called'); 452 Get.log('"$newKey" onDelete() called');
457 } 453 }
@@ -518,14 +514,14 @@ class _InstanceBuilderFactory<S> { @@ -518,14 +514,14 @@ class _InstanceBuilderFactory<S> {
518 514
519 String? tag; 515 String? tag;
520 516
521 - _InstanceBuilderFactory(  
522 - this.isSingleton,  
523 - this.builderFunc,  
524 - this.permanent,  
525 - this.isInit,  
526 - this.fenix,  
527 - this.tag, {  
528 - this.lateRemove, 517 + _InstanceBuilderFactory({
  518 + required this.isSingleton,
  519 + required this.builderFunc,
  520 + required this.permanent,
  521 + required this.isInit,
  522 + required this.fenix,
  523 + required this.tag,
  524 + required this.lateRemove,
529 }); 525 });
530 526
531 void _showInitLog() { 527 void _showInitLog() {
1 -import '../../get_core/get_core.dart'; 1 +import 'package:flutter/foundation.dart';
  2 +import 'package:flutter/scheduler.dart';
2 3
3 -/// Special callable class to keep the contract of a regular method, and avoid  
4 -/// overrides if you extend the class that uses it, as Dart has no final  
5 -/// methods.  
6 -/// Used in `DisposableInterface` to avoid the danger of overriding onStart.  
7 -class InternalFinalCallback<T> {  
8 - ValueUpdater<T>? _callback;  
9 -  
10 - InternalFinalCallback({ValueUpdater<T>? callback}) : _callback = callback;  
11 -  
12 - T call() => _callback!.call();  
13 -} 4 +import '../../get.dart';
14 5
15 /// The [GetLifeCycle] 6 /// The [GetLifeCycle]
16 /// 7 ///
@@ -21,26 +12,15 @@ class InternalFinalCallback<T> { @@ -21,26 +12,15 @@ class InternalFinalCallback<T> {
21 /// } 12 /// }
22 /// } 13 /// }
23 /// ``` 14 /// ```
24 -mixin GetLifeCycleBase {  
25 - /// Called at the exact moment the widget is allocated in memory.  
26 - /// It uses an internal "callable" type, to avoid any @overrides in subclases.  
27 - /// This method should be internal and is required to define the  
28 - /// lifetime cycle of the subclass.  
29 - final onStart = InternalFinalCallback<void>();  
30 -  
31 - // /// The `configureLifeCycle` works as a constructor for the [GetLifeCycle]  
32 - // ///  
33 - // /// This method must be invoked in the constructor of the implementation  
34 - // void configureLifeCycle() {  
35 - // if (_initialized) return;  
36 - // }  
37 -  
38 - /// Internal callback that starts the cycle of this controller.  
39 - final onDelete = InternalFinalCallback<void>();  
40 - 15 +mixin GetLifeCycleMixin {
41 /// Called immediately after the widget is allocated in memory. 16 /// Called immediately after the widget is allocated in memory.
42 /// You might use this to initialize something for the controller. 17 /// You might use this to initialize something for the controller.
43 - void onInit() {} 18 + @protected
  19 + @mustCallSuper
  20 + void onInit() {
  21 + ambiguate(SchedulerBinding.instance)
  22 + ?.addPostFrameCallback((_) => onReady());
  23 + }
44 24
45 /// Called 1 frame after onInit(). It is the perfect place to enter 25 /// Called 1 frame after onInit(). It is the perfect place to enter
46 /// navigation events, like snackbar, dialogs, or a new route, or 26 /// navigation events, like snackbar, dialogs, or a new route, or
@@ -60,8 +40,15 @@ mixin GetLifeCycleBase { @@ -60,8 +40,15 @@ mixin GetLifeCycleBase {
60 /// Checks whether the controller has already been initialized. 40 /// Checks whether the controller has already been initialized.
61 bool get initialized => _initialized; 41 bool get initialized => _initialized;
62 42
63 - // Internal callback that starts the cycle of this controller.  
64 - void _onStart() { 43 + /// Called at the exact moment the widget is allocated in memory.
  44 + /// It uses an internal "callable" type, to avoid any @overrides in subclases.
  45 + /// This method should be internal and is required to define the
  46 + /// lifetime cycle of the subclass.
  47 + // @protected
  48 + @mustCallSuper
  49 + @nonVirtual
  50 + void onStart() {
  51 + // _checkIfAlreadyConfigured();
65 if (_initialized) return; 52 if (_initialized) return;
66 onInit(); 53 onInit();
67 _initialized = true; 54 _initialized = true;
@@ -72,33 +59,31 @@ mixin GetLifeCycleBase { @@ -72,33 +59,31 @@ mixin GetLifeCycleBase {
72 /// Checks whether the controller has already been closed. 59 /// Checks whether the controller has already been closed.
73 bool get isClosed => _isClosed; 60 bool get isClosed => _isClosed;
74 61
75 - // Internal callback that starts the cycle of this controller.  
76 - void _onDelete() { 62 + // Called when the controller is removed from memory.
  63 + @mustCallSuper
  64 + @nonVirtual
  65 + void onDelete() {
77 if (_isClosed) return; 66 if (_isClosed) return;
78 _isClosed = true; 67 _isClosed = true;
79 onClose(); 68 onClose();
80 } 69 }
81 70
82 - void $configureLifeCycle() {  
83 - _checkIfAlreadyConfigured();  
84 - onStart._callback = _onStart;  
85 - onDelete._callback = _onDelete;  
86 - }  
87 -  
88 - void _checkIfAlreadyConfigured() {  
89 - if (_initialized) {  
90 - throw """You can only call configureLifeCycle once.  
91 -The proper place to insert it is in your class's constructor  
92 -that inherits GetLifeCycle.""";  
93 - }  
94 - }  
95 -}  
96 -  
97 -abstract class GetLifeCycle with GetLifeCycleBase {  
98 - GetLifeCycle() {  
99 - $configureLifeCycle();  
100 - } 71 +// void _checkIfAlreadyConfigured() {
  72 +// if (_initialized) {
  73 +// throw """You can only call configureLifeCycle once.
  74 +// The proper place to insert it is in your class's constructor
  75 +// that inherits GetLifeCycle.""";
  76 +// }
  77 +// }
101 } 78 }
102 79
103 /// Allow track difference between GetxServices and GetxControllers 80 /// Allow track difference between GetxServices and GetxControllers
104 mixin GetxServiceMixin {} 81 mixin GetxServiceMixin {}
  82 +
  83 +/// Unlike GetxController, which serves to control events on each of its pages,
  84 +/// GetxService is not automatically disposed (nor can be removed with
  85 +/// Get.delete()).
  86 +/// It is ideal for situations where, once started, that service will
  87 +/// remain in memory, such as Auth control for example. Only way to remove
  88 +/// it is Get.reset().
  89 +abstract class GetxService with GetLifeCycleMixin, GetxServiceMixin {}
@@ -2,10 +2,6 @@ library get_navigation; @@ -2,10 +2,6 @@ library get_navigation;
2 2
3 export 'src/bottomsheet/bottomsheet.dart'; 3 export 'src/bottomsheet/bottomsheet.dart';
4 export 'src/extension_navigation.dart'; 4 export 'src/extension_navigation.dart';
5 -export 'src/nav2/get_information_parser.dart';  
6 -export 'src/nav2/get_nav_config.dart';  
7 -export 'src/nav2/get_router_delegate.dart';  
8 -export 'src/nav2/router_outlet.dart';  
9 export 'src/root/get_cupertino_app.dart'; 5 export 'src/root/get_cupertino_app.dart';
10 export 'src/root/get_material_app.dart'; 6 export 'src/root/get_material_app.dart';
11 export 'src/root/internacionalization.dart'; 7 export 'src/root/internacionalization.dart';
@@ -13,6 +9,7 @@ export 'src/root/root_controller.dart'; @@ -13,6 +9,7 @@ export 'src/root/root_controller.dart';
13 export 'src/routes/custom_transition.dart'; 9 export 'src/routes/custom_transition.dart';
14 export 'src/routes/default_route.dart'; 10 export 'src/routes/default_route.dart';
15 export 'src/routes/get_route.dart'; 11 export 'src/routes/get_route.dart';
  12 +export 'src/routes/index.dart';
16 export 'src/routes/observers/route_observer.dart'; 13 export 'src/routes/observers/route_observer.dart';
17 export 'src/routes/route_middleware.dart'; 14 export 'src/routes/route_middleware.dart';
18 export 'src/routes/transitions_type.dart'; 15 export 'src/routes/transitions_type.dart';
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
  2 +
2 import '../../../get.dart'; 3 import '../../../get.dart';
3 import '../router_report.dart'; 4 import '../router_report.dart';
4 5
@@ -21,7 +22,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { @@ -21,7 +22,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
21 this.enterBottomSheetDuration = const Duration(milliseconds: 250), 22 this.enterBottomSheetDuration = const Duration(milliseconds: 250),
22 this.exitBottomSheetDuration = const Duration(milliseconds: 200), 23 this.exitBottomSheetDuration = const Duration(milliseconds: 200),
23 }) : super(settings: settings) { 24 }) : super(settings: settings) {
24 - RouterReportManager.reportCurrentRoute(this); 25 + RouterReportManager.instance.reportCurrentRoute(this);
25 } 26 }
26 final bool? isPersistent; 27 final bool? isPersistent;
27 final WidgetBuilder? builder; 28 final WidgetBuilder? builder;
@@ -56,7 +57,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { @@ -56,7 +57,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
56 57
57 @override 58 @override
58 void dispose() { 59 void dispose() {
59 - RouterReportManager.reportRouteDispose(this); 60 + RouterReportManager.instance.reportRouteDispose(this);
60 super.dispose(); 61 super.dispose();
61 } 62 }
62 63
1 import 'package:flutter/widgets.dart'; 1 import 'package:flutter/widgets.dart';
  2 +
2 import '../router_report.dart'; 3 import '../router_report.dart';
3 4
4 class GetDialogRoute<T> extends PopupRoute<T> { 5 class GetDialogRoute<T> extends PopupRoute<T> {
@@ -17,7 +18,7 @@ class GetDialogRoute<T> extends PopupRoute<T> { @@ -17,7 +18,7 @@ class GetDialogRoute<T> extends PopupRoute<T> {
17 _transitionDuration = transitionDuration, 18 _transitionDuration = transitionDuration,
18 _transitionBuilder = transitionBuilder, 19 _transitionBuilder = transitionBuilder,
19 super(settings: settings) { 20 super(settings: settings) {
20 - RouterReportManager.reportCurrentRoute(this); 21 + RouterReportManager.instance.reportCurrentRoute(this);
21 } 22 }
22 23
23 final RoutePageBuilder widget; 24 final RoutePageBuilder widget;
@@ -28,7 +29,7 @@ class GetDialogRoute<T> extends PopupRoute<T> { @@ -28,7 +29,7 @@ class GetDialogRoute<T> extends PopupRoute<T> {
28 29
29 @override 30 @override
30 void dispose() { 31 void dispose() {
31 - RouterReportManager.reportRouteDispose(this); 32 + RouterReportManager.instance.reportRouteDispose(this);
32 super.dispose(); 33 super.dispose();
33 } 34 }
34 35
@@ -8,15 +8,11 @@ import '../../get_instance/src/bindings_interface.dart'; @@ -8,15 +8,11 @@ import '../../get_instance/src/bindings_interface.dart';
8 import '../../get_utils/get_utils.dart'; 8 import '../../get_utils/get_utils.dart';
9 import '../get_navigation.dart'; 9 import '../get_navigation.dart';
10 import 'dialog/dialog_route.dart'; 10 import 'dialog/dialog_route.dart';
11 -import 'root/parse_route.dart';  
12 -import 'root/root_controller.dart';  
13 -import 'routes/transitions_type.dart';  
14 -import 'snackbar/snackbar_controller.dart';  
15 11
16 /// It replaces the Flutter Navigator, but needs no context. 12 /// It replaces the Flutter Navigator, but needs no context.
17 /// You can to use navigator.push(YourRoute()) rather 13 /// You can to use navigator.push(YourRoute()) rather
18 /// Navigator.push(context, YourRoute()); 14 /// Navigator.push(context, YourRoute());
19 -NavigatorState? get navigator => GetNavigation(Get).key.currentState; 15 +NavigatorState? get navigator => GetNavigationExt(Get).key.currentState;
20 16
21 extension ExtensionBottomSheet on GetInterface { 17 extension ExtensionBottomSheet on GetInterface {
22 Future<T?> bottomSheet<T>( 18 Future<T?> bottomSheet<T>(
@@ -80,6 +76,7 @@ extension ExtensionDialog on GetInterface { @@ -80,6 +76,7 @@ extension ExtensionDialog on GetInterface {
80 Curve? transitionCurve, 76 Curve? transitionCurve,
81 String? name, 77 String? name,
82 RouteSettings? routeSettings, 78 RouteSettings? routeSettings,
  79 + String? id,
83 }) { 80 }) {
84 assert(debugCheckHasMaterialLocalizations(context!)); 81 assert(debugCheckHasMaterialLocalizations(context!));
85 82
@@ -112,12 +109,13 @@ extension ExtensionDialog on GetInterface { @@ -112,12 +109,13 @@ extension ExtensionDialog on GetInterface {
112 navigatorKey: navigatorKey, 109 navigatorKey: navigatorKey,
113 routeSettings: 110 routeSettings:
114 routeSettings ?? RouteSettings(arguments: arguments, name: name), 111 routeSettings ?? RouteSettings(arguments: arguments, name: name),
  112 + id: id,
115 ); 113 );
116 } 114 }
117 115
118 /// Api from showGeneralDialog with no context 116 /// Api from showGeneralDialog with no context
119 - Future<T?> generalDialog<T>({  
120 - required RoutePageBuilder pageBuilder, 117 + Future<T?> generalDialog<T>(
  118 + {required RoutePageBuilder pageBuilder,
121 bool barrierDismissible = false, 119 bool barrierDismissible = false,
122 String? barrierLabel, 120 String? barrierLabel,
123 Color barrierColor = const Color(0x80000000), 121 Color barrierColor = const Color(0x80000000),
@@ -125,9 +123,10 @@ extension ExtensionDialog on GetInterface { @@ -125,9 +123,10 @@ extension ExtensionDialog on GetInterface {
125 RouteTransitionsBuilder? transitionBuilder, 123 RouteTransitionsBuilder? transitionBuilder,
126 GlobalKey<NavigatorState>? navigatorKey, 124 GlobalKey<NavigatorState>? navigatorKey,
127 RouteSettings? routeSettings, 125 RouteSettings? routeSettings,
128 - }) { 126 + String? id}) {
129 assert(!barrierDismissible || barrierLabel != null); 127 assert(!barrierDismissible || barrierLabel != null);
130 - final nav = navigatorKey?.currentState ?? 128 + final key = navigatorKey ?? Get.nestedKey(id)?.navigatorKey;
  129 + final nav = key?.currentState ??
131 Navigator.of(overlayContext!, 130 Navigator.of(overlayContext!,
132 rootNavigator: 131 rootNavigator:
133 true); //overlay context will always return the root navigator 132 true); //overlay context will always return the root navigator
@@ -150,6 +149,7 @@ extension ExtensionDialog on GetInterface { @@ -150,6 +149,7 @@ extension ExtensionDialog on GetInterface {
150 EdgeInsetsGeometry? titlePadding, 149 EdgeInsetsGeometry? titlePadding,
151 TextStyle? titleStyle, 150 TextStyle? titleStyle,
152 Widget? content, 151 Widget? content,
  152 + String? id,
153 EdgeInsetsGeometry? contentPadding, 153 EdgeInsetsGeometry? contentPadding,
154 VoidCallback? onConfirm, 154 VoidCallback? onConfirm,
155 VoidCallback? onCancel, 155 VoidCallback? onCancel,
@@ -194,7 +194,7 @@ extension ExtensionDialog on GetInterface { @@ -194,7 +194,7 @@ extension ExtensionDialog on GetInterface {
194 color: buttonColor ?? theme.colorScheme.secondary, 194 color: buttonColor ?? theme.colorScheme.secondary,
195 width: 2, 195 width: 2,
196 style: BorderStyle.solid), 196 style: BorderStyle.solid),
197 - borderRadius: BorderRadius.circular(100)), 197 + borderRadius: BorderRadius.circular(radius)),
198 ), 198 ),
199 onPressed: () { 199 onPressed: () {
200 onCancel?.call(); 200 onCancel?.call();
@@ -217,7 +217,7 @@ extension ExtensionDialog on GetInterface { @@ -217,7 +217,7 @@ extension ExtensionDialog on GetInterface {
217 tapTargetSize: MaterialTapTargetSize.shrinkWrap, 217 tapTargetSize: MaterialTapTargetSize.shrinkWrap,
218 backgroundColor: buttonColor ?? theme.colorScheme.secondary, 218 backgroundColor: buttonColor ?? theme.colorScheme.secondary,
219 shape: RoundedRectangleBorder( 219 shape: RoundedRectangleBorder(
220 - borderRadius: BorderRadius.circular(100)), 220 + borderRadius: BorderRadius.circular(radius)),
221 ), 221 ),
222 child: Text( 222 child: Text(
223 textConfirm ?? "Ok", 223 textConfirm ?? "Ok",
@@ -271,6 +271,7 @@ extension ExtensionDialog on GetInterface { @@ -271,6 +271,7 @@ extension ExtensionDialog on GetInterface {
271 : baseAlertDialog, 271 : baseAlertDialog,
272 barrierDismissible: barrierDismissible, 272 barrierDismissible: barrierDismissible,
273 navigatorKey: navigatorKey, 273 navigatorKey: navigatorKey,
  274 + id: id,
274 ); 275 );
275 } 276 }
276 } 277 }
@@ -357,7 +358,7 @@ extension ExtensionSnackbar on GetInterface { @@ -357,7 +358,7 @@ extension ExtensionSnackbar on GetInterface {
357 if (instantInit) { 358 if (instantInit) {
358 controller.show(); 359 controller.show();
359 } else { 360 } else {
360 - SchedulerBinding.instance!.addPostFrameCallback((_) { 361 + ambiguate(SchedulerBinding.instance)!.addPostFrameCallback((_) {
361 controller.show(); 362 controller.show();
362 }); 363 });
363 } 364 }
@@ -468,7 +469,7 @@ extension ExtensionSnackbar on GetInterface { @@ -468,7 +469,7 @@ extension ExtensionSnackbar on GetInterface {
468 controller.show(); 469 controller.show();
469 } else { 470 } else {
470 //routing.isSnackbar = true; 471 //routing.isSnackbar = true;
471 - SchedulerBinding.instance!.addPostFrameCallback((_) { 472 + ambiguate(SchedulerBinding.instance)!.addPostFrameCallback((_) {
472 controller.show(); 473 controller.show();
473 }); 474 });
474 } 475 }
@@ -476,7 +477,7 @@ extension ExtensionSnackbar on GetInterface { @@ -476,7 +477,7 @@ extension ExtensionSnackbar on GetInterface {
476 } 477 }
477 } 478 }
478 479
479 -extension GetNavigation on GetInterface { 480 +extension GetNavigationExt on GetInterface {
480 /// **Navigation.push()** shortcut.<br><br> 481 /// **Navigation.push()** shortcut.<br><br>
481 /// 482 ///
482 /// Pushes a new `page` to the stack 483 /// Pushes a new `page` to the stack
@@ -501,9 +502,8 @@ extension GetNavigation on GetInterface { @@ -501,9 +502,8 @@ extension GetNavigation on GetInterface {
501 /// 502 ///
502 /// By default, GetX will prevent you from push a route that you already in, 503 /// By default, GetX will prevent you from push a route that you already in,
503 /// if you want to push anyway, set [preventDuplicates] to false 504 /// if you want to push anyway, set [preventDuplicates] to false
504 - Future<T?>? to<T>(  
505 - dynamic page, {  
506 - bool? opaque, 505 + Future<T?>? to<T>(Widget Function() page,
  506 + {bool? opaque,
507 Transition? transition, 507 Transition? transition,
508 Curve? curve, 508 Curve? curve,
509 Duration? duration, 509 Duration? duration,
@@ -511,54 +511,53 @@ extension GetNavigation on GetInterface { @@ -511,54 +511,53 @@ extension GetNavigation on GetInterface {
511 String? routeName, 511 String? routeName,
512 bool fullscreenDialog = false, 512 bool fullscreenDialog = false,
513 dynamic arguments, 513 dynamic arguments,
514 - Bindings? binding, 514 + List<BindingsInterface> bindings = const [],
515 bool preventDuplicates = true, 515 bool preventDuplicates = true,
516 bool? popGesture, 516 bool? popGesture,
  517 + bool showCupertinoParallax = true,
517 double Function(BuildContext context)? gestureWidth, 518 double Function(BuildContext context)? gestureWidth,
518 - }) {  
519 - // var routeName = "/${page.runtimeType}";  
520 - routeName ??= "/${page.runtimeType}";  
521 - routeName = _cleanRouteName(routeName);  
522 - if (preventDuplicates && routeName == currentRoute) {  
523 - return null;  
524 - }  
525 - return global(id).currentState?.push<T>(  
526 - GetPageRoute<T>(  
527 - opaque: opaque ?? true,  
528 - page: _resolvePage(page, 'to'), 519 + bool rebuildStack = true,
  520 + PreventDuplicateHandlingMode preventDuplicateHandlingMode =
  521 + PreventDuplicateHandlingMode.ReorderRoutes}) {
  522 + return searchDelegate(id).to(
  523 + page,
  524 + opaque: opaque,
  525 + transition: transition,
  526 + curve: curve,
  527 + duration: duration,
  528 + id: id,
529 routeName: routeName, 529 routeName: routeName,
530 - gestureWidth: gestureWidth,  
531 - settings: RouteSettings(  
532 - name: routeName,  
533 - arguments: arguments,  
534 - ),  
535 - popGesture: popGesture ?? defaultPopGesture,  
536 - transition: transition ?? defaultTransition,  
537 - curve: curve ?? defaultTransitionCurve,  
538 fullscreenDialog: fullscreenDialog, 530 fullscreenDialog: fullscreenDialog,
539 - binding: binding,  
540 - transitionDuration: duration ?? defaultTransitionDuration,  
541 - ), 531 + arguments: arguments,
  532 + bindings: bindings,
  533 + preventDuplicates: preventDuplicates,
  534 + popGesture: popGesture,
  535 + showCupertinoParallax: showCupertinoParallax,
  536 + gestureWidth: gestureWidth,
  537 + rebuildStack: rebuildStack,
  538 + preventDuplicateHandlingMode: preventDuplicateHandlingMode,
542 ); 539 );
543 } 540 }
544 541
545 - GetPageBuilder _resolvePage(dynamic page, String method) {  
546 - if (page is GetPageBuilder) {  
547 - return page;  
548 - } else if (page is Widget) {  
549 - Get.log(  
550 - '''WARNING, consider using: "Get.$method(() => Page())" instead of "Get.$method(Page())".  
551 -Using a widget function instead of a widget fully guarantees that the widget and its controllers will be removed from memory when they are no longer used.  
552 - ''');  
553 - return () => page;  
554 - } else if (page is String) {  
555 - throw '''Unexpected String,  
556 -use toNamed() instead''';  
557 - } else {  
558 - throw '''Unexpected format,  
559 -you can only use widgets and widget functions here''';  
560 - }  
561 - } 542 +// GetPageBuilder _resolvePage(dynamic page, String method) {
  543 +// if (page is GetPageBuilder) {
  544 +// return page;
  545 +// } else if (page is Widget) {
  546 +// Get.log(
  547 +// '''WARNING, consider using: "Get.$method(() => Page())"
  548 +//instead of "Get.$method(Page())".
  549 +// Using a widget function instead of a widget fully guarantees that the widget
  550 +//and its controllers will be removed from memory when they are no longer used.
  551 +// ''');
  552 +// return () => page;
  553 +// } else if (page is String) {
  554 +// throw '''Unexpected String,
  555 +// use toNamed() instead''';
  556 +// } else {
  557 +// throw '''Unexpected format,
  558 +// you can only use widgets and widget functions here''';
  559 +// }
  560 +// }
562 561
563 /// **Navigation.pushNamed()** shortcut.<br><br> 562 /// **Navigation.pushNamed()** shortcut.<br><br>
564 /// 563 ///
@@ -579,22 +578,25 @@ you can only use widgets and widget functions here'''; @@ -579,22 +578,25 @@ you can only use widgets and widget functions here''';
579 Future<T?>? toNamed<T>( 578 Future<T?>? toNamed<T>(
580 String page, { 579 String page, {
581 dynamic arguments, 580 dynamic arguments,
582 - int? id, 581 + dynamic id,
583 bool preventDuplicates = true, 582 bool preventDuplicates = true,
584 Map<String, String>? parameters, 583 Map<String, String>? parameters,
585 }) { 584 }) {
586 - if (preventDuplicates && page == currentRoute) {  
587 - return null;  
588 - } 585 + // if (preventDuplicates && page == currentRoute) {
  586 + // return null;
  587 + // }
589 588
590 if (parameters != null) { 589 if (parameters != null) {
591 final uri = Uri(path: page, queryParameters: parameters); 590 final uri = Uri(path: page, queryParameters: parameters);
592 page = uri.toString(); 591 page = uri.toString();
593 } 592 }
594 593
595 - return global(id).currentState?.pushNamed<T>( 594 + return searchDelegate(id).toNamed(
596 page, 595 page,
597 arguments: arguments, 596 arguments: arguments,
  597 + id: id,
  598 + preventDuplicates: preventDuplicates,
  599 + parameters: parameters,
598 ); 600 );
599 } 601 }
600 602
@@ -618,20 +620,22 @@ you can only use widgets and widget functions here'''; @@ -618,20 +620,22 @@ you can only use widgets and widget functions here''';
618 String page, { 620 String page, {
619 dynamic arguments, 621 dynamic arguments,
620 int? id, 622 int? id,
621 - bool preventDuplicates = true,  
622 Map<String, String>? parameters, 623 Map<String, String>? parameters,
623 }) { 624 }) {
624 - if (preventDuplicates && page == currentRoute) {  
625 - return null;  
626 - } 625 + // if (preventDuplicates && page == currentRoute) {
  626 + // return null;
  627 + // }
627 628
628 if (parameters != null) { 629 if (parameters != null) {
629 final uri = Uri(path: page, queryParameters: parameters); 630 final uri = Uri(path: page, queryParameters: parameters);
630 page = uri.toString(); 631 page = uri.toString();
631 } 632 }
632 - return global(id).currentState?.pushReplacementNamed( 633 + return searchDelegate(id).offNamed(
633 page, 634 page,
634 arguments: arguments, 635 arguments: arguments,
  636 + id: id,
  637 + // preventDuplicates: preventDuplicates,
  638 + parameters: parameters,
635 ); 639 );
636 } 640 }
637 641
@@ -648,34 +652,10 @@ you can only use widgets and widget functions here'''; @@ -648,34 +652,10 @@ you can only use widgets and widget functions here''';
648 /// or also like this: 652 /// or also like this:
649 /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the 653 /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the
650 /// dialog is closed 654 /// dialog is closed
651 - void until(RoutePredicate predicate, {int? id}) { 655 + void until(bool Function(GetPage<dynamic>) predicate, {int? id}) {
652 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 656 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
653 // when widget don't mounted 657 // when widget don't mounted
654 - return global(id).currentState?.popUntil(predicate);  
655 - }  
656 -  
657 - /// **Navigation.pushAndRemoveUntil()** shortcut.<br><br>  
658 - ///  
659 - /// Push the given `page`, and then pop several pages in the stack until  
660 - /// [predicate] returns true  
661 - ///  
662 - /// [id] is for when you are using nested navigation,  
663 - /// as explained in documentation  
664 - ///  
665 - /// Obs: unlike other get methods, this one you need to send a function  
666 - /// that returns the widget to the page argument, like this:  
667 - /// Get.offUntil(GetPageRoute(page: () => HomePage()), predicate)  
668 - ///  
669 - /// [predicate] can be used like this:  
670 - /// `Get.offUntil(page, (route) => (route as GetPageRoute).routeName == '/home')`  
671 - /// to pop routes in stack until home,  
672 - /// or also like this:  
673 - /// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog  
674 - /// is closed  
675 - Future<T?>? offUntil<T>(Route<T> page, RoutePredicate predicate, {int? id}) {  
676 - // if (key.currentState.mounted) // add this if appear problems on future with route navigate  
677 - // when widget don't mounted  
678 - return global(id).currentState?.pushAndRemoveUntil<T>(page, predicate); 658 + return searchDelegate(id).backUntil(predicate);
679 } 659 }
680 660
681 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> 661 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
@@ -698,7 +678,7 @@ you can only use widgets and widget functions here'''; @@ -698,7 +678,7 @@ you can only use widgets and widget functions here''';
698 /// Note: Always put a slash on the route name ('/page1'), to avoid unexpected errors 678 /// Note: Always put a slash on the route name ('/page1'), to avoid unexpected errors
699 Future<T?>? offNamedUntil<T>( 679 Future<T?>? offNamedUntil<T>(
700 String page, 680 String page,
701 - RoutePredicate predicate, { 681 + bool Function(GetPage<dynamic>)? predicate, {
702 int? id, 682 int? id,
703 dynamic arguments, 683 dynamic arguments,
704 Map<String, String>? parameters, 684 Map<String, String>? parameters,
@@ -708,10 +688,12 @@ you can only use widgets and widget functions here'''; @@ -708,10 +688,12 @@ you can only use widgets and widget functions here''';
708 page = uri.toString(); 688 page = uri.toString();
709 } 689 }
710 690
711 - return global(id).currentState?.pushNamedAndRemoveUntil<T>( 691 + return searchDelegate(id).offNamedUntil<T>(
712 page, 692 page,
713 - predicate, 693 + predicate: predicate,
  694 + id: id,
714 arguments: arguments, 695 arguments: arguments,
  696 + parameters: parameters,
715 ); 697 );
716 } 698 }
717 699
@@ -737,7 +719,7 @@ you can only use widgets and widget functions here'''; @@ -737,7 +719,7 @@ you can only use widgets and widget functions here''';
737 final uri = Uri(path: page, queryParameters: parameters); 719 final uri = Uri(path: page, queryParameters: parameters);
738 page = uri.toString(); 720 page = uri.toString();
739 } 721 }
740 - return global(id).currentState?.popAndPushNamed( 722 + return searchDelegate(id).backAndtoNamed(
741 page, 723 page,
742 arguments: arguments, 724 arguments: arguments,
743 result: result, 725 result: result,
@@ -750,8 +732,8 @@ you can only use widgets and widget functions here'''; @@ -750,8 +732,8 @@ you can only use widgets and widget functions here''';
750 /// 732 ///
751 /// [id] is for when you are using nested navigation, 733 /// [id] is for when you are using nested navigation,
752 /// as explained in documentation 734 /// as explained in documentation
753 - void removeRoute(Route<dynamic> route, {int? id}) {  
754 - return global(id).currentState?.removeRoute(route); 735 + void removeRoute(String name, {int? id}) {
  736 + return searchDelegate(id).removeRoute(name);
755 } 737 }
756 738
757 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br> 739 /// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
@@ -776,7 +758,7 @@ you can only use widgets and widget functions here'''; @@ -776,7 +758,7 @@ you can only use widgets and widget functions here''';
776 /// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors 758 /// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
777 Future<T?>? offAllNamed<T>( 759 Future<T?>? offAllNamed<T>(
778 String newRouteName, { 760 String newRouteName, {
779 - RoutePredicate? predicate, 761 + // bool Function(GetPage<dynamic>)? predicate,
780 dynamic arguments, 762 dynamic arguments,
781 int? id, 763 int? id,
782 Map<String, String>? parameters, 764 Map<String, String>? parameters,
@@ -786,10 +768,12 @@ you can only use widgets and widget functions here'''; @@ -786,10 +768,12 @@ you can only use widgets and widget functions here''';
786 newRouteName = uri.toString(); 768 newRouteName = uri.toString();
787 } 769 }
788 770
789 - return global(id).currentState?.pushNamedAndRemoveUntil<T>( 771 + return searchDelegate(id).offAllNamed<T>(
790 newRouteName, 772 newRouteName,
791 - predicate ?? (_) => false, 773 + //predicate: predicate ?? (_) => false,
792 arguments: arguments, 774 arguments: arguments,
  775 + id: id,
  776 + parameters: parameters,
793 ); 777 );
794 } 778 }
795 779
@@ -819,6 +803,13 @@ you can only use widgets and widget functions here'''; @@ -819,6 +803,13 @@ you can only use widgets and widget functions here''';
819 bool canPop = true, 803 bool canPop = true,
820 int? id, 804 int? id,
821 }) { 805 }) {
  806 + //TODO: remove this when change own api to Dialog and BottomSheets
  807 + //to declarative way
  808 + if (isDialogOpen! || isBottomSheetOpen!) {
  809 + searchDelegate(id).navigatorKey.currentState?.pop();
  810 + return;
  811 + }
  812 +
822 //TODO: This code brings compatibility of the new snackbar with GetX 4, 813 //TODO: This code brings compatibility of the new snackbar with GetX 4,
823 // remove this code in version 5 814 // remove this code in version 5
824 if (isSnackbarOpen && !closeOverlays) { 815 if (isSnackbarOpen && !closeOverlays) {
@@ -832,16 +823,21 @@ you can only use widgets and widget functions here'''; @@ -832,16 +823,21 @@ you can only use widgets and widget functions here''';
832 if (isSnackbarOpen) { 823 if (isSnackbarOpen) {
833 closeAllSnackbars(); 824 closeAllSnackbars();
834 } 825 }
835 - navigator?.popUntil((route) {  
836 - return (!isDialogOpen! && !isBottomSheetOpen!);  
837 - }); 826 +
  827 + while ((isDialogOpen! && isBottomSheetOpen!)) {
  828 + searchDelegate(id).navigatorKey.currentState?.pop();
  829 + }
  830 +
  831 + // navigator?.popUntil((route) {
  832 + // return;
  833 + // });
838 } 834 }
839 if (canPop) { 835 if (canPop) {
840 - if (global(id).currentState?.canPop() == true) {  
841 - global(id).currentState?.pop<T>(result); 836 + if (searchDelegate(id).canBack == true) {
  837 + searchDelegate(id).back<T>(result);
842 } 838 }
843 } else { 839 } else {
844 - global(id).currentState?.pop<T>(result); 840 + searchDelegate(id).back<T>(result);
845 } 841 }
846 } 842 }
847 843
@@ -856,7 +852,7 @@ you can only use widgets and widget functions here'''; @@ -856,7 +852,7 @@ you can only use widgets and widget functions here''';
856 times = 1; 852 times = 1;
857 } 853 }
858 var count = 0; 854 var count = 0;
859 - var back = global(id).currentState?.popUntil((route) => count++ == times); 855 + var back = searchDelegate(id).backUntil((route) => count++ == times);
860 856
861 return back; 857 return back;
862 } 858 }
@@ -887,15 +883,15 @@ you can only use widgets and widget functions here'''; @@ -887,15 +883,15 @@ you can only use widgets and widget functions here''';
887 /// By default, GetX will prevent you from push a route that you already in, 883 /// By default, GetX will prevent you from push a route that you already in,
888 /// if you want to push anyway, set [preventDuplicates] to false 884 /// if you want to push anyway, set [preventDuplicates] to false
889 Future<T?>? off<T>( 885 Future<T?>? off<T>(
890 - dynamic page, {  
891 - bool opaque = false, 886 + Widget Function() page, {
  887 + bool? opaque,
892 Transition? transition, 888 Transition? transition,
893 Curve? curve, 889 Curve? curve,
894 bool? popGesture, 890 bool? popGesture,
895 int? id, 891 int? id,
896 String? routeName, 892 String? routeName,
897 dynamic arguments, 893 dynamic arguments,
898 - Bindings? binding, 894 + List<BindingsInterface> bindings = const [],
899 bool fullscreenDialog = false, 895 bool fullscreenDialog = false,
900 bool preventDuplicates = true, 896 bool preventDuplicates = true,
901 Duration? duration, 897 Duration? duration,
@@ -906,21 +902,34 @@ you can only use widgets and widget functions here'''; @@ -906,21 +902,34 @@ you can only use widgets and widget functions here''';
906 if (preventDuplicates && routeName == currentRoute) { 902 if (preventDuplicates && routeName == currentRoute) {
907 return null; 903 return null;
908 } 904 }
909 - return global(id).currentState?.pushReplacement(GetPageRoute(  
910 - opaque: opaque,  
911 - gestureWidth: gestureWidth,  
912 - page: _resolvePage(page, 'off'),  
913 - binding: binding,  
914 - settings: RouteSettings(  
915 - arguments: arguments,  
916 - name: routeName,  
917 - ), 905 + return searchDelegate(id).off(
  906 + page,
  907 + opaque: opaque ?? true,
  908 + transition: transition,
  909 + curve: curve,
  910 + popGesture: popGesture,
  911 + id: id,
918 routeName: routeName, 912 routeName: routeName,
  913 + arguments: arguments,
  914 + bindings: bindings,
919 fullscreenDialog: fullscreenDialog, 915 fullscreenDialog: fullscreenDialog,
920 - popGesture: popGesture ?? defaultPopGesture,  
921 - transition: transition ?? defaultTransition,  
922 - curve: curve ?? defaultTransitionCurve,  
923 - transitionDuration: duration ?? defaultTransitionDuration)); 916 + preventDuplicates: preventDuplicates,
  917 + duration: duration,
  918 + gestureWidth: gestureWidth,
  919 + );
  920 + }
  921 +
  922 + Future<T?> offUntil<T>(
  923 + Widget Function() page,
  924 + bool Function(GetPage) predicate, [
  925 + Object? arguments,
  926 + int? id,
  927 + ]) {
  928 + return searchDelegate(id).offUntil(
  929 + page,
  930 + predicate,
  931 + arguments,
  932 + );
924 } 933 }
925 934
926 /// 935 ///
@@ -954,14 +963,14 @@ you can only use widgets and widget functions here'''; @@ -954,14 +963,14 @@ you can only use widgets and widget functions here''';
954 /// By default, GetX will prevent you from push a route that you already in, 963 /// By default, GetX will prevent you from push a route that you already in,
955 /// if you want to push anyway, set [preventDuplicates] to false 964 /// if you want to push anyway, set [preventDuplicates] to false
956 Future<T?>? offAll<T>( 965 Future<T?>? offAll<T>(
957 - dynamic page, {  
958 - RoutePredicate? predicate,  
959 - bool opaque = false, 966 + Widget Function() page, {
  967 + bool Function(GetPage<dynamic>)? predicate,
  968 + bool? opaque,
960 bool? popGesture, 969 bool? popGesture,
961 int? id, 970 int? id,
962 String? routeName, 971 String? routeName,
963 dynamic arguments, 972 dynamic arguments,
964 - Bindings? binding, 973 + List<BindingsInterface> bindings = const [],
965 bool fullscreenDialog = false, 974 bool fullscreenDialog = false,
966 Transition? transition, 975 Transition? transition,
967 Curve? curve, 976 Curve? curve,
@@ -970,24 +979,21 @@ you can only use widgets and widget functions here'''; @@ -970,24 +979,21 @@ you can only use widgets and widget functions here''';
970 }) { 979 }) {
971 routeName ??= "/${page.runtimeType.toString()}"; 980 routeName ??= "/${page.runtimeType.toString()}";
972 routeName = _cleanRouteName(routeName); 981 routeName = _cleanRouteName(routeName);
973 - return global(id).currentState?.pushAndRemoveUntil<T>(  
974 - GetPageRoute<T>(  
975 - opaque: opaque,  
976 - popGesture: popGesture ?? defaultPopGesture,  
977 - page: _resolvePage(page, 'offAll'),  
978 - binding: binding,  
979 - gestureWidth: gestureWidth,  
980 - settings: RouteSettings(  
981 - name: routeName, 982 + return searchDelegate(id).offAll<T>(
  983 + page,
  984 + predicate: predicate,
  985 + opaque: opaque ?? true,
  986 + popGesture: popGesture,
  987 + id: id,
  988 + // routeName routeName,
982 arguments: arguments, 989 arguments: arguments,
983 - ), 990 + bindings: bindings,
984 fullscreenDialog: fullscreenDialog, 991 fullscreenDialog: fullscreenDialog,
985 - routeName: routeName,  
986 - transition: transition ?? defaultTransition,  
987 - curve: curve ?? defaultTransitionCurve,  
988 - transitionDuration: duration ?? defaultTransitionDuration,  
989 - ),  
990 - predicate ?? (route) => false); 992 + transition: transition,
  993 + curve: curve,
  994 + duration: duration,
  995 + gestureWidth: gestureWidth,
  996 + );
991 } 997 }
992 998
993 /// Takes a route [name] String generated by [to], [off], [offAll] 999 /// Takes a route [name] String generated by [to], [off], [offAll]
@@ -1055,7 +1061,7 @@ you can only use widgets and widget functions here'''; @@ -1055,7 +1061,7 @@ you can only use widgets and widget functions here''';
1055 /// Your entire application will be rebuilt, and touch events will not 1061 /// Your entire application will be rebuilt, and touch events will not
1056 /// work until the end of rendering. 1062 /// work until the end of rendering.
1057 Future<void> forceAppUpdate() async { 1063 Future<void> forceAppUpdate() async {
1058 - await engine!.performReassemble(); 1064 + await engine.performReassemble();
1059 } 1065 }
1060 1066
1061 void appUpdate() => _getxController.update(); 1067 void appUpdate() => _getxController.update();
@@ -1072,20 +1078,25 @@ you can only use widgets and widget functions here'''; @@ -1072,20 +1078,25 @@ you can only use widgets and widget functions here''';
1072 return _getxController.addKey(newKey); 1078 return _getxController.addKey(newKey);
1073 } 1079 }
1074 1080
1075 - GlobalKey<NavigatorState>? nestedKey(dynamic key) { 1081 + GetDelegate? nestedKey(String? key) {
  1082 + if (key == null) {
  1083 + return routerDelegate as GetDelegate;
  1084 + }
1076 keys.putIfAbsent( 1085 keys.putIfAbsent(
1077 key, 1086 key,
1078 - () => GlobalKey<NavigatorState>(  
1079 - debugLabel: 'Getx nested key: ${key.toString()}', 1087 + () => GetDelegate(
  1088 + showHashOnUrl: true,
  1089 + //debugLabel: 'Getx nested key: ${key.toString()}',
  1090 + pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],
1080 ), 1091 ),
1081 ); 1092 );
1082 return keys[key]; 1093 return keys[key];
1083 } 1094 }
1084 1095
1085 - GlobalKey<NavigatorState> global(int? k) {  
1086 - GlobalKey<NavigatorState> _key; 1096 + GetDelegate searchDelegate(dynamic k) {
  1097 + GetDelegate _key;
1087 if (k == null) { 1098 if (k == null) {
1088 - _key = key; 1099 + _key = Get.rootController.rootDelegate;
1089 } else { 1100 } else {
1090 if (!keys.containsKey(k)) { 1101 if (!keys.containsKey(k)) {
1091 throw 'Route id ($k) not found'; 1102 throw 'Route id ($k) not found';
@@ -1093,21 +1104,22 @@ you can only use widgets and widget functions here'''; @@ -1093,21 +1104,22 @@ you can only use widgets and widget functions here''';
1093 _key = keys[k]!; 1104 _key = keys[k]!;
1094 } 1105 }
1095 1106
1096 - if (_key.currentContext == null && !testMode) {  
1097 - throw """You are trying to use contextless navigation without  
1098 - a GetMaterialApp or Get.key.  
1099 - If you are testing your app, you can use:  
1100 - [Get.testMode = true], or if you are running your app on  
1101 - a physical device or emulator, you must exchange your [MaterialApp]  
1102 - for a [GetMaterialApp].  
1103 - """;  
1104 - } 1107 + // if (_key.listenersLength == 0 && !testMode) {
  1108 + // throw """You are trying to use contextless navigation without
  1109 + // a GetMaterialApp or Get.key.
  1110 + // If you are testing your app, you can use:
  1111 + // [Get.testMode = true], or if you are running your app on
  1112 + // a physical device or emulator, you must exchange your [MaterialApp]
  1113 + // for a [GetMaterialApp].
  1114 + // """;
  1115 + // }
1105 1116
1106 return _key; 1117 return _key;
1107 } 1118 }
1108 1119
1109 /// give current arguments 1120 /// give current arguments
1110 - dynamic get arguments => routing.args; 1121 + //dynamic get arguments => routing.args;
  1122 + dynamic get arguments => _getxController.rootDelegate.arguments();
1111 1123
1112 /// give name from current route 1124 /// give name from current route
1113 String get currentRoute => routing.current; 1125 String get currentRoute => routing.current;
@@ -1163,12 +1175,9 @@ you can only use widgets and widget functions here'''; @@ -1163,12 +1175,9 @@ you can only use widgets and widget functions here''';
1163 return _theme; 1175 return _theme;
1164 } 1176 }
1165 1177
1166 - ///The current [WidgetsBinding]  
1167 - WidgetsBinding? get engine {  
1168 - if (WidgetsBinding.instance == null) {  
1169 - WidgetsFlutterBinding();  
1170 - }  
1171 - return WidgetsBinding.instance; 1178 + /// The current null safe [WidgetsBinding]
  1179 + WidgetsBinding get engine {
  1180 + return WidgetsFlutterBinding.ensureInitialized();
1172 } 1181 }
1173 1182
1174 /// The window to which this binding is bound. 1183 /// The window to which this binding is bound.
@@ -1225,7 +1234,7 @@ you can only use widgets and widget functions here'''; @@ -1225,7 +1234,7 @@ you can only use widgets and widget functions here''';
1225 1234
1226 GlobalKey<NavigatorState> get key => _getxController.key; 1235 GlobalKey<NavigatorState> get key => _getxController.key;
1227 1236
1228 - Map<dynamic, GlobalKey<NavigatorState>> get keys => _getxController.keys; 1237 + Map<dynamic, GetDelegate> get keys => _getxController.keys;
1229 1238
1230 GetMaterialController get rootController => _getxController; 1239 GetMaterialController get rootController => _getxController;
1231 1240
@@ -1250,7 +1259,8 @@ you can only use widgets and widget functions here'''; @@ -1250,7 +1259,8 @@ you can only use widgets and widget functions here''';
1250 1259
1251 Routing get routing => _getxController.routing; 1260 Routing get routing => _getxController.routing;
1252 1261
1253 - Map<String, String?> get parameters => _getxController.parameters; 1262 + Map<String, String?> get parameters =>
  1263 + _getxController.rootDelegate.parameters;
1254 set parameters(Map<String, String?> newParameters) => 1264 set parameters(Map<String, String?> newParameters) =>
1255 _getxController.parameters = newParameters; 1265 _getxController.parameters = newParameters;
1256 1266
@@ -1280,10 +1290,15 @@ extension NavTwoExt on GetInterface { @@ -1280,10 +1290,15 @@ extension NavTwoExt on GetInterface {
1280 static late final _routeTree = ParseRouteTree(routes: []); 1290 static late final _routeTree = ParseRouteTree(routes: []);
1281 1291
1282 ParseRouteTree get routeTree => _routeTree; 1292 ParseRouteTree get routeTree => _routeTree;
  1293 +
1283 void addPage(GetPage getPage) { 1294 void addPage(GetPage getPage) {
1284 routeTree.addRoute(getPage); 1295 routeTree.addRoute(getPage);
1285 } 1296 }
1286 1297
  1298 + void removePage(GetPage getPage) {
  1299 + routeTree.removeRoute(getPage);
  1300 + }
  1301 +
1287 /// Casts the stored router delegate to a desired type 1302 /// Casts the stored router delegate to a desired type
1288 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => 1303 TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() =>
1289 routerDelegate as TDelegate?; 1304 routerDelegate as TDelegate?;
@@ -1307,15 +1322,15 @@ extension NavTwoExt on GetInterface { @@ -1307,15 +1322,15 @@ extension NavTwoExt on GetInterface {
1307 1322
1308 // static GetDelegate? _delegate; 1323 // static GetDelegate? _delegate;
1309 1324
1310 - GetDelegate get rootDelegate => createDelegate();  
1311 -  
1312 GetDelegate createDelegate({ 1325 GetDelegate createDelegate({
1313 GetPage<dynamic>? notFoundRoute, 1326 GetPage<dynamic>? notFoundRoute,
  1327 + List<GetPage> pages = const [],
1314 List<NavigatorObserver>? navigatorObservers, 1328 List<NavigatorObserver>? navigatorObservers,
1315 TransitionDelegate<dynamic>? transitionDelegate, 1329 TransitionDelegate<dynamic>? transitionDelegate,
1316 PopMode backButtonPopMode = PopMode.History, 1330 PopMode backButtonPopMode = PopMode.History,
1317 PreventDuplicateHandlingMode preventDuplicateHandlingMode = 1331 PreventDuplicateHandlingMode preventDuplicateHandlingMode =
1318 PreventDuplicateHandlingMode.ReorderRoutes, 1332 PreventDuplicateHandlingMode.ReorderRoutes,
  1333 + GlobalKey<NavigatorState>? navigatorKey,
1319 }) { 1334 }) {
1320 if (routerDelegate == null) { 1335 if (routerDelegate == null) {
1321 return routerDelegate = GetDelegate( 1336 return routerDelegate = GetDelegate(
@@ -1324,6 +1339,8 @@ extension NavTwoExt on GetInterface { @@ -1324,6 +1339,8 @@ extension NavTwoExt on GetInterface {
1324 transitionDelegate: transitionDelegate, 1339 transitionDelegate: transitionDelegate,
1325 backButtonPopMode: backButtonPopMode, 1340 backButtonPopMode: backButtonPopMode,
1326 preventDuplicateHandlingMode: preventDuplicateHandlingMode, 1341 preventDuplicateHandlingMode: preventDuplicateHandlingMode,
  1342 + pages: pages,
  1343 + navigatorKey: navigatorKey,
1327 ); 1344 );
1328 } else { 1345 } else {
1329 return routerDelegate as GetDelegate; 1346 return routerDelegate as GetDelegate;
1 -import 'package:flutter/widgets.dart';  
2 -  
3 -import '../../../get.dart';  
4 -  
5 -// class GetRouterState extends GetxController {  
6 -// GetRouterState({required this.currentTreeBranch});  
7 -// final List<GetPage> currentTreeBranch;  
8 -// GetPage? get currentPage => currentTreeBranch.last;  
9 -  
10 -// static GetNavConfig? fromRoute(String route) {  
11 -// final res = Get.routeTree.matchRoute(route);  
12 -// if (res.treeBranch.isEmpty) return null;  
13 -// return GetNavConfig(  
14 -// currentTreeBranch: res.treeBranch,  
15 -// location: route,  
16 -// state: null,  
17 -// );  
18 -// }  
19 -// }  
20 -  
21 -/// This config enables us to navigate directly to a sub-url  
22 -class GetNavConfig extends RouteInformation {  
23 - final List<GetPage> currentTreeBranch;  
24 - GetPage? get currentPage => currentTreeBranch.last;  
25 -  
26 - GetNavConfig({  
27 - required this.currentTreeBranch,  
28 - required String? location,  
29 - required Object? state,  
30 - }) : super(  
31 - location: location,  
32 - state: state,  
33 - );  
34 -  
35 - GetNavConfig copyWith({  
36 - List<GetPage>? currentTreeBranch,  
37 - required String? location,  
38 - required Object? state,  
39 - }) {  
40 - return GetNavConfig(  
41 - currentTreeBranch: currentTreeBranch ?? this.currentTreeBranch,  
42 - location: location ?? this.location,  
43 - state: state ?? this.state,  
44 - );  
45 - }  
46 -  
47 - static GetNavConfig? fromRoute(String route) {  
48 - final res = Get.routeTree.matchRoute(route);  
49 - if (res.treeBranch.isEmpty) return null;  
50 - return GetNavConfig(  
51 - currentTreeBranch: res.treeBranch,  
52 - location: route,  
53 - state: null,  
54 - );  
55 - }  
56 -  
57 - @override  
58 - String toString() => '''  
59 -======GetNavConfig=====\ncurrentTreeBranch: $currentTreeBranch\ncurrentPage: $currentPage\n======GetNavConfig=====''';  
60 -}  
1 -import 'dart:async';  
2 -  
3 -import 'package:flutter/foundation.dart';  
4 -import 'package:flutter/material.dart';  
5 -  
6 -import '../../../get.dart';  
7 -import '../../../get_state_manager/src/simple/list_notifier.dart';  
8 -  
9 -class GetDelegate extends RouterDelegate<GetNavConfig>  
10 - with ListenableMixin, ListNotifierMixin {  
11 - final List<GetNavConfig> history = <GetNavConfig>[];  
12 - final PopMode backButtonPopMode;  
13 - final PreventDuplicateHandlingMode preventDuplicateHandlingMode;  
14 -  
15 - final GetPage notFoundRoute;  
16 -  
17 - final List<NavigatorObserver>? navigatorObservers;  
18 - final TransitionDelegate<dynamic>? transitionDelegate;  
19 -  
20 - final _allCompleters = <GetPage, Completer>{};  
21 -  
22 - GetDelegate({  
23 - GetPage? notFoundRoute,  
24 - this.navigatorObservers,  
25 - this.transitionDelegate,  
26 - this.backButtonPopMode = PopMode.History,  
27 - this.preventDuplicateHandlingMode =  
28 - PreventDuplicateHandlingMode.ReorderRoutes,  
29 - }) : notFoundRoute = notFoundRoute ??  
30 - GetPage(  
31 - name: '/404',  
32 - page: () => Scaffold(  
33 - body: Text('Route not found'),  
34 - ),  
35 - ) {  
36 - Get.log('GetDelegate is created !');  
37 - }  
38 -  
39 - @override  
40 - GetNavConfig? get currentConfiguration {  
41 - if (history.isEmpty) return null;  
42 - final route = history.last;  
43 - return route;  
44 - }  
45 -  
46 - GlobalKey<NavigatorState> get navigatorKey => Get.key;  
47 -  
48 - Map<String, String> get parameters {  
49 - return currentConfiguration?.currentPage?.parameters ?? {};  
50 - }  
51 -  
52 - T arguments<T>() {  
53 - return currentConfiguration?.currentPage?.arguments as T;  
54 - }  
55 -  
56 - /// Removes routes according to [PopMode]  
57 - /// until it reaches the specifc [fullRoute],  
58 - /// DOES NOT remove the [fullRoute]  
59 - Future<void> backUntil(  
60 - String fullRoute, {  
61 - PopMode popMode = PopMode.Page,  
62 - }) async {  
63 - // remove history or page entries until you meet route  
64 - var iterator = currentConfiguration;  
65 - while (_canPop(popMode) &&  
66 - iterator != null &&  
67 - iterator.location != fullRoute) {  
68 - await _pop(popMode);  
69 - // replace iterator  
70 - iterator = currentConfiguration;  
71 - }  
72 - refresh();  
73 - }  
74 -  
75 - @override  
76 - Widget build(BuildContext context) {  
77 - final pages = getVisualPages();  
78 - if (pages.length == 0) return SizedBox.shrink();  
79 - final extraObservers = navigatorObservers;  
80 - return GetNavigator(  
81 - key: navigatorKey,  
82 - onPopPage: _onPopVisualRoute,  
83 - pages: pages,  
84 - observers: [  
85 - GetObserver(),  
86 - if (extraObservers != null) ...extraObservers,  
87 - ],  
88 - transitionDelegate:  
89 - transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),  
90 - );  
91 - }  
92 -  
93 - // void _unsafeHistoryClear() {  
94 - // history.clear();  
95 - // }  
96 -  
97 - Future<bool> canPopHistory() {  
98 - return SynchronousFuture(_canPopHistory());  
99 - }  
100 -  
101 - Future<bool> canPopPage() {  
102 - return SynchronousFuture(_canPopPage());  
103 - }  
104 -  
105 - /// gets the visual pages from the current history entry  
106 - ///  
107 - /// visual pages must have [participatesInRootNavigator] set to true  
108 - List<GetPage> getVisualPages() {  
109 - final currentHistory = currentConfiguration;  
110 - if (currentHistory == null) return <GetPage>[];  
111 -  
112 - final res = currentHistory.currentTreeBranch  
113 - .where((r) => r.participatesInRootNavigator != null);  
114 - if (res.length == 0) {  
115 - //default behavoir, all routes participate in root navigator  
116 - return history.map((e) => e.currentPage!).toList();  
117 - } else {  
118 - //user specified at least one participatesInRootNavigator  
119 - return res  
120 - .where((element) => element.participatesInRootNavigator == true)  
121 - .toList();  
122 - }  
123 - }  
124 -  
125 - // GetPageRoute getPageRoute(RouteSettings? settings) {  
126 - // return PageRedirect(settings ?? RouteSettings(name: '/404'), _notFound())  
127 - // .page();  
128 - // }  
129 -  
130 - Future<bool> handlePopupRoutes({  
131 - Object? result,  
132 - }) async {  
133 - Route? currentRoute;  
134 - navigatorKey.currentState!.popUntil((route) {  
135 - currentRoute = route;  
136 - return true;  
137 - });  
138 - if (currentRoute is PopupRoute) {  
139 - return await navigatorKey.currentState!.maybePop(result);  
140 - }  
141 - return false;  
142 - }  
143 -  
144 - Future<T?>? offAndToNamed<T>(  
145 - String page, {  
146 - dynamic arguments,  
147 - int? id,  
148 - dynamic result,  
149 - Map<String, String>? parameters,  
150 - PopMode popMode = PopMode.History,  
151 - }) async {  
152 - if (parameters != null) {  
153 - final uri = Uri(path: page, queryParameters: parameters);  
154 - page = uri.toString();  
155 - }  
156 -  
157 - await popRoute(result: result);  
158 - return toNamed(page, arguments: arguments, parameters: parameters);  
159 - }  
160 -  
161 - Future<T> offNamed<T>(  
162 - String page, {  
163 - dynamic arguments,  
164 - Map<String, String>? parameters,  
165 - }) async {  
166 - history.removeLast();  
167 - return toNamed<T>(page, arguments: arguments, parameters: parameters);  
168 - }  
169 -  
170 - Future<GetNavConfig?> popHistory() async {  
171 - return await _popHistory();  
172 - }  
173 -  
174 - // returns the popped page  
175 - @override  
176 - Future<bool> popRoute({  
177 - Object? result,  
178 - PopMode popMode = PopMode.Page,  
179 - }) async {  
180 - //Returning false will cause the entire app to be popped.  
181 - final wasPopup = await handlePopupRoutes(result: result);  
182 - if (wasPopup) return true;  
183 - final _popped = await _pop(popMode);  
184 - refresh();  
185 - if (_popped != null) {  
186 - //emulate the old pop with result  
187 - return true;  
188 - }  
189 - return false;  
190 - }  
191 -  
192 - /// Adds a new history entry and waits for the result  
193 - Future<void> pushHistory(  
194 - GetNavConfig config, {  
195 - bool rebuildStack = true,  
196 - }) async {  
197 - //this changes the currentConfiguration  
198 - await _pushHistory(config);  
199 - if (rebuildStack) {  
200 - refresh();  
201 - }  
202 - }  
203 -  
204 - Future<GetNavConfig?> runMiddleware(GetNavConfig config) async {  
205 - final middlewares = config.currentTreeBranch.last.middlewares;  
206 - if (middlewares == null) {  
207 - return config;  
208 - }  
209 - var iterator = config;  
210 - for (var item in middlewares) {  
211 - var redirectRes = await item.redirectDelegate(iterator);  
212 - if (redirectRes == null) return null;  
213 - iterator = redirectRes;  
214 - }  
215 - return iterator;  
216 - }  
217 -  
218 - @override  
219 - Future<void> setNewRoutePath(GetNavConfig configuration) async {  
220 - await pushHistory(configuration);  
221 - }  
222 -  
223 - Future<T> toNamed<T>(  
224 - String page, {  
225 - dynamic arguments,  
226 - Map<String, String>? parameters,  
227 - }) async {  
228 - if (parameters != null) {  
229 - final uri = Uri(path: page, queryParameters: parameters);  
230 - page = uri.toString();  
231 - }  
232 -  
233 - final decoder = Get.routeTree.matchRoute(page, arguments: arguments);  
234 - decoder.replaceArguments(arguments);  
235 -  
236 - final completer = Completer<T>();  
237 -  
238 - if (decoder.route != null) {  
239 - _allCompleters[decoder.route!] = completer;  
240 - await pushHistory(  
241 - GetNavConfig(  
242 - currentTreeBranch: decoder.treeBranch,  
243 - location: page,  
244 - state: null, //TODO: persist state?  
245 - ),  
246 - );  
247 -  
248 - return completer.future;  
249 - } else {  
250 - ///TODO: IMPLEMENT ROUTE NOT FOUND  
251 -  
252 - return Future.value();  
253 - }  
254 - }  
255 -  
256 - bool _canPop(PopMode mode) {  
257 - switch (mode) {  
258 - case PopMode.History:  
259 - return _canPopHistory();  
260 - case PopMode.Page:  
261 - default:  
262 - return _canPopPage();  
263 - }  
264 - }  
265 -  
266 - bool _canPopHistory() {  
267 - return history.length > 1;  
268 - }  
269 -  
270 - bool _canPopPage() {  
271 - final currentTreeBranch = currentConfiguration?.currentTreeBranch;  
272 - if (currentTreeBranch == null) return false;  
273 - return currentTreeBranch.length > 1 ? true : _canPopHistory();  
274 - }  
275 -  
276 - Future<GetNavConfig?> _doPopHistory() async {  
277 - return await _unsafeHistoryRemoveAt(history.length - 1);  
278 - }  
279 -  
280 - // @override  
281 - // Future<void> setInitialRoutePath(GetNavConfig configuration) async {  
282 - // //no need to clear history with Reorder route strategy  
283 - // // _unsafeHistoryClear();  
284 - // // _resultCompleter.clear();  
285 - // await pushHistory(configuration);  
286 - // }  
287 -  
288 - Future<GetNavConfig?> _doPopPage() async {  
289 - final currentBranch = currentConfiguration?.currentTreeBranch;  
290 - if (currentBranch != null && currentBranch.length > 1) {  
291 - //remove last part only  
292 - final remaining = currentBranch.take(currentBranch.length - 1);  
293 - final prevHistoryEntry =  
294 - history.length > 1 ? history[history.length - 2] : null;  
295 -  
296 - //check if current route is the same as the previous route  
297 - if (prevHistoryEntry != null) {  
298 - //if so, pop the entire history entry  
299 - final newLocation = remaining.last.name;  
300 - final prevLocation = prevHistoryEntry.location;  
301 - if (newLocation == prevLocation) {  
302 - //pop the entire history entry  
303 - return await _popHistory();  
304 - }  
305 - }  
306 -  
307 - //create a new route with the remaining tree branch  
308 - final res = await _popHistory();  
309 - await _pushHistory(  
310 - GetNavConfig(  
311 - currentTreeBranch: remaining.toList(),  
312 - location: remaining.last.name,  
313 - state: null, //TOOD: persist state??  
314 - ),  
315 - );  
316 - return res;  
317 - } else {  
318 - //remove entire entry  
319 - return await _popHistory();  
320 - }  
321 - }  
322 -  
323 - bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {  
324 - final didPop = route.didPop(result);  
325 - if (!didPop) {  
326 - return false;  
327 - }  
328 - final settings = route.settings;  
329 - if (settings is GetPage) {  
330 - final config = history.cast<GetNavConfig?>().firstWhere(  
331 - (element) => element?.currentPage == settings,  
332 - orElse: () => null,  
333 - );  
334 - if (config != null) {  
335 - _removeHistoryEntry(config);  
336 - }  
337 - if (_allCompleters.containsKey(settings)) {  
338 - _allCompleters[settings]?.complete(route.popped);  
339 - }  
340 - }  
341 - refresh();  
342 -  
343 - return true;  
344 - }  
345 -  
346 - Future<GetNavConfig?> _pop(PopMode mode) async {  
347 - switch (mode) {  
348 - case PopMode.History:  
349 - return await _popHistory();  
350 - case PopMode.Page:  
351 - return await _popPage();  
352 - default:  
353 - return null;  
354 - }  
355 - }  
356 -  
357 - Future<GetNavConfig?> _popHistory() async {  
358 - if (!_canPopHistory()) return null;  
359 - return await _doPopHistory();  
360 - }  
361 -  
362 - Future<GetNavConfig?> _popPage() async {  
363 - if (!_canPopPage()) return null;  
364 - return await _doPopPage();  
365 - }  
366 -  
367 - Future<void> _pushHistory(GetNavConfig config) async {  
368 - if (config.currentPage!.preventDuplicates) {  
369 - final originalEntryIndex =  
370 - history.indexWhere((element) => element.location == config.location);  
371 - if (originalEntryIndex >= 0) {  
372 - switch (preventDuplicateHandlingMode) {  
373 - case PreventDuplicateHandlingMode.PopUntilOriginalRoute:  
374 - await backUntil(config.location!, popMode: PopMode.Page);  
375 - break;  
376 - case PreventDuplicateHandlingMode.ReorderRoutes:  
377 - await _unsafeHistoryRemoveAt(originalEntryIndex);  
378 - await _unsafeHistoryAdd(config);  
379 - break;  
380 - case PreventDuplicateHandlingMode.DoNothing:  
381 - default:  
382 - break;  
383 - }  
384 - return;  
385 - }  
386 - }  
387 - await _unsafeHistoryAdd(config);  
388 - }  
389 -  
390 - Future<void> _removeHistoryEntry(GetNavConfig entry) async {  
391 - await _unsafeHistoryRemove(entry);  
392 - }  
393 -  
394 - Future<void> _unsafeHistoryAdd(GetNavConfig config) async {  
395 - final res = await runMiddleware(config);  
396 - if (res == null) return;  
397 - history.add(res);  
398 - }  
399 -  
400 - Future<void> _unsafeHistoryRemove(GetNavConfig config) async {  
401 - var index = history.indexOf(config);  
402 - if (index >= 0) await _unsafeHistoryRemoveAt(index);  
403 - }  
404 -  
405 - Future<GetNavConfig?> _unsafeHistoryRemoveAt(int index) async {  
406 - if (index == history.length - 1 && history.length > 1) {  
407 - //removing WILL update the current route  
408 - final toCheck = history[history.length - 2];  
409 - final resMiddleware = await runMiddleware(toCheck);  
410 - if (resMiddleware == null) return null;  
411 - history[history.length - 2] = resMiddleware;  
412 - }  
413 - return history.removeAt(index);  
414 - }  
415 -}  
416 -  
417 -class GetNavigator extends Navigator {  
418 - GetNavigator({  
419 - GlobalKey<NavigatorState>? key,  
420 - bool Function(Route<dynamic>, dynamic)? onPopPage,  
421 - required List<Page> pages,  
422 - List<NavigatorObserver>? observers,  
423 - bool reportsRouteUpdateToEngine = false,  
424 - TransitionDelegate? transitionDelegate,  
425 - }) : super(  
426 - //keys should be optional  
427 - key: key,  
428 - onPopPage: onPopPage ??  
429 - (route, result) {  
430 - final didPop = route.didPop(result);  
431 - if (!didPop) {  
432 - return false;  
433 - }  
434 - return true;  
435 - },  
436 - reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,  
437 - pages: pages,  
438 - observers: [  
439 - // GetObserver(),  
440 - if (observers != null) ...observers,  
441 - ],  
442 - transitionDelegate:  
443 - transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),  
444 - );  
445 -}  
446 -  
447 -/// Enables the user to customize the intended pop behavior  
448 -///  
449 -/// Goes to either the previous history entry or the previous page entry  
450 -///  
451 -/// e.g. if the user navigates to these pages  
452 -/// 1) /home  
453 -/// 2) /home/products/1234  
454 -///  
455 -/// when popping on [History] mode, it will emulate a browser back button.  
456 -///  
457 -/// so the new history stack will be:  
458 -/// 1) /home  
459 -///  
460 -/// when popping on [Page] mode, it will only remove the last part of the route  
461 -/// so the new history stack will be:  
462 -/// 1) /home  
463 -/// 2) /home/products  
464 -///  
465 -/// another pop will change the history stack to:  
466 -/// 1) /home  
467 -enum PopMode {  
468 - History,  
469 - Page,  
470 -}  
471 -  
472 -/// Enables the user to customize the behavior when pushing multiple routes that  
473 -/// shouldn't be duplicates  
474 -enum PreventDuplicateHandlingMode {  
475 - /// Removes the history entries until it reaches the old route  
476 - PopUntilOriginalRoute,  
477 -  
478 - /// Simply don't push the new route  
479 - DoNothing,  
480 -  
481 - /// Recommended - Moves the old route entry to the front  
482 - ///  
483 - /// With this mode, you guarantee there will be only one  
484 - /// route entry for each location  
485 - ReorderRoutes  
486 -}  
@@ -7,7 +7,6 @@ import '../../../get_instance/get_instance.dart'; @@ -7,7 +7,6 @@ import '../../../get_instance/get_instance.dart';
7 import '../../../get_state_manager/get_state_manager.dart'; 7 import '../../../get_state_manager/get_state_manager.dart';
8 import '../../../get_utils/get_utils.dart'; 8 import '../../../get_utils/get_utils.dart';
9 import '../../get_navigation.dart'; 9 import '../../get_navigation.dart';
10 -import 'root_controller.dart';  
11 10
12 class GetCupertinoApp extends StatelessWidget { 11 class GetCupertinoApp extends StatelessWidget {
13 final GlobalKey<NavigatorState>? navigatorKey; 12 final GlobalKey<NavigatorState>? navigatorKey;
@@ -52,7 +51,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -52,7 +51,7 @@ class GetCupertinoApp extends StatelessWidget {
52 final LogWriterCallback? logWriterCallback; 51 final LogWriterCallback? logWriterCallback;
53 final bool? popGesture; 52 final bool? popGesture;
54 final SmartManagement smartManagement; 53 final SmartManagement smartManagement;
55 - final Bindings? initialBinding; 54 + final BindingsInterface? initialBinding;
56 final Duration? transitionDuration; 55 final Duration? transitionDuration;
57 final bool? defaultGlobalState; 56 final bool? defaultGlobalState;
58 final List<GetPage>? getPages; 57 final List<GetPage>? getPages;
@@ -63,7 +62,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -63,7 +62,7 @@ class GetCupertinoApp extends StatelessWidget {
63 final BackButtonDispatcher? backButtonDispatcher; 62 final BackButtonDispatcher? backButtonDispatcher;
64 final CupertinoThemeData? theme; 63 final CupertinoThemeData? theme;
65 final bool useInheritedMediaQuery; 64 final bool useInheritedMediaQuery;
66 - const GetCupertinoApp({ 65 + GetCupertinoApp({
67 Key? key, 66 Key? key,
68 this.theme, 67 this.theme,
69 this.navigatorKey, 68 this.navigatorKey,
@@ -116,17 +115,28 @@ class GetCupertinoApp extends StatelessWidget { @@ -116,17 +115,28 @@ class GetCupertinoApp extends StatelessWidget {
116 this.highContrastDarkTheme, 115 this.highContrastDarkTheme,
117 this.actions, 116 this.actions,
118 }) : routeInformationProvider = null, 117 }) : routeInformationProvider = null,
  118 + backButtonDispatcher = null,
119 routeInformationParser = null, 119 routeInformationParser = null,
120 routerDelegate = null, 120 routerDelegate = null,
121 - backButtonDispatcher = null,  
122 super(key: key); 121 super(key: key);
123 122
  123 + static String _cleanRouteName(String name) {
  124 + name = name.replaceAll('() => ', '');
  125 +
  126 + /// uncommonent for URL styling.
  127 + // name = name.paramCase!;
  128 + if (!name.startsWith('/')) {
  129 + name = '/$name';
  130 + }
  131 + return Uri.tryParse(name)?.toString() ?? name;
  132 + }
  133 +
124 GetCupertinoApp.router({ 134 GetCupertinoApp.router({
125 Key? key, 135 Key? key,
126 this.theme, 136 this.theme,
127 this.routeInformationProvider, 137 this.routeInformationProvider,
128 - RouteInformationParser<Object>? routeInformationParser,  
129 - RouterDelegate<Object>? routerDelegate, 138 + this.routeInformationParser,
  139 + this.routerDelegate,
130 this.backButtonDispatcher, 140 this.backButtonDispatcher,
131 this.builder, 141 this.builder,
132 this.title = '', 142 this.title = '',
@@ -166,35 +176,30 @@ class GetCupertinoApp extends StatelessWidget { @@ -166,35 +176,30 @@ class GetCupertinoApp extends StatelessWidget {
166 this.transitionDuration, 176 this.transitionDuration,
167 this.defaultGlobalState, 177 this.defaultGlobalState,
168 this.getPages, 178 this.getPages,
  179 + this.navigatorObservers,
169 this.unknownRoute, 180 this.unknownRoute,
170 - }) : routerDelegate = routerDelegate ??= Get.createDelegate(  
171 - notFoundRoute: unknownRoute,  
172 - ),  
173 - routeInformationParser =  
174 - routeInformationParser ??= Get.createInformationParser(  
175 - initialRoute: getPages?.first.name ?? '/',  
176 - ),  
177 - navigatorObservers = null,  
178 - navigatorKey = null, 181 + }) : navigatorKey = null,
179 onGenerateRoute = null, 182 onGenerateRoute = null,
180 home = null, 183 home = null,
181 onGenerateInitialRoutes = null, 184 onGenerateInitialRoutes = null,
182 onUnknownRoute = null, 185 onUnknownRoute = null,
183 routes = null, 186 routes = null,
184 initialRoute = null, 187 initialRoute = null,
185 - super(key: key) {  
186 - Get.routerDelegate = routerDelegate;  
187 - Get.routeInformationParser = routeInformationParser;  
188 - } 188 + super(key: key);
189 189
190 @override 190 @override
191 Widget build(BuildContext context) => GetBuilder<GetMaterialController>( 191 Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
192 init: Get.rootController, 192 init: Get.rootController,
193 dispose: (d) { 193 dispose: (d) {
194 onDispose?.call(); 194 onDispose?.call();
  195 + Get.clearRouteTree();
  196 + Get.clearTranslations();
  197 + Get.resetRootNavigator();
  198 + Get.routerDelegate = null;
  199 + Get.routeInformationParser = null;
195 }, 200 },
196 initState: (i) { 201 initState: (i) {
197 - Get.engine!.addPostFrameCallback((timeStamp) { 202 + Get.engine.addPostFrameCallback((timeStamp) {
198 onReady?.call(); 203 onReady?.call();
199 }); 204 });
200 if (locale != null) Get.locale = locale; 205 if (locale != null) Get.locale = locale;
@@ -212,6 +217,13 @@ class GetCupertinoApp extends StatelessWidget { @@ -212,6 +217,13 @@ class GetCupertinoApp extends StatelessWidget {
212 initialBinding?.dependencies(); 217 initialBinding?.dependencies();
213 if (getPages != null) { 218 if (getPages != null) {
214 Get.addPages(getPages!); 219 Get.addPages(getPages!);
  220 + } else {
  221 + Get.addPage(
  222 + GetPage(
  223 + name: _cleanRouteName("/${home.runtimeType}"),
  224 + page: () => home!,
  225 + ),
  226 + );
215 } 227 }
216 228
217 Get.smartManagement = smartManagement; 229 Get.smartManagement = smartManagement;
@@ -227,46 +239,11 @@ class GetCupertinoApp extends StatelessWidget { @@ -227,46 +239,11 @@ class GetCupertinoApp extends StatelessWidget {
227 transitionDuration ?? Get.defaultTransitionDuration, 239 transitionDuration ?? Get.defaultTransitionDuration,
228 ); 240 );
229 }, 241 },
230 - builder: (_) => routerDelegate != null  
231 - ? CupertinoApp.router(  
232 - routerDelegate: routerDelegate!,  
233 - routeInformationParser: routeInformationParser!,  
234 - backButtonDispatcher: backButtonDispatcher,  
235 - routeInformationProvider: routeInformationProvider,  
236 - key: _.unikey,  
237 - theme: theme,  
238 - builder: defaultBuilder,  
239 - title: title,  
240 - onGenerateTitle: onGenerateTitle,  
241 - color: color,  
242 - locale: Get.locale ?? locale,  
243 - localizationsDelegates: localizationsDelegates,  
244 - localeListResolutionCallback: localeListResolutionCallback,  
245 - localeResolutionCallback: localeResolutionCallback,  
246 - supportedLocales: supportedLocales,  
247 - showPerformanceOverlay: showPerformanceOverlay,  
248 - checkerboardRasterCacheImages: checkerboardRasterCacheImages,  
249 - checkerboardOffscreenLayers: checkerboardOffscreenLayers,  
250 - showSemanticsDebugger: showSemanticsDebugger,  
251 - debugShowCheckedModeBanner: debugShowCheckedModeBanner,  
252 - shortcuts: shortcuts,  
253 - useInheritedMediaQuery: useInheritedMediaQuery,  
254 - )  
255 - : CupertinoApp(  
256 - key: _.unikey,  
257 - theme: theme,  
258 - navigatorKey: (navigatorKey == null  
259 - ? Get.key  
260 - : Get.addKey(navigatorKey!)),  
261 - home: home,  
262 - routes: routes ?? const <String, WidgetBuilder>{},  
263 - initialRoute: initialRoute,  
264 - onGenerateRoute:  
265 - (getPages != null ? generator : onGenerateRoute),  
266 - onGenerateInitialRoutes: (getPages == null || home != null)  
267 - ? onGenerateInitialRoutes  
268 - : initialRoutesGenerate,  
269 - onUnknownRoute: onUnknownRoute, 242 + builder: (_) {
  243 + final routerDelegate = Get.createDelegate(
  244 + pages: getPages ?? [],
  245 + notFoundRoute: unknownRoute,
  246 + navigatorKey: navigatorKey,
270 navigatorObservers: (navigatorObservers == null 247 navigatorObservers: (navigatorObservers == null
271 ? <NavigatorObserver>[ 248 ? <NavigatorObserver>[
272 GetObserver(routingCallback, Get.routing) 249 GetObserver(routingCallback, Get.routing)
@@ -274,7 +251,20 @@ class GetCupertinoApp extends StatelessWidget { @@ -274,7 +251,20 @@ class GetCupertinoApp extends StatelessWidget {
274 : <NavigatorObserver>[ 251 : <NavigatorObserver>[
275 GetObserver(routingCallback, Get.routing) 252 GetObserver(routingCallback, Get.routing)
276 ] 253 ]
277 - ..addAll(navigatorObservers!)), 254 + ..addAll(navigatorObservers!)));
  255 + final routeInformationParser = Get.createInformationParser(
  256 + initialRoute: initialRoute ??
  257 + getPages?.first.name ??
  258 + _cleanRouteName("/${home.runtimeType}"),
  259 + );
  260 +
  261 + return CupertinoApp.router(
  262 + routerDelegate: routerDelegate,
  263 + routeInformationParser: routeInformationParser,
  264 + backButtonDispatcher: backButtonDispatcher,
  265 + routeInformationProvider: routeInformationProvider,
  266 + key: _.unikey,
  267 + theme: theme,
278 builder: defaultBuilder, 268 builder: defaultBuilder,
279 title: title, 269 title: title,
280 onGenerateTitle: onGenerateTitle, 270 onGenerateTitle: onGenerateTitle,
@@ -291,8 +281,8 @@ class GetCupertinoApp extends StatelessWidget { @@ -291,8 +281,8 @@ class GetCupertinoApp extends StatelessWidget {
291 debugShowCheckedModeBanner: debugShowCheckedModeBanner, 281 debugShowCheckedModeBanner: debugShowCheckedModeBanner,
292 shortcuts: shortcuts, 282 shortcuts: shortcuts,
293 useInheritedMediaQuery: useInheritedMediaQuery, 283 useInheritedMediaQuery: useInheritedMediaQuery,
294 - // actions: actions,  
295 - ), 284 + );
  285 + },
296 ); 286 );
297 287
298 Widget defaultBuilder(BuildContext context, Widget? child) { 288 Widget defaultBuilder(BuildContext context, Widget? child) {
1 -import 'package:flutter/cupertino.dart';  
2 import 'package:flutter/foundation.dart'; 1 import 'package:flutter/foundation.dart';
3 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
4 3
@@ -7,7 +6,6 @@ import '../../../get_instance/get_instance.dart'; @@ -7,7 +6,6 @@ import '../../../get_instance/get_instance.dart';
7 import '../../../get_state_manager/get_state_manager.dart'; 6 import '../../../get_state_manager/get_state_manager.dart';
8 import '../../../get_utils/get_utils.dart'; 7 import '../../../get_utils/get_utils.dart';
9 import '../../get_navigation.dart'; 8 import '../../get_navigation.dart';
10 -import 'root_controller.dart';  
11 9
12 class GetMaterialApp extends StatelessWidget { 10 class GetMaterialApp extends StatelessWidget {
13 final GlobalKey<NavigatorState>? navigatorKey; 11 final GlobalKey<NavigatorState>? navigatorKey;
@@ -58,7 +56,7 @@ class GetMaterialApp extends StatelessWidget { @@ -58,7 +56,7 @@ class GetMaterialApp extends StatelessWidget {
58 final LogWriterCallback? logWriterCallback; 56 final LogWriterCallback? logWriterCallback;
59 final bool? popGesture; 57 final bool? popGesture;
60 final SmartManagement smartManagement; 58 final SmartManagement smartManagement;
61 - final Bindings? initialBinding; 59 + final BindingsInterface? initialBinding;
62 final Duration? transitionDuration; 60 final Duration? transitionDuration;
63 final bool? defaultGlobalState; 61 final bool? defaultGlobalState;
64 final List<GetPage>? getPages; 62 final List<GetPage>? getPages;
@@ -68,7 +66,7 @@ class GetMaterialApp extends StatelessWidget { @@ -68,7 +66,7 @@ class GetMaterialApp extends StatelessWidget {
68 final RouterDelegate<Object>? routerDelegate; 66 final RouterDelegate<Object>? routerDelegate;
69 final BackButtonDispatcher? backButtonDispatcher; 67 final BackButtonDispatcher? backButtonDispatcher;
70 final bool useInheritedMediaQuery; 68 final bool useInheritedMediaQuery;
71 - const GetMaterialApp({ 69 + GetMaterialApp({
72 Key? key, 70 Key? key,
73 this.navigatorKey, 71 this.navigatorKey,
74 this.scaffoldMessengerKey, 72 this.scaffoldMessengerKey,
@@ -126,17 +124,28 @@ class GetMaterialApp extends StatelessWidget { @@ -126,17 +124,28 @@ class GetMaterialApp extends StatelessWidget {
126 this.highContrastDarkTheme, 124 this.highContrastDarkTheme,
127 this.actions, 125 this.actions,
128 }) : routeInformationProvider = null, 126 }) : routeInformationProvider = null,
  127 + backButtonDispatcher = null,
129 routeInformationParser = null, 128 routeInformationParser = null,
130 routerDelegate = null, 129 routerDelegate = null,
131 - backButtonDispatcher = null,  
132 super(key: key); 130 super(key: key);
133 131
  132 + static String _cleanRouteName(String name) {
  133 + name = name.replaceAll('() => ', '');
  134 +
  135 + /// uncommonent for URL styling.
  136 + // name = name.paramCase!;
  137 + if (!name.startsWith('/')) {
  138 + name = '/$name';
  139 + }
  140 + return Uri.tryParse(name)?.toString() ?? name;
  141 + }
  142 +
134 GetMaterialApp.router({ 143 GetMaterialApp.router({
135 Key? key, 144 Key? key,
136 this.routeInformationProvider, 145 this.routeInformationProvider,
137 this.scaffoldMessengerKey, 146 this.scaffoldMessengerKey,
138 - RouteInformationParser<Object>? routeInformationParser,  
139 - RouterDelegate<Object>? routerDelegate, 147 + this.routeInformationParser,
  148 + this.routerDelegate,
140 this.backButtonDispatcher, 149 this.backButtonDispatcher,
141 this.builder, 150 this.builder,
142 this.title = '', 151 this.title = '',
@@ -183,34 +192,30 @@ class GetMaterialApp extends StatelessWidget { @@ -183,34 +192,30 @@ class GetMaterialApp extends StatelessWidget {
183 this.getPages, 192 this.getPages,
184 this.navigatorObservers, 193 this.navigatorObservers,
185 this.unknownRoute, 194 this.unknownRoute,
186 - }) : routerDelegate = routerDelegate ??= Get.createDelegate(  
187 - notFoundRoute: unknownRoute,  
188 - ),  
189 - routeInformationParser =  
190 - routeInformationParser ??= Get.createInformationParser(  
191 - initialRoute: getPages?.first.name ?? '/',  
192 - ),  
193 - //navigatorObservers = null,  
194 - navigatorKey = null, 195 + }) : navigatorKey = null,
195 onGenerateRoute = null, 196 onGenerateRoute = null,
196 home = null, 197 home = null,
197 onGenerateInitialRoutes = null, 198 onGenerateInitialRoutes = null,
198 onUnknownRoute = null, 199 onUnknownRoute = null,
199 routes = null, 200 routes = null,
200 initialRoute = null, 201 initialRoute = null,
201 - super(key: key) {  
202 - Get.routerDelegate = routerDelegate;  
203 - Get.routeInformationParser = routeInformationParser;  
204 - } 202 + super(key: key);
205 203
206 @override 204 @override
207 Widget build(BuildContext context) => GetBuilder<GetMaterialController>( 205 Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
208 init: Get.rootController, 206 init: Get.rootController,
209 dispose: (d) { 207 dispose: (d) {
210 onDispose?.call(); 208 onDispose?.call();
  209 + Get.clearRouteTree();
  210 + Get.clearTranslations();
  211 + Get.resetRootNavigator();
  212 + Get.routerDelegate = null;
  213 + Get.routeInformationParser = null;
211 }, 214 },
212 initState: (i) { 215 initState: (i) {
213 - Get.engine!.addPostFrameCallback((timeStamp) { 216 + // Get.routerDelegate = routerDelegate;
  217 + // Get.routeInformationParser = routeInformationParser;
  218 + Get.engine.addPostFrameCallback((timeStamp) {
214 onReady?.call(); 219 onReady?.call();
215 }); 220 });
216 if (locale != null) Get.locale = locale; 221 if (locale != null) Get.locale = locale;
@@ -228,6 +233,13 @@ class GetMaterialApp extends StatelessWidget { @@ -228,6 +233,13 @@ class GetMaterialApp extends StatelessWidget {
228 initialBinding?.dependencies(); 233 initialBinding?.dependencies();
229 if (getPages != null) { 234 if (getPages != null) {
230 Get.addPages(getPages!); 235 Get.addPages(getPages!);
  236 + } else {
  237 + Get.addPage(
  238 + GetPage(
  239 + name: _cleanRouteName("/${home.runtimeType}"),
  240 + page: () => home!,
  241 + ),
  242 + );
231 } 243 }
232 244
233 //Get.setDefaultDelegate(routerDelegate); 245 //Get.setDefaultDelegate(routerDelegate);
@@ -244,10 +256,26 @@ class GetMaterialApp extends StatelessWidget { @@ -244,10 +256,26 @@ class GetMaterialApp extends StatelessWidget {
244 transitionDuration ?? Get.defaultTransitionDuration, 256 transitionDuration ?? Get.defaultTransitionDuration,
245 ); 257 );
246 }, 258 },
247 - builder: (_) => routerDelegate != null  
248 - ? MaterialApp.router(  
249 - routerDelegate: routerDelegate!,  
250 - routeInformationParser: routeInformationParser!, 259 + builder: (_) {
  260 + final routerDelegate = Get.createDelegate(
  261 + pages: getPages ?? [],
  262 + notFoundRoute: unknownRoute,
  263 + navigatorKey: navigatorKey,
  264 + navigatorObservers: (navigatorObservers == null
  265 + ? <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
  266 + : <NavigatorObserver>[
  267 + GetObserver(routingCallback, Get.routing),
  268 + ...navigatorObservers!
  269 + ]));
  270 +
  271 + final routeInformationParser = Get.createInformationParser(
  272 + initialRoute: initialRoute ??
  273 + getPages?.first.name ??
  274 + _cleanRouteName("/${home.runtimeType}"),
  275 + );
  276 + return MaterialApp.router(
  277 + routerDelegate: routerDelegate,
  278 + routeInformationParser: routeInformationParser,
251 backButtonDispatcher: backButtonDispatcher, 279 backButtonDispatcher: backButtonDispatcher,
252 routeInformationProvider: routeInformationProvider, 280 routeInformationProvider: routeInformationProvider,
253 key: _.unikey, 281 key: _.unikey,
@@ -256,59 +284,10 @@ class GetMaterialApp extends StatelessWidget { @@ -256,59 +284,10 @@ class GetMaterialApp extends StatelessWidget {
256 onGenerateTitle: onGenerateTitle, 284 onGenerateTitle: onGenerateTitle,
257 color: color, 285 color: color,
258 theme: _.theme ?? theme ?? ThemeData.fallback(), 286 theme: _.theme ?? theme ?? ThemeData.fallback(),
259 - darkTheme:  
260 - _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(),  
261 - themeMode: _.themeMode ?? themeMode,  
262 - locale: Get.locale ?? locale,  
263 - scaffoldMessengerKey:  
264 - scaffoldMessengerKey ?? _.scaffoldMessengerKey,  
265 - localizationsDelegates: localizationsDelegates,  
266 - localeListResolutionCallback: localeListResolutionCallback,  
267 - localeResolutionCallback: localeResolutionCallback,  
268 - supportedLocales: supportedLocales,  
269 - debugShowMaterialGrid: debugShowMaterialGrid,  
270 - showPerformanceOverlay: showPerformanceOverlay,  
271 - checkerboardRasterCacheImages: checkerboardRasterCacheImages,  
272 - checkerboardOffscreenLayers: checkerboardOffscreenLayers,  
273 - showSemanticsDebugger: showSemanticsDebugger,  
274 - debugShowCheckedModeBanner: debugShowCheckedModeBanner,  
275 - shortcuts: shortcuts,  
276 - scrollBehavior: scrollBehavior,  
277 - useInheritedMediaQuery: useInheritedMediaQuery,  
278 - )  
279 - : MaterialApp(  
280 - key: _.unikey,  
281 - navigatorKey: (navigatorKey == null  
282 - ? Get.key  
283 - : Get.addKey(navigatorKey!)),  
284 - scaffoldMessengerKey:  
285 - scaffoldMessengerKey ?? _.scaffoldMessengerKey,  
286 - home: home,  
287 - routes: routes ?? const <String, WidgetBuilder>{},  
288 - initialRoute: initialRoute,  
289 - onGenerateRoute:  
290 - (getPages != null ? generator : onGenerateRoute),  
291 - onGenerateInitialRoutes: (getPages == null || home != null)  
292 - ? onGenerateInitialRoutes  
293 - : initialRoutesGenerate,  
294 - onUnknownRoute: onUnknownRoute,  
295 - navigatorObservers: (navigatorObservers == null  
296 - ? <NavigatorObserver>[  
297 - GetObserver(routingCallback, Get.routing)  
298 - ]  
299 - : <NavigatorObserver>[  
300 - GetObserver(routingCallback, Get.routing)  
301 - ]  
302 - ..addAll(navigatorObservers!)),  
303 - builder: defaultBuilder,  
304 - title: title,  
305 - onGenerateTitle: onGenerateTitle,  
306 - color: color,  
307 - theme: _.theme ?? theme ?? ThemeData.fallback(),  
308 - darkTheme:  
309 - _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(), 287 + darkTheme: _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(),
310 themeMode: _.themeMode ?? themeMode, 288 themeMode: _.themeMode ?? themeMode,
311 locale: Get.locale ?? locale, 289 locale: Get.locale ?? locale,
  290 + scaffoldMessengerKey: scaffoldMessengerKey ?? _.scaffoldMessengerKey,
312 localizationsDelegates: localizationsDelegates, 291 localizationsDelegates: localizationsDelegates,
313 localeListResolutionCallback: localeListResolutionCallback, 292 localeListResolutionCallback: localeListResolutionCallback,
314 localeResolutionCallback: localeResolutionCallback, 293 localeResolutionCallback: localeResolutionCallback,
@@ -322,9 +301,8 @@ class GetMaterialApp extends StatelessWidget { @@ -322,9 +301,8 @@ class GetMaterialApp extends StatelessWidget {
322 shortcuts: shortcuts, 301 shortcuts: shortcuts,
323 scrollBehavior: scrollBehavior, 302 scrollBehavior: scrollBehavior,
324 useInheritedMediaQuery: useInheritedMediaQuery, 303 useInheritedMediaQuery: useInheritedMediaQuery,
325 - // actions: actions,  
326 - ),  
327 ); 304 );
  305 + });
328 306
329 Widget defaultBuilder(BuildContext context, Widget? child) { 307 Widget defaultBuilder(BuildContext context, Widget? child) {
330 return Directionality( 308 return Directionality(
@@ -342,12 +320,12 @@ class GetMaterialApp extends StatelessWidget { @@ -342,12 +320,12 @@ class GetMaterialApp extends StatelessWidget {
342 return PageRedirect(settings: settings, unknownRoute: unknownRoute).page(); 320 return PageRedirect(settings: settings, unknownRoute: unknownRoute).page();
343 } 321 }
344 322
345 - List<Route<dynamic>> initialRoutesGenerate(String name) {  
346 - return [  
347 - PageRedirect(  
348 - settings: RouteSettings(name: name),  
349 - unknownRoute: unknownRoute,  
350 - ).page()  
351 - ];  
352 - } 323 + // List<Route<dynamic>> initialRoutesGenerate(String name) {
  324 + // return [
  325 + // PageRedirect(
  326 + // settings: RouteSettings(name: name),
  327 + // unknownRoute: unknownRoute,
  328 + // ).page()
  329 + // ];
  330 + // }
353 } 331 }
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 2
3 import '../../../get.dart'; 3 import '../../../get.dart';
4 -import '../../../get_state_manager/get_state_manager.dart';  
5 -import '../../../get_utils/get_utils.dart';  
6 -import '../routes/custom_transition.dart';  
7 -import '../routes/observers/route_observer.dart';  
8 -import '../routes/transitions_type.dart';  
9 4
10 -class GetMaterialController extends SuperController { 5 +class GetMaterialController extends FullLifeCycleController {
  6 + static GetMaterialController get to => Get.find();
  7 +
11 bool testMode = false; 8 bool testMode = false;
12 Key? unikey; 9 Key? unikey;
13 ThemeData? theme; 10 ThemeData? theme;
@@ -33,14 +30,14 @@ class GetMaterialController extends SuperController { @@ -33,14 +30,14 @@ class GetMaterialController extends SuperController {
33 30
34 CustomTransition? customTransition; 31 CustomTransition? customTransition;
35 32
36 - var _key = GlobalKey<NavigatorState>(debugLabel: 'Key Created by default'); 33 + Map<dynamic, GetDelegate> keys = {};
37 34
38 - Map<dynamic, GlobalKey<NavigatorState>> keys = {}; 35 + GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey;
39 36
40 - GlobalKey<NavigatorState> get key => _key; 37 + GetDelegate get rootDelegate => Get.createDelegate();
41 38
42 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { 39 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
43 - _key = newKey; 40 + rootDelegate.navigatorKey = newKey;
44 return key; 41 return key;
45 } 42 }
46 43
@@ -54,18 +51,6 @@ class GetMaterialController extends SuperController { @@ -54,18 +51,6 @@ class GetMaterialController extends SuperController {
54 }); 51 });
55 } 52 }
56 53
57 - @override  
58 - void onDetached() {}  
59 -  
60 - @override  
61 - void onInactive() {}  
62 -  
63 - @override  
64 - void onPaused() {}  
65 -  
66 - @override  
67 - void onResumed() {}  
68 -  
69 void restartApp() { 54 void restartApp() {
70 unikey = UniqueKey(); 55 unikey = UniqueKey();
71 update(); 56 update();
@@ -7,28 +7,30 @@ import '../../get.dart'; @@ -7,28 +7,30 @@ import '../../get.dart';
7 class RouterReportManager<T> { 7 class RouterReportManager<T> {
8 /// Holds a reference to `Get.reference` when the Instance was 8 /// Holds a reference to `Get.reference` when the Instance was
9 /// created to manage the memory. 9 /// created to manage the memory.
10 - static final Map<Route?, List<String>> _routesKey = {}; 10 + final Map<T?, List<String>> _routesKey = {};
11 11
12 /// Stores the onClose() references of instances created with `Get.create()` 12 /// Stores the onClose() references of instances created with `Get.create()`
13 /// using the `Get.reference`. 13 /// using the `Get.reference`.
14 /// Experimental feature to keep the lifecycle and memory management with 14 /// Experimental feature to keep the lifecycle and memory management with
15 /// non-singleton instances. 15 /// non-singleton instances.
16 - static final Map<Route?, HashSet<Function>> _routesByCreate = {}; 16 + final Map<T?, HashSet<Function>> _routesByCreate = {};
  17 +
  18 + static late final RouterReportManager instance = RouterReportManager();
17 19
18 void printInstanceStack() { 20 void printInstanceStack() {
19 Get.log(_routesKey.toString()); 21 Get.log(_routesKey.toString());
20 } 22 }
21 23
22 - static Route? _current; 24 + T? _current;
23 25
24 // ignore: use_setters_to_change_properties 26 // ignore: use_setters_to_change_properties
25 - static void reportCurrentRoute(Route newRoute) { 27 + void reportCurrentRoute(T newRoute) {
26 _current = newRoute; 28 _current = newRoute;
27 } 29 }
28 30
29 /// Links a Class instance [S] (or [tag]) to the current route. 31 /// Links a Class instance [S] (or [tag]) to the current route.
30 /// Requires usage of `GetMaterialApp`. 32 /// Requires usage of `GetMaterialApp`.
31 - static void reportDependencyLinkedToRoute(String depedencyKey) { 33 + void reportDependencyLinkedToRoute(String depedencyKey) {
32 if (_current == null) return; 34 if (_current == null) return;
33 if (_routesKey.containsKey(_current)) { 35 if (_routesKey.containsKey(_current)) {
34 _routesKey[_current!]!.add(depedencyKey); 36 _routesKey[_current!]!.add(depedencyKey);
@@ -37,26 +39,26 @@ class RouterReportManager<T> { @@ -37,26 +39,26 @@ class RouterReportManager<T> {
37 } 39 }
38 } 40 }
39 41
40 - static void clearRouteKeys() { 42 + void clearRouteKeys() {
41 _routesKey.clear(); 43 _routesKey.clear();
42 _routesByCreate.clear(); 44 _routesByCreate.clear();
43 } 45 }
44 46
45 - static void appendRouteByCreate(GetLifeCycleBase i) { 47 + void appendRouteByCreate(GetLifeCycleMixin i) {
46 _routesByCreate[_current] ??= HashSet<Function>(); 48 _routesByCreate[_current] ??= HashSet<Function>();
47 // _routesByCreate[Get.reference]!.add(i.onDelete as Function); 49 // _routesByCreate[Get.reference]!.add(i.onDelete as Function);
48 _routesByCreate[_current]!.add(i.onDelete); 50 _routesByCreate[_current]!.add(i.onDelete);
49 } 51 }
50 52
51 - static void reportRouteDispose(Route disposed) { 53 + void reportRouteDispose(T disposed) {
52 if (Get.smartManagement != SmartManagement.onlyBuilder) { 54 if (Get.smartManagement != SmartManagement.onlyBuilder) {
53 - WidgetsBinding.instance!.addPostFrameCallback((_) { 55 + ambiguate(WidgetsBinding.instance)!.addPostFrameCallback((_) {
54 _removeDependencyByRoute(disposed); 56 _removeDependencyByRoute(disposed);
55 }); 57 });
56 } 58 }
57 } 59 }
58 60
59 - static void reportRouteWillDispose(Route disposed) { 61 + void reportRouteWillDispose(T disposed) {
60 final keysToRemove = <String>[]; 62 final keysToRemove = <String>[];
61 63
62 _routesKey[disposed]?.forEach(keysToRemove.add); 64 _routesKey[disposed]?.forEach(keysToRemove.add);
@@ -85,7 +87,7 @@ class RouterReportManager<T> { @@ -85,7 +87,7 @@ class RouterReportManager<T> {
85 /// using `Get.smartManagement` as [SmartManagement.full] or 87 /// using `Get.smartManagement` as [SmartManagement.full] or
86 /// [SmartManagement.keepFactory] 88 /// [SmartManagement.keepFactory]
87 /// Meant for internal usage of `GetPageRoute` and `GetDialogRoute` 89 /// Meant for internal usage of `GetPageRoute` and `GetDialogRoute`
88 - static void _removeDependencyByRoute(Route routeName) { 90 + void _removeDependencyByRoute(T routeName) {
89 final keysToRemove = <String>[]; 91 final keysToRemove = <String>[];
90 92
91 _routesKey[routeName]?.forEach(keysToRemove.add); 93 _routesKey[routeName]?.forEach(keysToRemove.add);
  1 +import 'dart:math' show sqrt, max;
  2 +import 'dart:ui' show lerpDouble;
  3 +
  4 +import 'package:flutter/material.dart';
  5 +
  6 +class CircularRevealClipper extends CustomClipper<Path> {
  7 + final double fraction;
  8 + final Alignment? centerAlignment;
  9 + final Offset? centerOffset;
  10 + final double? minRadius;
  11 + final double? maxRadius;
  12 +
  13 + CircularRevealClipper({
  14 + required this.fraction,
  15 + this.centerAlignment,
  16 + this.centerOffset,
  17 + this.minRadius,
  18 + this.maxRadius,
  19 + });
  20 +
  21 + @override
  22 + Path getClip(Size size) {
  23 + final center = centerAlignment?.alongSize(size) ??
  24 + centerOffset ??
  25 + Offset(size.width / 2, size.height / 2);
  26 + final minRadius = this.minRadius ?? 0;
  27 + final maxRadius = this.maxRadius ?? calcMaxRadius(size, center);
  28 +
  29 + return Path()
  30 + ..addOval(
  31 + Rect.fromCircle(
  32 + center: center,
  33 + radius: lerpDouble(minRadius, maxRadius, fraction)!,
  34 + ),
  35 + );
  36 + }
  37 +
  38 + @override
  39 + bool shouldReclip(CustomClipper<Path> oldClipper) => true;
  40 +
  41 + static double calcMaxRadius(Size size, Offset center) {
  42 + final w = max(center.dx, size.width - center.dx);
  43 + final h = max(center.dy, size.height - center.dy);
  44 + return sqrt(w * w + h * h);
  45 + }
  46 +}
@@ -2,22 +2,33 @@ import 'package:flutter/material.dart'; @@ -2,22 +2,33 @@ import 'package:flutter/material.dart';
2 2
3 import '../../../get.dart'; 3 import '../../../get.dart';
4 import '../router_report.dart'; 4 import '../router_report.dart';
5 -import 'custom_transition.dart';  
6 -import 'get_transition_mixin.dart';  
7 -import 'route_middleware.dart';  
8 -import 'transitions_type.dart'; 5 +
  6 +@optionalTypeArgs
  7 +mixin RouteReportMixin<T extends StatefulWidget> on State<T> {
  8 + @override
  9 + void initState() {
  10 + super.initState();
  11 + RouterReportManager.instance.reportCurrentRoute(this);
  12 + }
  13 +
  14 + @override
  15 + void dispose() {
  16 + super.dispose();
  17 + RouterReportManager.instance.reportRouteDispose(this);
  18 + }
  19 +}
9 20
10 mixin PageRouteReportMixin<T> on Route<T> { 21 mixin PageRouteReportMixin<T> on Route<T> {
11 @override 22 @override
12 void install() { 23 void install() {
13 super.install(); 24 super.install();
14 - RouterReportManager.reportCurrentRoute(this); 25 + RouterReportManager.instance.reportCurrentRoute(this);
15 } 26 }
16 27
17 @override 28 @override
18 void dispose() { 29 void dispose() {
19 super.dispose(); 30 super.dispose();
20 - RouterReportManager.reportRouteDispose(this); 31 + RouterReportManager.instance.reportRouteDispose(this);
21 } 32 }
22 } 33 }
23 34
@@ -40,8 +51,8 @@ class GetPageRoute<T> extends PageRoute<T> @@ -40,8 +51,8 @@ class GetPageRoute<T> extends PageRoute<T>
40 this.customTransition, 51 this.customTransition,
41 this.barrierDismissible = false, 52 this.barrierDismissible = false,
42 this.barrierColor, 53 this.barrierColor,
43 - this.binding,  
44 - this.bindings, 54 + this.bindings = const [],
  55 + this.binds,
45 this.routeName, 56 this.routeName,
46 this.page, 57 this.page,
47 this.title, 58 this.title,
@@ -50,7 +61,11 @@ class GetPageRoute<T> extends PageRoute<T> @@ -50,7 +61,11 @@ class GetPageRoute<T> extends PageRoute<T>
50 this.maintainState = true, 61 this.maintainState = true,
51 bool fullscreenDialog = false, 62 bool fullscreenDialog = false,
52 this.middlewares, 63 this.middlewares,
53 - }) : super(settings: settings, fullscreenDialog: fullscreenDialog); 64 + }) : super(
  65 + settings: settings,
  66 + fullscreenDialog: fullscreenDialog,
  67 + // builder: (context) => Container(),
  68 + );
54 69
55 @override 70 @override
56 final Duration transitionDuration; 71 final Duration transitionDuration;
@@ -58,9 +73,9 @@ class GetPageRoute<T> extends PageRoute<T> @@ -58,9 +73,9 @@ class GetPageRoute<T> extends PageRoute<T>
58 final String? routeName; 73 final String? routeName;
59 //final String reference; 74 //final String reference;
60 final CustomTransition? customTransition; 75 final CustomTransition? customTransition;
61 - final Bindings? binding; 76 + final List<BindingsInterface> bindings;
62 final Map<String, String>? parameter; 77 final Map<String, String>? parameter;
63 - final List<Bindings>? bindings; 78 + final List<Bind>? binds;
64 79
65 @override 80 @override
66 final bool showCupertinoParallax; 81 final bool showCupertinoParallax;
@@ -98,20 +113,33 @@ class GetPageRoute<T> extends PageRoute<T> @@ -98,20 +113,33 @@ class GetPageRoute<T> extends PageRoute<T>
98 if (_child != null) return _child!; 113 if (_child != null) return _child!;
99 final middlewareRunner = MiddlewareRunner(middlewares); 114 final middlewareRunner = MiddlewareRunner(middlewares);
100 115
101 - final localbindings = [  
102 - if (bindings != null) ...bindings!,  
103 - if (binding != null) ...[binding!]  
104 - ];  
105 - final bindingsToBind = middlewareRunner.runOnBindingsStart(localbindings);  
106 - if (bindingsToBind != null) {  
107 - for (final binding in bindingsToBind) {  
108 - binding.dependencies(); 116 + final localbinds = [if (binds != null) ...binds!];
  117 +
  118 + final bindingsToBind = middlewareRunner
  119 + .runOnBindingsStart(bindings.isNotEmpty ? bindings : localbinds);
  120 +
  121 + final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!;
  122 +
  123 + if (bindingsToBind != null && bindingsToBind.isNotEmpty) {
  124 + if (bindingsToBind is List<BindingsInterface>) {
  125 + for (final item in bindingsToBind) {
  126 + final dep = item.dependencies();
  127 + if (dep is List<Bind>) {
  128 + _child = Binds(
  129 + child: middlewareRunner.runOnPageBuilt(pageToBuild()),
  130 + binds: dep,
  131 + );
  132 + }
  133 + }
  134 + } else if (bindingsToBind is List<Bind>) {
  135 + _child = Binds(
  136 + child: middlewareRunner.runOnPageBuilt(pageToBuild()),
  137 + binds: bindingsToBind,
  138 + );
109 } 139 }
110 } 140 }
111 141
112 - final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!;  
113 - _child = middlewareRunner.runOnPageBuilt(pageToBuild());  
114 - return _child!; 142 + return _child ??= middlewareRunner.runOnPageBuilt(pageToBuild());
115 } 143 }
116 144
117 @override 145 @override
1 import 'package:flutter/cupertino.dart'; 1 import 'package:flutter/cupertino.dart';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 3
  4 +import 'circular_reveal_clipper.dart';
  5 +
4 class LeftToRightFadeTransition { 6 class LeftToRightFadeTransition {
5 Widget buildTransitions( 7 Widget buildTransitions(
6 BuildContext context, 8 BuildContext context,
@@ -184,3 +186,24 @@ class SizeTransitions { @@ -184,3 +186,24 @@ class SizeTransitions {
184 ); 186 );
185 } 187 }
186 } 188 }
  189 +
  190 +class CircularRevealTransition {
  191 + Widget buildTransitions(
  192 + BuildContext context,
  193 + Curve? curve,
  194 + Alignment? alignment,
  195 + Animation<double> animation,
  196 + Animation<double> secondaryAnimation,
  197 + Widget child) {
  198 + return ClipPath(
  199 + clipper: CircularRevealClipper(
  200 + fraction: animation.value,
  201 + centerAlignment: Alignment.center,
  202 + centerOffset: Offset.zero,
  203 + minRadius: 0,
  204 + maxRadius: 800,
  205 + ),
  206 + child: child,
  207 + );
  208 + }
  209 +}
@@ -3,16 +3,16 @@ import 'package:flutter/widgets.dart'; @@ -3,16 +3,16 @@ import 'package:flutter/widgets.dart';
3 3
4 import '../../../get.dart'; 4 import '../../../get.dart';
5 5
6 -class GetInformationParser extends RouteInformationParser<GetNavConfig> { 6 +class GetInformationParser extends RouteInformationParser<RouteDecoder> {
7 final String initialRoute; 7 final String initialRoute;
8 8
9 GetInformationParser({ 9 GetInformationParser({
10 - this.initialRoute = '/', 10 + required this.initialRoute,
11 }) { 11 }) {
12 Get.log('GetInformationParser is created !'); 12 Get.log('GetInformationParser is created !');
13 } 13 }
14 @override 14 @override
15 - SynchronousFuture<GetNavConfig> parseRouteInformation( 15 + SynchronousFuture<RouteDecoder> parseRouteInformation(
16 RouteInformation routeInformation, 16 RouteInformation routeInformation,
17 ) { 17 ) {
18 var location = routeInformation.location; 18 var location = routeInformation.location;
@@ -26,22 +26,16 @@ class GetInformationParser extends RouteInformationParser<GetNavConfig> { @@ -26,22 +26,16 @@ class GetInformationParser extends RouteInformationParser<GetNavConfig> {
26 26
27 Get.log('GetInformationParser: route location: $location'); 27 Get.log('GetInformationParser: route location: $location');
28 28
29 - final matchResult = Get.routeTree.matchRoute(location ?? initialRoute); 29 + final routeName = location ?? initialRoute;
30 30
31 - return SynchronousFuture(  
32 - GetNavConfig(  
33 - currentTreeBranch: matchResult.treeBranch,  
34 - location: location,  
35 - state: routeInformation.state,  
36 - ),  
37 - ); 31 + return SynchronousFuture(RouteDecoder.fromRoute(routeName));
38 } 32 }
39 33
40 @override 34 @override
41 - RouteInformation restoreRouteInformation(GetNavConfig config) { 35 + RouteInformation restoreRouteInformation(RouteDecoder config) {
42 return RouteInformation( 36 return RouteInformation(
43 - location: config.location,  
44 - state: config.state, 37 + location: config.pageSettings?.name,
  38 + state: null,
45 ); 39 );
46 } 40 }
47 } 41 }
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +import '../../../get_instance/src/bindings_interface.dart';
  4 +import '../routes/get_route.dart';
  5 +import '../routes/transitions_type.dart';
  6 +
  7 +/// Enables the user to customize the intended pop behavior
  8 +///
  9 +/// Goes to either the previous _activePages entry or the previous page entry
  10 +///
  11 +/// e.g. if the user navigates to these pages
  12 +/// 1) /home
  13 +/// 2) /home/products/1234
  14 +///
  15 +/// when popping on [History] mode, it will emulate a browser back button.
  16 +///
  17 +/// so the new _activePages stack will be:
  18 +/// 1) /home
  19 +///
  20 +/// when popping on [Page] mode, it will only remove the last part of the route
  21 +/// so the new _activePages stack will be:
  22 +/// 1) /home
  23 +/// 2) /home/products
  24 +///
  25 +/// another pop will change the _activePages stack to:
  26 +/// 1) /home
  27 +enum PopMode {
  28 + History,
  29 + Page,
  30 +}
  31 +
  32 +/// Enables the user to customize the behavior when pushing multiple routes that
  33 +/// shouldn't be duplicates
  34 +enum PreventDuplicateHandlingMode {
  35 + /// Removes the _activePages entries until it reaches the old route
  36 + PopUntilOriginalRoute,
  37 +
  38 + /// Simply don't push the new route
  39 + DoNothing,
  40 +
  41 + /// Recommended - Moves the old route entry to the front
  42 + ///
  43 + /// With this mode, you guarantee there will be only one
  44 + /// route entry for each location
  45 + ReorderRoutes,
  46 +
  47 + Recreate,
  48 +}
  49 +
  50 +mixin IGetNavigation {
  51 + Future<T?> to<T>(
  52 + Widget Function() page, {
  53 + bool? opaque,
  54 + Transition? transition,
  55 + Curve? curve,
  56 + Duration? duration,
  57 + int? id,
  58 + String? routeName,
  59 + bool fullscreenDialog = false,
  60 + dynamic arguments,
  61 + List<BindingsInterface> bindings = const [],
  62 + bool preventDuplicates = true,
  63 + bool? popGesture,
  64 + bool showCupertinoParallax = true,
  65 + double Function(BuildContext context)? gestureWidth,
  66 + });
  67 +
  68 + Future<void> popModeUntil(
  69 + String fullRoute, {
  70 + PopMode popMode = PopMode.History,
  71 + });
  72 +
  73 + Future<T?> off<T>(
  74 + Widget Function() page, {
  75 + bool? opaque,
  76 + Transition? transition,
  77 + Curve? curve,
  78 + Duration? duration,
  79 + int? id,
  80 + String? routeName,
  81 + bool fullscreenDialog = false,
  82 + dynamic arguments,
  83 + List<BindingsInterface> bindings = const [],
  84 + bool preventDuplicates = true,
  85 + bool? popGesture,
  86 + bool showCupertinoParallax = true,
  87 + double Function(BuildContext context)? gestureWidth,
  88 + });
  89 +
  90 + Future<T?>? offAll<T>(
  91 + Widget Function() page, {
  92 + bool Function(GetPage route)? predicate,
  93 + bool opaque = true,
  94 + bool? popGesture,
  95 + int? id,
  96 + String? routeName,
  97 + dynamic arguments,
  98 + List<BindingsInterface> bindings = const [],
  99 + bool fullscreenDialog = false,
  100 + Transition? transition,
  101 + Curve? curve,
  102 + Duration? duration,
  103 + bool showCupertinoParallax = true,
  104 + double Function(BuildContext context)? gestureWidth,
  105 + });
  106 +
  107 + Future<T?> toNamed<T>(
  108 + String page, {
  109 + dynamic arguments,
  110 + int? id,
  111 + bool preventDuplicates = true,
  112 + Map<String, String>? parameters,
  113 + });
  114 +
  115 + Future<T?> offNamed<T>(
  116 + String page, {
  117 + dynamic arguments,
  118 + int? id,
  119 + Map<String, String>? parameters,
  120 + });
  121 +
  122 + Future<T?>? offAllNamed<T>(
  123 + String newRouteName, {
  124 + // bool Function(GetPage route)? predicate,
  125 + dynamic arguments,
  126 + int? id,
  127 + Map<String, String>? parameters,
  128 + });
  129 +
  130 + Future<T?>? offNamedUntil<T>(
  131 + String page, {
  132 + bool Function(GetPage route)? predicate,
  133 + dynamic arguments,
  134 + int? id,
  135 + Map<String, String>? parameters,
  136 + });
  137 +
  138 + Future<T?> toNamedAndOffUntil<T>(
  139 + String page,
  140 + bool Function(GetPage) predicate, [
  141 + Object? data,
  142 + ]);
  143 +
  144 + Future<T?> offUntil<T>(
  145 + Widget Function() page,
  146 + bool Function(GetPage) predicate, [
  147 + Object? arguments,
  148 + ]);
  149 +
  150 + void back<T>([T? result]);
  151 +
  152 + Future<R?> backAndtoNamed<T, R>(String page, {T? result, Object? arguments});
  153 +
  154 + void backUntil(bool Function(GetPage) predicate);
  155 +
  156 + void goToUnknownPage([bool clearPages = true]);
  157 +}
  1 +import 'package:flutter/widgets.dart';
  2 +
  3 +import '../../../get.dart';
  4 +
  5 +class GetNavigator extends Navigator {
  6 + GetNavigator.onGenerateRoute({
  7 + GlobalKey<NavigatorState>? key,
  8 + bool Function(Route<dynamic>, dynamic)? onPopPage,
  9 + required List<GetPage> pages,
  10 + List<NavigatorObserver>? observers,
  11 + bool reportsRouteUpdateToEngine = false,
  12 + TransitionDelegate? transitionDelegate,
  13 + String? initialRoute,
  14 + String? restorationScopeId,
  15 + }) : super(
  16 + //keys should be optional
  17 + key: key,
  18 + initialRoute: initialRoute,
  19 + onPopPage: onPopPage ??
  20 + (route, result) {
  21 + final didPop = route.didPop(result);
  22 + if (!didPop) {
  23 + return false;
  24 + }
  25 + return true;
  26 + },
  27 + onGenerateRoute: (settings) {
  28 + final selectedPageList =
  29 + pages.where((element) => element.name == settings.name);
  30 + if (selectedPageList.isNotEmpty) {
  31 + final selectedPage = selectedPageList.first;
  32 + return GetPageRoute(
  33 + page: selectedPage.page,
  34 + settings: settings,
  35 + );
  36 + }
  37 + return null;
  38 + },
  39 + reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,
  40 + restorationScopeId: restorationScopeId,
  41 + pages: pages,
  42 + observers: [
  43 + // GetObserver(),
  44 + ...?observers,
  45 + ],
  46 + transitionDelegate:
  47 + transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
  48 + );
  49 +
  50 + GetNavigator({
  51 + GlobalKey<NavigatorState>? key,
  52 + bool Function(Route<dynamic>, dynamic)? onPopPage,
  53 + required List<GetPage> pages,
  54 + List<NavigatorObserver>? observers,
  55 + bool reportsRouteUpdateToEngine = false,
  56 + TransitionDelegate? transitionDelegate,
  57 + String? initialRoute,
  58 + String? restorationScopeId,
  59 + }) : super(
  60 + //keys should be optional
  61 + key: key,
  62 + initialRoute: initialRoute,
  63 + onPopPage: onPopPage ??
  64 + (route, result) {
  65 + final didPop = route.didPop(result);
  66 + if (!didPop) {
  67 + return false;
  68 + }
  69 + return true;
  70 + },
  71 + reportsRouteUpdateToEngine: reportsRouteUpdateToEngine,
  72 + restorationScopeId: restorationScopeId,
  73 + pages: pages,
  74 + observers: [
  75 + // GetObserver(null, Get.routing),
  76 + HeroController(),
  77 + ...?observers,
  78 + ],
  79 + transitionDelegate:
  80 + transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
  81 + );
  82 +}
  1 +import 'dart:async';
  2 +
1 import 'package:flutter/cupertino.dart'; 3 import 'package:flutter/cupertino.dart';
2 import 'package:flutter/foundation.dart'; 4 import 'package:flutter/foundation.dart';
3 import 'package:flutter/material.dart'; 5 import 'package:flutter/material.dart';
4 -import 'package:flutter/widgets.dart';  
5 6
6 -import '../../../get_core/src/get_main.dart';  
7 -import '../../../get_instance/get_instance.dart'; 7 +import '../../../get_instance/src/bindings_interface.dart';
  8 +import '../../../get_state_manager/src/simple/get_state.dart';
8 import '../../get_navigation.dart'; 9 import '../../get_navigation.dart';
9 -import 'custom_transition.dart';  
10 -import 'transitions_type.dart';  
11 10
12 class GetPage<T> extends Page<T> { 11 class GetPage<T> extends Page<T> {
13 final GetPageBuilder page; 12 final GetPageBuilder page;
@@ -21,12 +20,14 @@ class GetPage<T> extends Page<T> { @@ -21,12 +20,14 @@ class GetPage<T> extends Page<T> {
21 final bool maintainState; 20 final bool maintainState;
22 final bool opaque; 21 final bool opaque;
23 final double Function(BuildContext context)? gestureWidth; 22 final double Function(BuildContext context)? gestureWidth;
24 - final Bindings? binding;  
25 - final List<Bindings> bindings; 23 + //final BindingsInterface? binding;
  24 + final List<BindingsInterface> bindings;
  25 + final List<Bind> binds;
26 final CustomTransition? customTransition; 26 final CustomTransition? customTransition;
27 final Duration? transitionDuration; 27 final Duration? transitionDuration;
28 final bool fullscreenDialog; 28 final bool fullscreenDialog;
29 final bool preventDuplicates; 29 final bool preventDuplicates;
  30 + final Completer<T?>? completer;
30 // @override 31 // @override
31 // final LocalKey? key; 32 // final LocalKey? key;
32 33
@@ -45,6 +46,8 @@ class GetPage<T> extends Page<T> { @@ -45,6 +46,8 @@ class GetPage<T> extends Page<T> {
45 final GetPage? unknownRoute; 46 final GetPage? unknownRoute;
46 final bool showCupertinoParallax; 47 final bool showCupertinoParallax;
47 48
  49 + final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
  50 +
48 GetPage({ 51 GetPage({
49 required this.name, 52 required this.name,
50 required this.page, 53 required this.page,
@@ -59,8 +62,8 @@ class GetPage<T> extends Page<T> { @@ -59,8 +62,8 @@ class GetPage<T> extends Page<T> {
59 this.opaque = true, 62 this.opaque = true,
60 this.transitionDuration, 63 this.transitionDuration,
61 this.popGesture, 64 this.popGesture,
62 - this.binding,  
63 this.bindings = const [], 65 this.bindings = const [],
  66 + this.binds = const [],
64 this.transition, 67 this.transition,
65 this.customTransition, 68 this.customTransition,
66 this.fullscreenDialog = false, 69 this.fullscreenDialog = false,
@@ -70,17 +73,22 @@ class GetPage<T> extends Page<T> { @@ -70,17 +73,22 @@ class GetPage<T> extends Page<T> {
70 this.arguments, 73 this.arguments,
71 this.showCupertinoParallax = true, 74 this.showCupertinoParallax = true,
72 this.preventDuplicates = true, 75 this.preventDuplicates = true,
  76 + this.preventDuplicateHandlingMode =
  77 + PreventDuplicateHandlingMode.ReorderRoutes,
  78 + this.completer,
  79 + LocalKey? key,
73 }) : path = _nameToRegex(name), 80 }) : path = _nameToRegex(name),
74 assert(name.startsWith('/'), 81 assert(name.startsWith('/'),
75 'It is necessary to start route name [$name] with a slash: /$name'), 82 'It is necessary to start route name [$name] with a slash: /$name'),
76 super( 83 super(
77 - key: ValueKey(name), 84 + key: key ?? ValueKey(name),
78 name: name, 85 name: name,
79 - arguments: Get.arguments, 86 + // arguments: Get.arguments,
80 ); 87 );
81 // settings = RouteSettings(name: name, arguments: Get.arguments); 88 // settings = RouteSettings(name: name, arguments: Get.arguments);
82 89
83 GetPage<T> copy({ 90 GetPage<T> copy({
  91 + LocalKey? key,
84 String? name, 92 String? name,
85 GetPageBuilder? page, 93 GetPageBuilder? page,
86 bool? popGesture, 94 bool? popGesture,
@@ -91,13 +99,14 @@ class GetPage<T> extends Page<T> { @@ -91,13 +99,14 @@ class GetPage<T> extends Page<T> {
91 Alignment? alignment, 99 Alignment? alignment,
92 bool? maintainState, 100 bool? maintainState,
93 bool? opaque, 101 bool? opaque,
94 - Bindings? binding,  
95 - List<Bindings>? bindings, 102 + List<BindingsInterface>? bindings,
  103 + // BindingsInterface? binding,
  104 + List<Bind>? binds,
96 CustomTransition? customTransition, 105 CustomTransition? customTransition,
97 Duration? transitionDuration, 106 Duration? transitionDuration,
98 bool? fullscreenDialog, 107 bool? fullscreenDialog,
99 RouteSettings? settings, 108 RouteSettings? settings,
100 - List<GetPage>? children, 109 + List<GetPage<T>>? children,
101 GetPage? unknownRoute, 110 GetPage? unknownRoute,
102 List<GetMiddleware>? middlewares, 111 List<GetMiddleware>? middlewares,
103 bool? preventDuplicates, 112 bool? preventDuplicates,
@@ -105,8 +114,10 @@ class GetPage<T> extends Page<T> { @@ -105,8 +114,10 @@ class GetPage<T> extends Page<T> {
105 bool? participatesInRootNavigator, 114 bool? participatesInRootNavigator,
106 Object? arguments, 115 Object? arguments,
107 bool? showCupertinoParallax, 116 bool? showCupertinoParallax,
  117 + Completer<T?>? completer,
108 }) { 118 }) {
109 return GetPage( 119 return GetPage(
  120 + key: key ?? this.key,
110 participatesInRootNavigator: 121 participatesInRootNavigator:
111 participatesInRootNavigator ?? this.participatesInRootNavigator, 122 participatesInRootNavigator ?? this.participatesInRootNavigator,
112 preventDuplicates: preventDuplicates ?? this.preventDuplicates, 123 preventDuplicates: preventDuplicates ?? this.preventDuplicates,
@@ -120,8 +131,8 @@ class GetPage<T> extends Page<T> { @@ -120,8 +131,8 @@ class GetPage<T> extends Page<T> {
120 alignment: alignment ?? this.alignment, 131 alignment: alignment ?? this.alignment,
121 maintainState: maintainState ?? this.maintainState, 132 maintainState: maintainState ?? this.maintainState,
122 opaque: opaque ?? this.opaque, 133 opaque: opaque ?? this.opaque,
123 - binding: binding ?? this.binding,  
124 bindings: bindings ?? this.bindings, 134 bindings: bindings ?? this.bindings,
  135 + binds: binds ?? this.binds,
125 customTransition: customTransition ?? this.customTransition, 136 customTransition: customTransition ?? this.customTransition,
126 transitionDuration: transitionDuration ?? this.transitionDuration, 137 transitionDuration: transitionDuration ?? this.transitionDuration,
127 fullscreenDialog: fullscreenDialog ?? this.fullscreenDialog, 138 fullscreenDialog: fullscreenDialog ?? this.fullscreenDialog,
@@ -132,6 +143,7 @@ class GetPage<T> extends Page<T> { @@ -132,6 +143,7 @@ class GetPage<T> extends Page<T> {
132 arguments: arguments ?? this.arguments, 143 arguments: arguments ?? this.arguments,
133 showCupertinoParallax: 144 showCupertinoParallax:
134 showCupertinoParallax ?? this.showCupertinoParallax, 145 showCupertinoParallax ?? this.showCupertinoParallax,
  146 + completer: completer ?? this.completer,
135 ); 147 );
136 } 148 }
137 149
@@ -167,6 +179,21 @@ class GetPage<T> extends Page<T> { @@ -167,6 +179,21 @@ class GetPage<T> extends Page<T> {
167 179
168 return PathDecoded(RegExp('^$stringPath\$'), keys); 180 return PathDecoded(RegExp('^$stringPath\$'), keys);
169 } 181 }
  182 +
  183 + @override
  184 + bool operator ==(Object other) {
  185 + if (identical(this, other)) return true;
  186 + return other is GetPage<T> && other.key == key;
  187 + }
  188 +
  189 + @override
  190 + String toString() =>
  191 + '${objectRuntimeType(this, 'Page')}("$name", $key, $arguments)';
  192 +
  193 + @override
  194 + int get hashCode {
  195 + return key.hashCode;
  196 + }
170 } 197 }
171 198
172 @immutable 199 @immutable