Committed by
GitHub
Merge branch 'master' into master
Showing
65 changed files
with
1464 additions
and
1480 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, |
| @@ -13,20 +13,21 @@ class AppPages { | @@ -13,20 +13,21 @@ class AppPages { | ||
| 13 | 13 | ||
| 14 | static final routes = [ | 14 | static final routes = [ |
| 15 | GetPage( | 15 | GetPage( |
| 16 | - name: Routes.HOME, | ||
| 17 | - page: () => HomeView(), | ||
| 18 | - binding: HomeBinding(), | ||
| 19 | - children: [ | ||
| 20 | - GetPage( | ||
| 21 | - name: Routes.COUNTRY, | ||
| 22 | - page: () => CountryView(), | ||
| 23 | - children: [ | ||
| 24 | - GetPage( | ||
| 25 | - name: Routes.DETAILS, | ||
| 26 | - page: () => DetailsView(), | ||
| 27 | - ), | ||
| 28 | - ], | ||
| 29 | - ), | ||
| 30 | - ]), | 16 | + name: Routes.HOME, |
| 17 | + page: () => HomeView(), | ||
| 18 | + bindings: [HomeBinding()], | ||
| 19 | + children: [ | ||
| 20 | + GetPage( | ||
| 21 | + name: Routes.COUNTRY, | ||
| 22 | + page: () => CountryView(), | ||
| 23 | + children: [ | ||
| 24 | + GetPage( | ||
| 25 | + name: Routes.DETAILS, | ||
| 26 | + page: () => DetailsView(), | ||
| 27 | + ), | ||
| 28 | + ], | ||
| 29 | + ), | ||
| 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,32 +7,36 @@ import 'package:get/get.dart'; | @@ -7,32 +7,36 @@ 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( | ||
| 21 | - global: Global( | ||
| 22 | - totalDeaths: 100, | ||
| 23 | - totalConfirmed: 200, | ||
| 24 | - date: DateTime.now(), | ||
| 25 | - newConfirmed: 0, | ||
| 26 | - newDeaths: 0, | ||
| 27 | - newRecovered: 0, | ||
| 28 | - totalRecovered: 0), | ||
| 29 | - countries: [], | ||
| 30 | - date: DateTime.now(), | ||
| 31 | - id: '', | ||
| 32 | - message: '', | ||
| 33 | - ); | ||
| 34 | - } | 20 | + return CasesModel( |
| 21 | + global: Global( | ||
| 22 | + totalDeaths: 100, | ||
| 23 | + totalConfirmed: 200, | ||
| 24 | + date: DateTime.now(), | ||
| 25 | + newConfirmed: 0, | ||
| 26 | + newDeaths: 0, | ||
| 27 | + newRecovered: 0, | ||
| 28 | + totalRecovered: 0), | ||
| 29 | + countries: [], | ||
| 30 | + date: DateTime.now(), | ||
| 31 | + id: '', | ||
| 32 | + message: '', | ||
| 33 | + ); | ||
| 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 | - } | ||
| 83 | - | ||
| 84 | - if (controller.status.isSuccess) { | ||
| 85 | - expect(controller.state!.global.totalDeaths, 100); | ||
| 86 | - expect(controller.state!.global.totalConfirmed, 200); | ||
| 87 | - } | ||
| 88 | - }); | 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); | ||
| 89 | 78 | ||
| 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 = { |
| @@ -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>( | ||
| 9 | - () => DashboardController(), | ||
| 10 | - ); | 7 | + List<Bind> dependencies() { |
| 8 | + return [ | ||
| 9 | + Bind.lazyPut<DashboardController>( | ||
| 10 | + () => DashboardController(), | ||
| 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>( | ||
| 9 | - () => HomeController(), | ||
| 10 | - ); | 7 | + List<Bind> dependencies() { |
| 8 | + return [ | ||
| 9 | + Bind.lazyPut<HomeController>( | ||
| 10 | + () => HomeController(), | ||
| 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>( | ||
| 9 | - () => ProductDetailsController( | ||
| 10 | - Get.parameters['productId'] ?? '', | ||
| 11 | - ), | ||
| 12 | - ); | 7 | + List<Bind> dependencies() { |
| 8 | + return [ | ||
| 9 | + Bind.create<ProductDetailsController>( | ||
| 10 | + () => ProductDetailsController( | ||
| 11 | + Get.parameters['productId'] ?? '', | ||
| 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>( | ||
| 9 | - () => ProfileController(), | ||
| 10 | - ); | 7 | + List<Bind> dependencies() { |
| 8 | + return [ | ||
| 9 | + Bind.lazyPut<ProfileController>( | ||
| 10 | + () => ProfileController(), | ||
| 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>( | ||
| 9 | - () => RootController(), | ||
| 10 | - ); | 7 | + List<Bind> dependencies() { |
| 8 | + return [ | ||
| 9 | + Bind.lazyPut<RootController>( | ||
| 10 | + () => RootController(), | ||
| 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>( | ||
| 9 | - () => SettingsController(), | ||
| 10 | - ); | 7 | + List<Bind> dependencies() { |
| 8 | + return [ | ||
| 9 | + Bind.lazyPut<SettingsController>( | ||
| 10 | + () => SettingsController(), | ||
| 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; |
| @@ -125,18 +123,17 @@ class GetConnect extends GetConnectInterface { | @@ -125,18 +123,17 @@ class GetConnect extends GetConnectInterface { | ||
| 125 | 123 | ||
| 126 | @override | 124 | @override |
| 127 | GetHttpClient get httpClient => _httpClient ??= GetHttpClient( | 125 | GetHttpClient get httpClient => _httpClient ??= GetHttpClient( |
| 128 | - userAgent: userAgent, | ||
| 129 | - sendUserAgent: sendUserAgent, | ||
| 130 | - timeout: timeout, | ||
| 131 | - followRedirects: followRedirects, | ||
| 132 | - maxRedirects: maxRedirects, | ||
| 133 | - maxAuthRetries: maxAuthRetries, | ||
| 134 | - allowAutoSignedCert: allowAutoSignedCert, | ||
| 135 | - baseUrl: baseUrl, | ||
| 136 | - trustedCertificates: trustedCertificates, | ||
| 137 | - withCredentials: withCredentials, | ||
| 138 | - findProxy: findProxy | ||
| 139 | - ); | 126 | + userAgent: userAgent, |
| 127 | + sendUserAgent: sendUserAgent, | ||
| 128 | + timeout: timeout, | ||
| 129 | + followRedirects: followRedirects, | ||
| 130 | + maxRedirects: maxRedirects, | ||
| 131 | + maxAuthRetries: maxAuthRetries, | ||
| 132 | + allowAutoSignedCert: allowAutoSignedCert, | ||
| 133 | + baseUrl: baseUrl, | ||
| 134 | + trustedCertificates: trustedCertificates, | ||
| 135 | + withCredentials: withCredentials, | ||
| 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, |
| @@ -199,16 +207,16 @@ class GetHttpClient { | @@ -199,16 +207,16 @@ class GetHttpClient { | ||
| 199 | int requestNumber = 1, | 207 | int requestNumber = 1, |
| 200 | Map<String, String>? headers, | 208 | Map<String, String>? headers, |
| 201 | }) async { | 209 | }) async { |
| 202 | - var request = await handler(); | 210 | + var request = await handler(); |
| 203 | 211 | ||
| 204 | - headers?.forEach((key, value) { | ||
| 205 | - request.headers[key] = value; | ||
| 206 | - }); | 212 | + headers?.forEach((key, value) { |
| 213 | + request.headers[key] = value; | ||
| 214 | + }); | ||
| 207 | 215 | ||
| 208 | - if (authenticate) await _modifier.authenticator!(request); | ||
| 209 | - final newRequest = await _modifier.modifyRequest<T>(request); | 216 | + if (authenticate) await _modifier.authenticator!(request); |
| 217 | + final newRequest = await _modifier.modifyRequest<T>(request); | ||
| 210 | 218 | ||
| 211 | - _httpClient.timeout = timeout; | 219 | + _httpClient.timeout = timeout; |
| 212 | try { | 220 | try { |
| 213 | var response = await _httpClient.send<T>(newRequest); | 221 | var response = await _httpClient.send<T>(newRequest); |
| 214 | 222 |
| @@ -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(); |
| @@ -162,29 +162,24 @@ class GetInstance { | @@ -162,29 +162,24 @@ 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 | - ); | 167 | + final _dep = _singl[key]; |
| 168 | + if (_dep == null || !_dep.isDirty) { | ||
| 169 | + return; | ||
| 170 | + } else { | ||
| 171 | + dep = _dep as _InstanceBuilderFactory<S>; | ||
| 177 | } | 172 | } |
| 178 | - } else { | ||
| 179 | - _singl[key] = _InstanceBuilderFactory<S>( | ||
| 180 | - isSingleton, | ||
| 181 | - builder, | ||
| 182 | - permanent, | ||
| 183 | - false, | ||
| 184 | - fenix, | ||
| 185 | - name, | ||
| 186 | - ); | ||
| 187 | } | 173 | } |
| 174 | + _singl[key] = _InstanceBuilderFactory<S>( | ||
| 175 | + isSingleton: isSingleton, | ||
| 176 | + builderFunc: builder, | ||
| 177 | + permanent: permanent, | ||
| 178 | + isInit: false, | ||
| 179 | + fenix: fenix, | ||
| 180 | + tag: name, | ||
| 181 | + lateRemove: dep, | ||
| 182 | + ); | ||
| 188 | } | 183 | } |
| 189 | 184 | ||
| 190 | /// Initializes the dependencies for a Class Instance [S] (or tag), | 185 | /// Initializes the dependencies for a Class Instance [S] (or tag), |
| @@ -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,22 +109,24 @@ extension ExtensionDialog on GetInterface { | @@ -112,22 +109,24 @@ 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, | ||
| 121 | - bool barrierDismissible = false, | ||
| 122 | - String? barrierLabel, | ||
| 123 | - Color barrierColor = const Color(0x80000000), | ||
| 124 | - Duration transitionDuration = const Duration(milliseconds: 200), | ||
| 125 | - RouteTransitionsBuilder? transitionBuilder, | ||
| 126 | - GlobalKey<NavigatorState>? navigatorKey, | ||
| 127 | - RouteSettings? routeSettings, | ||
| 128 | - }) { | 117 | + Future<T?> generalDialog<T>( |
| 118 | + {required RoutePageBuilder pageBuilder, | ||
| 119 | + bool barrierDismissible = false, | ||
| 120 | + String? barrierLabel, | ||
| 121 | + Color barrierColor = const Color(0x80000000), | ||
| 122 | + Duration transitionDuration = const Duration(milliseconds: 200), | ||
| 123 | + RouteTransitionsBuilder? transitionBuilder, | ||
| 124 | + GlobalKey<NavigatorState>? navigatorKey, | ||
| 125 | + RouteSettings? routeSettings, | ||
| 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,64 +502,62 @@ extension GetNavigation on GetInterface { | @@ -501,64 +502,62 @@ 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, | ||
| 507 | - Transition? transition, | ||
| 508 | - Curve? curve, | ||
| 509 | - Duration? duration, | ||
| 510 | - int? id, | ||
| 511 | - String? routeName, | ||
| 512 | - bool fullscreenDialog = false, | ||
| 513 | - dynamic arguments, | ||
| 514 | - Bindings? binding, | ||
| 515 | - bool preventDuplicates = true, | ||
| 516 | - bool? popGesture, | ||
| 517 | - 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'), | ||
| 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, | ||
| 539 | - binding: binding, | ||
| 540 | - transitionDuration: duration ?? defaultTransitionDuration, | ||
| 541 | - ), | ||
| 542 | - ); | 505 | + Future<T?>? to<T>(Widget Function() page, |
| 506 | + {bool? opaque, | ||
| 507 | + Transition? transition, | ||
| 508 | + Curve? curve, | ||
| 509 | + Duration? duration, | ||
| 510 | + int? id, | ||
| 511 | + String? routeName, | ||
| 512 | + bool fullscreenDialog = false, | ||
| 513 | + dynamic arguments, | ||
| 514 | + List<BindingsInterface> bindings = const [], | ||
| 515 | + bool preventDuplicates = true, | ||
| 516 | + bool? popGesture, | ||
| 517 | + bool showCupertinoParallax = true, | ||
| 518 | + double Function(BuildContext context)? gestureWidth, | ||
| 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, | ||
| 530 | + fullscreenDialog: fullscreenDialog, | ||
| 531 | + arguments: arguments, | ||
| 532 | + bindings: bindings, | ||
| 533 | + preventDuplicates: preventDuplicates, | ||
| 534 | + popGesture: popGesture, | ||
| 535 | + showCupertinoParallax: showCupertinoParallax, | ||
| 536 | + gestureWidth: gestureWidth, | ||
| 537 | + rebuildStack: rebuildStack, | ||
| 538 | + preventDuplicateHandlingMode: preventDuplicateHandlingMode, | ||
| 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,23 +578,26 @@ you can only use widgets and widget functions here'''; | @@ -579,23 +578,26 @@ 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>( | ||
| 596 | - page, | ||
| 597 | - arguments: arguments, | ||
| 598 | - ); | 594 | + return searchDelegate(id).toNamed( |
| 595 | + page, | ||
| 596 | + arguments: arguments, | ||
| 597 | + id: id, | ||
| 598 | + preventDuplicates: preventDuplicates, | ||
| 599 | + parameters: parameters, | ||
| 600 | + ); | ||
| 599 | } | 601 | } |
| 600 | 602 | ||
| 601 | /// **Navigation.pushReplacementNamed()** shortcut.<br><br> | 603 | /// **Navigation.pushReplacementNamed()** shortcut.<br><br> |
| @@ -618,21 +620,23 @@ you can only use widgets and widget functions here'''; | @@ -618,21 +620,23 @@ 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 | - page, | ||
| 634 | - arguments: arguments, | ||
| 635 | - ); | 633 | + return searchDelegate(id).offNamed( |
| 634 | + page, | ||
| 635 | + arguments: arguments, | ||
| 636 | + id: id, | ||
| 637 | + // preventDuplicates: preventDuplicates, | ||
| 638 | + parameters: parameters, | ||
| 639 | + ); | ||
| 636 | } | 640 | } |
| 637 | 641 | ||
| 638 | /// **Navigation.popUntil()** shortcut.<br><br> | 642 | /// **Navigation.popUntil()** shortcut.<br><br> |
| @@ -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}) { | ||
| 652 | - // if (key.currentState.mounted) // add this if appear problems on future with route navigate | ||
| 653 | - // 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}) { | 655 | + void until(bool Function(GetPage<dynamic>) predicate, {int? id}) { |
| 676 | // 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 |
| 677 | // when widget don't mounted | 657 | // 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,11 +688,13 @@ you can only use widgets and widget functions here'''; | @@ -708,11 +688,13 @@ 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>( | ||
| 712 | - page, | ||
| 713 | - predicate, | ||
| 714 | - arguments: arguments, | ||
| 715 | - ); | 691 | + return searchDelegate(id).offNamedUntil<T>( |
| 692 | + page, | ||
| 693 | + predicate: predicate, | ||
| 694 | + id: id, | ||
| 695 | + arguments: arguments, | ||
| 696 | + parameters: parameters, | ||
| 697 | + ); | ||
| 716 | } | 698 | } |
| 717 | 699 | ||
| 718 | /// **Navigation.popAndPushNamed()** shortcut.<br><br> | 700 | /// **Navigation.popAndPushNamed()** shortcut.<br><br> |
| @@ -737,11 +719,11 @@ you can only use widgets and widget functions here'''; | @@ -737,11 +719,11 @@ 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( | ||
| 741 | - page, | ||
| 742 | - arguments: arguments, | ||
| 743 | - result: result, | ||
| 744 | - ); | 722 | + return searchDelegate(id).backAndtoNamed( |
| 723 | + page, | ||
| 724 | + arguments: arguments, | ||
| 725 | + result: result, | ||
| 726 | + ); | ||
| 745 | } | 727 | } |
| 746 | 728 | ||
| 747 | /// **Navigation.removeRoute()** shortcut.<br><br> | 729 | /// **Navigation.removeRoute()** shortcut.<br><br> |
| @@ -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,11 +768,13 @@ you can only use widgets and widget functions here'''; | @@ -786,11 +768,13 @@ 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>( | ||
| 790 | - newRouteName, | ||
| 791 | - predicate ?? (_) => false, | ||
| 792 | - arguments: arguments, | ||
| 793 | - ); | 771 | + return searchDelegate(id).offAllNamed<T>( |
| 772 | + newRouteName, | ||
| 773 | + //predicate: predicate ?? (_) => false, | ||
| 774 | + arguments: arguments, | ||
| 775 | + id: id, | ||
| 776 | + parameters: parameters, | ||
| 777 | + ); | ||
| 794 | } | 778 | } |
| 795 | 779 | ||
| 796 | /// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN | 780 | /// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN |
| @@ -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 | - ), | ||
| 918 | - routeName: routeName, | ||
| 919 | - fullscreenDialog: fullscreenDialog, | ||
| 920 | - popGesture: popGesture ?? defaultPopGesture, | ||
| 921 | - transition: transition ?? defaultTransition, | ||
| 922 | - curve: curve ?? defaultTransitionCurve, | ||
| 923 | - transitionDuration: duration ?? defaultTransitionDuration)); | 905 | + return searchDelegate(id).off( |
| 906 | + page, | ||
| 907 | + opaque: opaque ?? true, | ||
| 908 | + transition: transition, | ||
| 909 | + curve: curve, | ||
| 910 | + popGesture: popGesture, | ||
| 911 | + id: id, | ||
| 912 | + routeName: routeName, | ||
| 913 | + arguments: arguments, | ||
| 914 | + bindings: bindings, | ||
| 915 | + fullscreenDialog: fullscreenDialog, | ||
| 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 | - arguments: arguments, | ||
| 983 | - ), | ||
| 984 | - fullscreenDialog: fullscreenDialog, | ||
| 985 | - routeName: routeName, | ||
| 986 | - transition: transition ?? defaultTransition, | ||
| 987 | - curve: curve ?? defaultTransitionCurve, | ||
| 988 | - transitionDuration: duration ?? defaultTransitionDuration, | ||
| 989 | - ), | ||
| 990 | - predicate ?? (route) => false); | 982 | + return searchDelegate(id).offAll<T>( |
| 983 | + page, | ||
| 984 | + predicate: predicate, | ||
| 985 | + opaque: opaque ?? true, | ||
| 986 | + popGesture: popGesture, | ||
| 987 | + id: id, | ||
| 988 | + // routeName routeName, | ||
| 989 | + arguments: arguments, | ||
| 990 | + bindings: bindings, | ||
| 991 | + fullscreenDialog: fullscreenDialog, | ||
| 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,72 +239,50 @@ class GetCupertinoApp extends StatelessWidget { | @@ -227,72 +239,50 @@ 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, | ||
| 270 | - navigatorObservers: (navigatorObservers == null | ||
| 271 | - ? <NavigatorObserver>[ | ||
| 272 | - GetObserver(routingCallback, Get.routing) | ||
| 273 | - ] | ||
| 274 | - : <NavigatorObserver>[ | ||
| 275 | - GetObserver(routingCallback, Get.routing) | ||
| 276 | - ] | ||
| 277 | - ..addAll(navigatorObservers!)), | ||
| 278 | - builder: defaultBuilder, | ||
| 279 | - title: title, | ||
| 280 | - onGenerateTitle: onGenerateTitle, | ||
| 281 | - color: color, | ||
| 282 | - locale: Get.locale ?? locale, | ||
| 283 | - localizationsDelegates: localizationsDelegates, | ||
| 284 | - localeListResolutionCallback: localeListResolutionCallback, | ||
| 285 | - localeResolutionCallback: localeResolutionCallback, | ||
| 286 | - supportedLocales: supportedLocales, | ||
| 287 | - showPerformanceOverlay: showPerformanceOverlay, | ||
| 288 | - checkerboardRasterCacheImages: checkerboardRasterCacheImages, | ||
| 289 | - checkerboardOffscreenLayers: checkerboardOffscreenLayers, | ||
| 290 | - showSemanticsDebugger: showSemanticsDebugger, | ||
| 291 | - debugShowCheckedModeBanner: debugShowCheckedModeBanner, | ||
| 292 | - shortcuts: shortcuts, | ||
| 293 | - useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 294 | - // actions: actions, | ||
| 295 | - ), | 242 | + builder: (_) { |
| 243 | + final routerDelegate = Get.createDelegate( | ||
| 244 | + pages: getPages ?? [], | ||
| 245 | + notFoundRoute: unknownRoute, | ||
| 246 | + navigatorKey: navigatorKey, | ||
| 247 | + navigatorObservers: (navigatorObservers == null | ||
| 248 | + ? <NavigatorObserver>[ | ||
| 249 | + GetObserver(routingCallback, Get.routing) | ||
| 250 | + ] | ||
| 251 | + : <NavigatorObserver>[ | ||
| 252 | + GetObserver(routingCallback, Get.routing) | ||
| 253 | + ] | ||
| 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, | ||
| 268 | + builder: defaultBuilder, | ||
| 269 | + title: title, | ||
| 270 | + onGenerateTitle: onGenerateTitle, | ||
| 271 | + color: color, | ||
| 272 | + locale: Get.locale ?? locale, | ||
| 273 | + localizationsDelegates: localizationsDelegates, | ||
| 274 | + localeListResolutionCallback: localeListResolutionCallback, | ||
| 275 | + localeResolutionCallback: localeResolutionCallback, | ||
| 276 | + supportedLocales: supportedLocales, | ||
| 277 | + showPerformanceOverlay: showPerformanceOverlay, | ||
| 278 | + checkerboardRasterCacheImages: checkerboardRasterCacheImages, | ||
| 279 | + checkerboardOffscreenLayers: checkerboardOffscreenLayers, | ||
| 280 | + showSemanticsDebugger: showSemanticsDebugger, | ||
| 281 | + debugShowCheckedModeBanner: debugShowCheckedModeBanner, | ||
| 282 | + shortcuts: shortcuts, | ||
| 283 | + useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 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,148 +192,117 @@ class GetMaterialApp extends StatelessWidget { | @@ -183,148 +192,117 @@ 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, | ||
| 209 | - dispose: (d) { | ||
| 210 | - onDispose?.call(); | ||
| 211 | - }, | ||
| 212 | - initState: (i) { | ||
| 213 | - Get.engine!.addPostFrameCallback((timeStamp) { | ||
| 214 | - onReady?.call(); | ||
| 215 | - }); | ||
| 216 | - if (locale != null) Get.locale = locale; | 206 | + init: Get.rootController, |
| 207 | + dispose: (d) { | ||
| 208 | + onDispose?.call(); | ||
| 209 | + Get.clearRouteTree(); | ||
| 210 | + Get.clearTranslations(); | ||
| 211 | + Get.resetRootNavigator(); | ||
| 212 | + Get.routerDelegate = null; | ||
| 213 | + Get.routeInformationParser = null; | ||
| 214 | + }, | ||
| 215 | + initState: (i) { | ||
| 216 | + // Get.routerDelegate = routerDelegate; | ||
| 217 | + // Get.routeInformationParser = routeInformationParser; | ||
| 218 | + Get.engine.addPostFrameCallback((timeStamp) { | ||
| 219 | + onReady?.call(); | ||
| 220 | + }); | ||
| 221 | + if (locale != null) Get.locale = locale; | ||
| 217 | 222 | ||
| 218 | - if (fallbackLocale != null) Get.fallbackLocale = fallbackLocale; | 223 | + if (fallbackLocale != null) Get.fallbackLocale = fallbackLocale; |
| 219 | 224 | ||
| 220 | - if (translations != null) { | ||
| 221 | - Get.addTranslations(translations!.keys); | ||
| 222 | - } else if (translationsKeys != null) { | ||
| 223 | - Get.addTranslations(translationsKeys!); | ||
| 224 | - } | 225 | + if (translations != null) { |
| 226 | + Get.addTranslations(translations!.keys); | ||
| 227 | + } else if (translationsKeys != null) { | ||
| 228 | + Get.addTranslations(translationsKeys!); | ||
| 229 | + } | ||
| 225 | 230 | ||
| 226 | - Get.customTransition = customTransition; | 231 | + Get.customTransition = customTransition; |
| 227 | 232 | ||
| 228 | - initialBinding?.dependencies(); | ||
| 229 | - if (getPages != null) { | ||
| 230 | - Get.addPages(getPages!); | ||
| 231 | - } | 233 | + initialBinding?.dependencies(); |
| 234 | + if (getPages != null) { | ||
| 235 | + Get.addPages(getPages!); | ||
| 236 | + } else { | ||
| 237 | + Get.addPage( | ||
| 238 | + GetPage( | ||
| 239 | + name: _cleanRouteName("/${home.runtimeType}"), | ||
| 240 | + page: () => home!, | ||
| 241 | + ), | ||
| 242 | + ); | ||
| 243 | + } | ||
| 232 | 244 | ||
| 233 | - //Get.setDefaultDelegate(routerDelegate); | ||
| 234 | - Get.smartManagement = smartManagement; | ||
| 235 | - onInit?.call(); | 245 | + //Get.setDefaultDelegate(routerDelegate); |
| 246 | + Get.smartManagement = smartManagement; | ||
| 247 | + onInit?.call(); | ||
| 236 | 248 | ||
| 237 | - Get.config( | ||
| 238 | - enableLog: enableLog ?? Get.isLogEnable, | ||
| 239 | - logWriterCallback: logWriterCallback, | ||
| 240 | - defaultTransition: defaultTransition ?? Get.defaultTransition, | ||
| 241 | - defaultOpaqueRoute: opaqueRoute ?? Get.isOpaqueRouteDefault, | ||
| 242 | - defaultPopGesture: popGesture ?? Get.isPopGestureEnable, | ||
| 243 | - defaultDurationTransition: | ||
| 244 | - transitionDuration ?? Get.defaultTransitionDuration, | ||
| 245 | - ); | ||
| 246 | - }, | ||
| 247 | - builder: (_) => routerDelegate != null | ||
| 248 | - ? MaterialApp.router( | ||
| 249 | - routerDelegate: routerDelegate!, | ||
| 250 | - routeInformationParser: routeInformationParser!, | ||
| 251 | - backButtonDispatcher: backButtonDispatcher, | ||
| 252 | - routeInformationProvider: routeInformationProvider, | ||
| 253 | - key: _.unikey, | ||
| 254 | - builder: defaultBuilder, | ||
| 255 | - title: title, | ||
| 256 | - onGenerateTitle: onGenerateTitle, | ||
| 257 | - color: color, | ||
| 258 | - 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(), | ||
| 310 | - themeMode: _.themeMode ?? themeMode, | ||
| 311 | - locale: Get.locale ?? locale, | ||
| 312 | - localizationsDelegates: localizationsDelegates, | ||
| 313 | - localeListResolutionCallback: localeListResolutionCallback, | ||
| 314 | - localeResolutionCallback: localeResolutionCallback, | ||
| 315 | - supportedLocales: supportedLocales, | ||
| 316 | - debugShowMaterialGrid: debugShowMaterialGrid, | ||
| 317 | - showPerformanceOverlay: showPerformanceOverlay, | ||
| 318 | - checkerboardRasterCacheImages: checkerboardRasterCacheImages, | ||
| 319 | - checkerboardOffscreenLayers: checkerboardOffscreenLayers, | ||
| 320 | - showSemanticsDebugger: showSemanticsDebugger, | ||
| 321 | - debugShowCheckedModeBanner: debugShowCheckedModeBanner, | ||
| 322 | - shortcuts: shortcuts, | ||
| 323 | - scrollBehavior: scrollBehavior, | ||
| 324 | - useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 325 | - // actions: actions, | ||
| 326 | - ), | ||
| 327 | - ); | 249 | + Get.config( |
| 250 | + enableLog: enableLog ?? Get.isLogEnable, | ||
| 251 | + logWriterCallback: logWriterCallback, | ||
| 252 | + defaultTransition: defaultTransition ?? Get.defaultTransition, | ||
| 253 | + defaultOpaqueRoute: opaqueRoute ?? Get.isOpaqueRouteDefault, | ||
| 254 | + defaultPopGesture: popGesture ?? Get.isPopGestureEnable, | ||
| 255 | + defaultDurationTransition: | ||
| 256 | + transitionDuration ?? Get.defaultTransitionDuration, | ||
| 257 | + ); | ||
| 258 | + }, | ||
| 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, | ||
| 279 | + backButtonDispatcher: backButtonDispatcher, | ||
| 280 | + routeInformationProvider: routeInformationProvider, | ||
| 281 | + key: _.unikey, | ||
| 282 | + builder: defaultBuilder, | ||
| 283 | + title: title, | ||
| 284 | + onGenerateTitle: onGenerateTitle, | ||
| 285 | + color: color, | ||
| 286 | + theme: _.theme ?? theme ?? ThemeData.fallback(), | ||
| 287 | + darkTheme: _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(), | ||
| 288 | + themeMode: _.themeMode ?? themeMode, | ||
| 289 | + locale: Get.locale ?? locale, | ||
| 290 | + scaffoldMessengerKey: scaffoldMessengerKey ?? _.scaffoldMessengerKey, | ||
| 291 | + localizationsDelegates: localizationsDelegates, | ||
| 292 | + localeListResolutionCallback: localeListResolutionCallback, | ||
| 293 | + localeResolutionCallback: localeResolutionCallback, | ||
| 294 | + supportedLocales: supportedLocales, | ||
| 295 | + debugShowMaterialGrid: debugShowMaterialGrid, | ||
| 296 | + showPerformanceOverlay: showPerformanceOverlay, | ||
| 297 | + checkerboardRasterCacheImages: checkerboardRasterCacheImages, | ||
| 298 | + checkerboardOffscreenLayers: checkerboardOffscreenLayers, | ||
| 299 | + showSemanticsDebugger: showSemanticsDebugger, | ||
| 300 | + debugShowCheckedModeBanner: debugShowCheckedModeBanner, | ||
| 301 | + shortcuts: shortcuts, | ||
| 302 | + scrollBehavior: scrollBehavior, | ||
| 303 | + useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 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 |
-
Please register or login to post a comment