Jonatas

update to 3.13.2

Showing 88 changed files with 61 additions and 4496 deletions

Too many changes to show.

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

{
// Use o IntelliSense para aprender sobre possíveis atributos.
// Passe o mouse para ver as descrições dos atributos existentes.
// Para obter mais informações, visite: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "getx",
"cwd": "getx",
"request": "launch",
"type": "dart"
},
{
"name": "example debug",
"cwd": "getx/example",
"request": "launch",
"flutterMode": "debug",
"type": "dart"
},
{
"name": "example profile",
"cwd": "getx/example",
"request": "launch",
"flutterMode": "profile",
"type": "dart"
},
{
"name": "example release",
"cwd": "getx/example",
"request": "launch",
"flutterMode": "release",
"type": "dart"
},
{
"name": "get_core",
"cwd": "packages/get_core",
"request": "launch",
"type": "dart"
},
{
"name": "get_instance",
"cwd": "packages/get_instance",
"request": "launch",
"type": "dart"
},
{
"name": "get_navigation",
"cwd": "packages/get_navigation",
"request": "launch",
"type": "dart"
},
{
"name": "get_rx",
"cwd": "packages/get_rx",
"request": "launch",
"type": "dart"
},
{
"name": "get_state_manager",
"cwd": "packages/get_state_manager",
"request": "launch",
"type": "dart"
},
{
"name": "get_test",
"cwd": "packages/get_test",
"request": "launch",
"type": "dart"
},
{
"name": "get_utils",
"cwd": "packages/get_utils",
"request": "launch",
"type": "dart"
}
]
}
\ No newline at end of file
## [3.13.2]
- Reunification of the package.
During the 2 week period, we try to keep this package as a compilation of smaller packages. We were successful in separating, getx is well decoupled and it was only necessary to send the internal folders as packages to pub.dev, however, it became very complicated to contribute to the package. This is because it was necessary to clone the repository, replace all pubspec packages with local paths, and after modification, return the original paths to do the PR. With that, the frequency of updates, which was about 4 to 5 days, became almost 2 weeks, and this is not legal for a community as active as Getx, which uses this package precisely in addition to being modern and performance, be constantly improving. This led contributors to the conclusion that getx works best together.
Additional packages will continue to be maintained, and will have the same base as the main package, however, development will take place in the full and main package, and as the addition of new features or bug fixes arrives, we will migrate to the individual packages . Getx reached the mark of 50 contributors today, more than 1500 likes in the pub, and will continue to make development easy.
## [3.13.1]
- Remove spaces whitespaces from dart files
-
... ...
![](get.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
*Idiomas: Español (este archivo), [Lengua china](README.zh-cn.md), [Inglés](README.md), [Portugués de Brasil](README.pt-br.md), [Polaco](README.pl.md).*
... ... @@ -13,30 +13,30 @@
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
![](getx.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
<h3>Lamentamos la inconsistencia en la traducción. El paquete GetX se actualiza con bastante frecuencia y es posible que las traducciones a documentos no sean tan rápidas. Entonces, para que esta documentación aún tenga todo el contenido, dejaré aquí todos los textos nuevos sin traducir (considero que es mejor tener los documentos en inglés que no tenerlos), por lo que si alguien quiere traducir, sería de gran ayuda 😁</h3>
- [Communication and support channels:](#communication-and-support-channels)
- [Sobre GetX](#sobre-getx)
- [Como contribuir](#como-contribuir)
- [Instalando](#installing)
- [Proyecto Counter en GetX](#proyeto-counter-no-getx)
- [Installing](#installing)
- [Proyecto Counter no GetX](#proyecto-counter-no-getx)
- [Los tres pilares](#los-tres-pilares)
- [Gestión del Estado](#gestión-del-estado)
- [STATE_MANAGER Reactivo](#reactivo-state_manager)
- [Reactivo STATE_MANAGER](#reactivo-state_manager)
- [Más detalles sobre la gestión del estado.](#más-detalles-sobre-la-gestión-del-estado)
- [Explicación en video sobre state management](#video-explanation-about-state-management)
- [Explicación en video sobre state management](#explicación-en-video-sobre-state-management)
- [Gestión de Rutas](#gestión-de-rutas)
- [Más detalles sobre la gestión de rutas.](#más-detalles-sobre-la-gestión-de-rutas)
- [Explicación del video](#video-explanation)
- [Explicación del video](#explicación-del-video)
- [Gestión de dependencias](#gestión-de-dependencias)
- [Más detalles sobre la gestión de dependencias.](#más-detalles-sobre-la-gestión-de-dependencias)
- [Utilidades](#utils)
- [Utilidades](#utilidades)
- [Cambiar de tema](#cambiar-de-tema)
- [Otras API avanzadas y configuraciones manuales](#otras-api-avanzadas-y-configuraciones-manuales)
- [Configuraciones globales opcionales](#configuraciones-globales-opcionales)
- [Explicación en video de Other GetX Features](#video-explanation-of-other-getx-features)
- [Video explanation of Other GetX Features](#video-explanation-of-other-getx-features)
- [Rompiendo cambios desde 2.0](#rompiendo-cambios-desde-20)
- [¿Por qué Getx?](#por-qué-getx)
... ... @@ -155,7 +155,7 @@ class Other extends StatelessWidget {
Resultado:
![](counter-app-gif.gif)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
Este es un proyecto simple pero ya deja en claro cuán poderoso es GetX. A medida que su proyecto crezca, esta diferencia se volverá más significativa. GetX fue diseñado para trabajar con equipos, pero también simplifica el trabajo de un desarrollador individual. Mejore sus plazos, entregue todo a tiempo, sin perder rendimiento. GetX no es para todos, pero si te identificaste con esa frase, ¡GET es para ti!
... ...
![](get.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
_Languages: English (this file), [Chinese](README.zh-cn.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md),[Polish](README.pl.md)._
... ... @@ -13,7 +13,7 @@ _Languages: English (this file), [Chinese](README.zh-cn.md), [Brazilian Portugue
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
![](getx.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
- [About Get](#about-get)
- [Installing](#installing)
... ... @@ -148,7 +148,7 @@ class Other extends StatelessWidget {
Result:
![](counter-app-gif.gif)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
This is a simple project but it already makes clear how powerful Get is. As your project grows, this difference will become more significant.
... ...
![](get.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
*Languages: [English](README.md), [Język chiński](README.zh-cn.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md), Polish (Jesteś tu).*
... ... @@ -14,28 +14,28 @@
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
![](getx.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
- [Kanały komunikacji i wsparcia:](#kanały-komunikacji-i-wsparcia)
- [Wprowadzenie](#wprowadzenie)
- [Instalacja](#instalacja)
- [Counter App z GetX](#counter-app-z-getx)
- [Trzy fialary](#trzy-filary)
- [Trzy filary](#trzy-filary)
- [Menadżer stanu](#menadżer-stanu)
- [Reaktywny menadżer stanu](#reaktywny-menadżer-stanu)
- [Bardziej szczegółowo o menadżerze stanu](#bardziej-szczegółowo-o-menadżerze-stanu)
- [Video tłumaczące użycie menadżera stanu](#video-tłumaczące-użycie-menadżera-stanu)
- [Zarzadzanie routami](#zarządzanie-routami)
- [Zarządzanie routami](#zarządzanie-routami)
- [Więcej o routach](#więcej-o-routach)
- [Video tłumaczące użycie](#video-tłumaczące-użycie)
- [Zarządzanie dependencies](#zarządzanie-dependencies)
- [Bardziej szczefółowo o menadżerze dependencies](#bardziej-szczegółowo-o-menadżerze-dependencies)
- [Bardziej szczegółowo o menadżerze dependencies](#bardziej-szczegółowo-o-menadżerze-dependencies)
- [Jak włożyć coś od siebie](#jak-włożyć-coś-od-siebie)
- [Narzędzia](#narzędzia)
- [Zmiana motywu](#zmiana-motywu)
- [Inne zaawansowane API](#inne-zaawansowane-api)
- [Inne zaawansowane API](#inne-zaawansowane-api)
- [Opcjonalne globalne ustawienia i manualna konfiguracja](#opcjonalne-globalne-ustawienia-i-manualna-konfiguracja)
- [Video tłumaczace inne funkcjonalności GetX](#video-tłumaczące-inne-funkcjonalności-getx)
- [Video tłumaczące inne funkcjonalności GetX](#video-tłumaczące-inne-funkcjonalności-getx)
- [Zmiany od 2.0](#zmiany-od-20)
... ... @@ -130,7 +130,7 @@ class Other extends StatelessWidget {
```
Wynik:
![](counter-app-gif.gif)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
Jest to prosty projekt, ale już na jego przykładzie widać potęgę Get. Wzraz ze wzrostem rozmiaru aplikacji ta różnica tylko się powieksza.
... ...
![](get.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
*Idiomas: [Inglês](README.md), [Língua chinesa](README.zh-cn.md), Português Brasileiro (este arquivo), [Espanhol](README-es.md), [Polaco](README.pl.md).*
... ... @@ -14,7 +14,7 @@
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
![](getx.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
<h2> Pedimos desculpas por qualquer parte não traduzida aqui. O GetX™ é atualizado com muita frequência e as traduções podem não vir ao mesmo tempo. Então, para manter essa documentação pelo menos com tudo que a versão em inglês tem, eu vou deixar todos os textos não-traduzidos aqui (eu considero que é melhor ele estar lá em inglês do que não estar), então se alguém quiser traduzir, seria muito útil 😁</h2>
... ... @@ -36,7 +36,7 @@
- [Traduções](#traduções)
- [Usando traduções](#usando-traduções)
- [Localidade](#localidade)
- [Alterar Local](#alterar-local)
- [Alterar local](#alterar-local)
- [Localidade do sistema operacional](#localidade-do-sistema-operacional)
- [Mudar tema (changeTheme)](#mudar-tema-changetheme)
- [Outras APIs avançadas](#outras-apis-avançadas)
... ... @@ -44,17 +44,17 @@
- [Widgets de Estado Local](#widgets-de-estado-local)
- [ValueBuilder](#valuebuilder)
- [ObxValue](#obxvalue)
- [Explicação em vídeo sobre Outras Features do GetX](#explicação-em-vídeo-sobre-outras-features-do-getx)
- [Dicas Úteis](#dicas-úteis)
- [GetView](#getview)
- [GetWidget](#getwidget)
- [GetxService](#getxservice)
- [Explicação em vídeo sobre Outras Features do GetX](#explicação-em-vídeo-sobre-outras-features-do-getx)
- [Breaking Changes da versão 2 para 3](#breaking-changes-da-versão-2-para-3)
- [Tipagem Rx](#tipagem-rx)
- [RxController e GetBuilder se uniram](#rxcontroller-e-getbuilder-se-uniram)
- [Rotas nomeadas](#rotas-nomeadas)
- [Porque essa mudança](#porque-essa-mudança)
- [Por que GetX?](#por-que-getx)
- [Porque essa mudança?](#porque-essa-mudança)
- [Por que GetX™?](#por-que-getx)
- [Comunidade](#comunidade)
- [Canais da comunidade](#canais-da-comunidade)
- [Como contribuir](#como-contribuir)
... ... @@ -147,7 +147,7 @@ class Outra extends StatelessWidget {
Resultado:
![](counter-app-gif.gif)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
Esse é um projeto simples mas já deixa claro o quão poderoso o Get é. Enquanto seu projeto cresce, essa diferença se torna bem mais significante.
... ... @@ -824,14 +824,14 @@ o ciclo de vida de seu aplicativo, use GetxService.
## Tipagem Rx
| Antes | Depois |
| -------- | ---------- |
| StringX | `RxString` |
| IntX | `RxInt` |
| MapX | `RxMap` |
| ListX | `RxList` |
| NumX | `RxNum` |
| DoubleX | `RxDouble` |
| Antes | Depois |
| ------- | ---------- |
| StringX | `RxString` |
| IntX | `RxInt` |
| MapX | `RxMap` |
| ListX | `RxList` |
| NumX | `RxNum` |
| DoubleX | `RxDouble` |
## RxController e GetBuilder se uniram
... ...
![](get.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
_语言: 中文, [英文](README.md), [巴西葡萄牙语](README.pt-br.md), [西班牙语](README-es.md), [波兰语](README.pl.md)_
... ... @@ -13,11 +13,11 @@ _语言: 中文, [英文](README.md), [巴西葡萄牙语](README.pt-br.md), [
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
![](getx.png)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
- [关于 Get](#关于Get)
- [关于Get](#关于get)
- [安装](#安装)
- [GetX 的计数器示例](#GetX的计数器示例)
- [GetX的计数器示例](#getx的计数器示例)
- [三大功能](#三大功能)
- [状态管理](#状态管理)
- [响应式状态管理器](#响应式状态管理器)
... ... @@ -34,7 +34,7 @@ _语言: 中文, [英文](README.md), [巴西葡萄牙语](README.pt-br.md), [
- [改变语言](#改变语言)
- [系统语言](#系统语言)
- [改变主题](#改变主题)
- [其他高级API](#其他高级API)
- [其他高级API](#其他高级api)
- [可选的全局设置和手动配置](#可选的全局设置和手动配置)
- [局部状态组件](#局部状态组件)
- [ValueBuilder](#valuebuilder)
... ... @@ -43,10 +43,10 @@ _语言: 中文, [英文](README.md), [巴西葡萄牙语](README.pt-br.md), [
- [GetView](#getview)
- [GetWidget](#getwidget)
- [GetxService](#getxservice)
- [从2.0开始的兼容性变化](#从2.0开始的兼容性变化)
- [为什么选择Getx?](#为什么选择Getx?)
- [从2.0开始的兼容性变化](#从20开始的兼容性变化)
- [为什么选择Getx?](#为什么选择getx)
- [社区](#社区)
- [社区频道](#社区频)
- [社区渠道](#社区渠)
- [如何做贡献](#如何做贡献)
- [文章和视频](#文章和视频)
... ... @@ -151,7 +151,7 @@ class Other extends StatelessWidget {
结果:
![](counter-app-gif.gif)
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
这是一个简单的项目,但它已经让人明白Get的强大。随着项目的发展,这种差异将变得更加显著。
... ...
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 29
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "getx.demo.app.example"
minSdkVersion 16
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="getx.demo.app.example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="getx.demo.app.example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
package getx.demo.app.example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@android:color/white</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="getx.demo.app.example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
cmake_minimum_required(VERSION 3.10)
project(runner LANGUAGES CXX)
set(BINARY_NAME "example")
set(APPLICATION_ID "getx.demo.app.example")
cmake_policy(SET CMP0063 NEW)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Configure build options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
# Compilation settings that should be applied to most targets.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
# Flutter library and tool build rules.
add_subdirectory(${FLUTTER_MANAGED_DIR})
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Application build
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
apply_standard_settings(${BINARY_NAME})
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
add_dependencies(${BINARY_NAME} flutter_assemble)
# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
PkgConfig::BLKID
)
add_dependencies(flutter flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
linux-x64 ${CMAKE_BUILD_TYPE}
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)
//
// Generated file. Do not edit.
//
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}
//
// Generated file. Do not edit.
//
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
#include "my_application.h"
int main(int argc, char** argv) {
// Only X11 is currently supported.
// Wayland support is being developed: https://github.com/flutter/flutter/issues/57932.
gdk_set_allowed_backends("x11");
g_autoptr(MyApplication) app = my_application_new();
return g_application_run(G_APPLICATION(app), argc, argv);
}
#include "my_application.h"
#include <flutter_linux/flutter_linux.h>
#include "flutter/generated_plugin_registrant.h"
struct _MyApplication {
GtkApplication parent_instance;
};
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "example");
gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new();
FlView* view = fl_view_new(project);
gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
gtk_widget_grab_focus(GTK_WIDGET(view));
}
static void my_application_class_init(MyApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
}
static void my_application_init(MyApplication* self) {}
MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
nullptr));
}
#ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
GtkApplication)
/**
* my_application_new:
*
* Creates a new Flutter-based application.
*
* Returns: a new #MyApplication.
*/
MyApplication* my_application_new();
#endif // FLUTTER_MY_APPLICATION_H_
... ... @@ -27,16 +27,14 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
get:
git:
url: git://github.com/jonataslaw/getx.git
path: getx
ref: master
path: ../
dio: ^3.0.9
get_test:
git:
url: git://github.com/jonataslaw/getx.git
path: packages/get_test
ref: master
get_test: ^3.13.2
dependency_overrides:
get:
path: ../
dev_dependencies:
flutter_test:
sdk: flutter
... ...
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="example">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>example</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('flutter_service_worker.js');
});
}
</script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
{
"name": "example",
"short_name": "example",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "A new Flutter project.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
... ... @@ -184,4 +184,3 @@ class SizeTransitions {
);
}
}
... ...
import 'dart:async';
import 'dart:collection';
import 'package:meta/meta.dart';
import 'package:flutter/foundation.dart';
import '../rx_core/rx_interface.dart';
part 'rx_num.dart';
... ...
import 'dart:async';
import 'dart:collection';
import 'dart:math';
import 'package:meta/meta.dart';
import 'package:flutter/foundation.dart';
import '../rx_core/rx_impl.dart';
import '../rx_core/rx_interface.dart';
... ...
import 'dart:async';
import 'dart:collection';
import 'package:meta/meta.dart';
import 'package:flutter/foundation.dart';
import '../rx_core/rx_impl.dart';
import '../rx_core/rx_interface.dart';
import '../rx_typedefs/rx_typedefs.dart';
... ...
import 'dart:async';
import 'dart:collection';
import 'package:meta/meta.dart';
import 'package:flutter/foundation.dart';
import '../rx_core/rx_impl.dart';
import '../rx_core/rx_interface.dart';
... ...
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: a27c242b0eea731317cfec5bbdd9d35452ab3ecb
channel: dev
project_type: package
## [3.13.0]
* Bump to Get 3.13.0
## [3.12.0]
* Bump to Get 3.12.0
## [3.10.2]
* Initial release
MIT License
Copyright (c) 2019 Jonny Borges
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# get_core
A new Flutter package project.
## Getting Started
This project is a starting point for a Dart
[package](https://flutter.dev/developing-packages/),
a library module containing code that can be shared easily across
multiple Flutter or Dart projects.
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# Include option is buggy:
# https://github.com/flutter/flutter/issues/62591
# In case the include issue gets fixed, lines below INCLUDE_FIX
# can be removed
# include: package:effective_dart/analysis_options.1.2.0.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
await_only_futures: true
# This one is desirable, but that's a lot of work for now
public_member_api_docs: false
# Desirable, but would be breaking changes:
avoid_positional_boolean_parameters: false
constant_identifier_names: false
include_file_not_found: false
# INCLUDE_FIX (copy of effective dart 1.2.0)
# STYLE
camel_case_types: true
camel_case_extensions: true
library_names: true
file_names: true
library_prefixes: true
non_constant_identifier_names: true
directives_ordering: true
lines_longer_than_80_chars: true # avoid
curly_braces_in_flow_control_structures: true
# DOCUMENTATION
slash_for_doc_comments: true
package_api_docs: true # prefer
#- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
# USAGE
implementation_imports: true
avoid_relative_lib_imports: true # prefer
prefer_relative_imports: true # prefer
prefer_adjacent_string_concatenation: true
prefer_interpolation_to_compose_strings: true # prefer
unnecessary_brace_in_string_interps: true # avoid
prefer_collection_literals: true
avoid_function_literals_in_foreach_calls: true # avoid
prefer_iterable_whereType: true
prefer_function_declarations_over_variables: true
unnecessary_lambdas: true
prefer_equal_for_default_values: true
avoid_init_to_null: true
unnecessary_getters_setters: true
#- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
#- prefer_expression_function_bodies # consider
unnecessary_this: true
prefer_initializing_formals: true
type_init_formals: true
empty_constructor_bodies: true
unnecessary_new: true
unnecessary_const: true
avoid_catches_without_on_clauses: true # avoid
avoid_catching_errors: true
use_rethrow_when_possible: true
# DESIGN
use_to_and_as_if_applicable: true # prefer
one_member_abstracts: true # avoid
avoid_classes_with_only_static_members: true # avoid
prefer_mixin: true
prefer_final_fields: true # prefer
use_setters_to_change_properties: true
avoid_setters_without_getters: true
avoid_returning_null: true # avoid
avoid_returning_this: true # avoid
type_annotate_public_apis: true # prefer
#- prefer_typing_uninitialized_variables # consider
omit_local_variable_types: true # avoid
avoid_types_on_closure_parameters: true # avoid
avoid_return_types_on_setters: true # avoid
prefer_generic_function_type_aliases: true
avoid_private_typedef_functions: true # prefer
#- use_function_type_syntax_for_parameters # consider
hash_and_equals: true
avoid_equals_and_hash_code_on_mutable_classes: true # avoid
avoid_null_checks_in_equality_operators: true
library get_core;
export 'src/get_interface.dart';
export 'src/get_main.dart';
export 'src/log.dart';
export 'src/smart_management.dart';
import 'log.dart';
import 'smart_management.dart';
/// GetInterface allows any auxiliary package to be merged into the "Get"
/// class through extensions
abstract class GetInterface {
SmartManagement smartManagement = SmartManagement.full;
String reference;
bool isLogEnable = true;
LogWriterCallback log = defaultLogWriterCallback;
}
import 'get_interface.dart';
///Use to instead of Navigator.push, off instead of Navigator.pushReplacement,
///offAll instead of Navigator.pushAndRemoveUntil. For named routes just
///add "named" after them. Example: toNamed, offNamed, and AllNamed.
///To return to the previous screen, use back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
class _GetImpl extends GetInterface {}
// ignore: non_constant_identifier_names
final Get = _GetImpl();
import 'dart:developer' as developer;
import 'get_main.dart';
///Voidcallback from logs
typedef LogWriterCallback = void Function(String text, {bool isError});
/// default logger from GetX
void defaultLogWriterCallback(String value, {bool isError = false}) {
if (isError || Get.isLogEnable) developer.log(value, name: 'GETX');
}
/// GetX by default disposes unused controllers from memory,
/// Through different behaviors.
/// SmartManagement.full
/// [SmartManagement.full] is the default one. Dispose classes that are
/// not being used and were not set to be permanent. In the majority
/// of the cases you will want to keep this config untouched.
/// If you new to GetX then don't change this.
/// [SmartManagement.onlyBuilders] only controllers started in init:
/// or loaded into a Binding with Get.lazyPut() will be disposed. If you use
/// Get.put() or Get.putAsync() or any other approach, SmartManagement
/// will not have permissions to exclude this dependency. With the default
/// behavior, even widgets instantiated with "Get.put" will be removed,
/// unlike SmartManagement.onlyBuilders.
/// [SmartManagement.keepFactory]Just like SmartManagement.full,
/// it will remove it's dependencies when it's not being used anymore.
/// However, it will keep their factory, which means it will recreate
/// the dependency if you need that instance again.
enum SmartManagement {
full,
onlyBuilder,
keepFactory,
}
name: get_core
description: A base package from allow use resources from GetX™ framework.
version: 3.13.0
homepage: https://github.com/jonataslaw/getx
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
dev_dependencies:
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# To add custom fonts to your package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: a27c242b0eea731317cfec5bbdd9d35452ab3ecb
channel: dev
project_type: package
## [3.13.0]
* Bump to Get 3.13.0
## [3.12.0]
* Bump to Get 3.12.0
## [3.10.2]
- Initial release
MIT License
Copyright (c) 2019 Jonny Borges
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# get_instance
A new Flutter package project.
## Getting Started
This project is a starting point for a Dart
[package](https://flutter.dev/developing-packages/),
a library module containing code that can be shared easily across
multiple Flutter or Dart projects.
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# Include option is buggy:
# https://github.com/flutter/flutter/issues/62591
# In case the include issue gets fixed, lines below INCLUDE_FIX
# can be removed
# include: package:effective_dart/analysis_options.1.2.0.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
await_only_futures: true
# This one is desirable, but that's a lot of work for now
public_member_api_docs: false
# Desirable, but would be breaking changes:
avoid_positional_boolean_parameters: false
constant_identifier_names: false
include_file_not_found: false
# INCLUDE_FIX (copy of effective dart 1.2.0)
# STYLE
camel_case_types: true
camel_case_extensions: true
library_names: true
file_names: true
library_prefixes: true
non_constant_identifier_names: true
directives_ordering: true
lines_longer_than_80_chars: true # avoid
curly_braces_in_flow_control_structures: true
# DOCUMENTATION
slash_for_doc_comments: true
package_api_docs: true # prefer
#- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
# USAGE
implementation_imports: true
avoid_relative_lib_imports: true # prefer
prefer_relative_imports: true # prefer
prefer_adjacent_string_concatenation: true
prefer_interpolation_to_compose_strings: true # prefer
unnecessary_brace_in_string_interps: true # avoid
prefer_collection_literals: true
avoid_function_literals_in_foreach_calls: true # avoid
prefer_iterable_whereType: true
prefer_function_declarations_over_variables: true
unnecessary_lambdas: true
prefer_equal_for_default_values: true
avoid_init_to_null: true
unnecessary_getters_setters: true
#- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
#- prefer_expression_function_bodies # consider
unnecessary_this: true
prefer_initializing_formals: true
type_init_formals: true
empty_constructor_bodies: true
unnecessary_new: true
unnecessary_const: true
avoid_catches_without_on_clauses: true # avoid
avoid_catching_errors: true
use_rethrow_when_possible: true
# DESIGN
use_to_and_as_if_applicable: true # prefer
one_member_abstracts: true # avoid
avoid_classes_with_only_static_members: true # avoid
prefer_mixin: true
prefer_final_fields: true # prefer
use_setters_to_change_properties: true
avoid_setters_without_getters: true
avoid_returning_null: true # avoid
avoid_returning_this: true # avoid
type_annotate_public_apis: true # prefer
#- prefer_typing_uninitialized_variables # consider
omit_local_variable_types: true # avoid
avoid_types_on_closure_parameters: true # avoid
avoid_return_types_on_setters: true # avoid
prefer_generic_function_type_aliases: true
avoid_private_typedef_functions: true # prefer
#- use_function_type_syntax_for_parameters # consider
hash_and_equals: true
avoid_equals_and_hash_code_on_mutable_classes: true # avoid
avoid_null_checks_in_equality_operators: true
import 'package:get_instance/get_instance.dart';
void main() {
Get.put(Foo());
final foo = Get.find<Foo>();
final foo2 = Get.find<Foo>();
print(foo == foo2); // true
}
class Foo {}
export 'package:get_core/get_core.dart';
export 'src/bindings_interface.dart';
export 'src/extension_instance.dart';
export 'src/get_instance.dart';
export 'src/lifecycle.dart';
import 'get_instance.dart';
/// [Bindings] should be extended or implemented.
/// When using [GetMaterialApp], all [GetPage]s and navigation
/// methods (like Get.to()) have a [binding] property that takes an
/// instance of Bindings to manage the
/// dependencies() (via [Get.put()]) for the Route you are opening.
// ignore: one_member_abstracts
abstract class Bindings {
void dependencies();
}
/// Simplifies Bindings generation from a single callback.
/// To avoid the creation of a custom Binding instance per route.
///
/// Example:
/// ```
/// GetPage(
/// name: '/',
/// page: () => Home(),
/// // This might cause you an error.
/// // binding: BindingsBuilder(() => Get.put(HomeController())),
/// binding: BindingsBuilder(() { Get.put(HomeController(); })),
/// // Using .lazyPut() works fine.
/// // binding: BindingsBuilder(() => Get.lazyPut(() => HomeController())),
/// ),
/// ```
class BindingsBuilder<T> extends Bindings {
/// Register your dependencies in the [builder] callback.
final BindingBuilderCallback builder;
/// Shortcut to register 1 Controller with Get.put(),
/// Prevents the issue of the fat arrow function with the constructor.
/// BindingsBuilder(() => Get.put(HomeController())),
///
/// Sample:
/// ```
/// GetPage(
/// name: '/',
/// page: () => Home(),
/// binding: BindingsBuilder.put(() => HomeController()),
/// ),
/// ```
factory BindingsBuilder.put(InstanceBuilderCallback<T> builder,
{String tag, bool permanent = false}) {
return BindingsBuilder(() => GetInstance()
.put<T>(null, tag: tag, permanent: permanent, builder: builder));
}
/// WARNING: don't use `()=> Get.put(Controller())`,
/// if only passing 1 callback use `BindingsBuilder.put(Controller())`
/// or `BindingsBuilder(()=> Get.lazyPut(Controller()))`
BindingsBuilder(this.builder);
@override
void dependencies() {
builder();
}
}
// abstract class INavigation {}
// typedef Snack = Function();
// typedef Modal = Function();
// typedef Route = Function();
typedef BindingBuilderCallback = void Function();
import 'package:get_core/get_core.dart';
import 'get_instance.dart';
extension Inst on GetInterface {
/// Creates a new Instance<S> lazily from the [<S>builder()] callback.
///
/// The first time you call [Get.find()], the [builder()] callback will create
/// the Instance and persisted as a Singleton (like you would use
/// [Get.put()]).
///
/// Using [Get.smartManagement] as [SmartManagement.keepFactory] has
/// the same outcome
/// as using [fenix:true] :
/// The internal register of [builder()] will remain in memory to recreate
/// the Instance if the Instance has been removed with [Get.delete()].
/// Therefore, future calls to [Get.find()] will return the same Instance.
///
/// If you need to make use of GetxController's life-cycle
/// ([onInit(), onStart(), onClose()])
/// [fenix] is a great choice to mix with [GetBuilder()] and [GetX()] widgets,
/// and/or [GetMaterialApp] Navigation.
///
/// You could use [Get.lazyPut(fenix:true)] in your app's [main()] instead of
/// [Bindings()] for each [GetPage].
/// And the memory management will be similar.
///
/// Subsequent calls to [Get.lazyPut()] with the same parameters
/// (<[S]> and optionally [tag] will **not** override the original).
void lazyPut<S>(InstanceBuilderCallback<S> builder,
{String tag, bool fenix = false}) {
GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
}
/// async version of [Get.put()].
/// Awaits for the resolution of the Future from [builder()] parameter and
/// stores the Instance returned.
Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
{String tag, bool permanent = false}) async =>
GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
/// Creates a new Class Instance [S] from the builder callback[S].
/// Every time [find]<[S]>() is used, it calls the builder method to generate
/// a new Instance [S].
/// It also registers each [instance.onClose()] with the current
/// Route [GetConfig.currentRoute] to keep the lifecycle active.
/// Is important to know that the instances created are only stored per Route.
/// So, if you call `Get.delete<T>()` the "instance factory" used in this
/// method ([Get.create<T>()]) will be removed, but NOT the instances
/// already created by it.
/// Uses `tag` as the other methods.
///
/// Example:
///
/// ```create(() => Repl());
/// Repl a = find();
/// Repl b = find();
/// print(a==b); (false)```
void create<S>(InstanceBuilderCallback<S> builder,
{String tag, bool permanent = true}) =>
GetInstance().create<S>(builder, tag: tag, permanent: permanent);
/// Finds a Instance of the required Class <[S]>(or [tag])
/// In the case of using [Get.create()], it will generate an Instance
/// each time you call [Get.find()].
S find<S>({String tag}) => GetInstance().find<S>(tag: tag);
/// Injects an [Instance<S>] in memory.
///
/// No need to define the generic type <[S]> as it's inferred
/// from the [dependency] parameter.
///
/// - [dependency] The Instance to be injected.
/// - [tag] optionally, use a [tag] as an "id" to create multiple records
/// of the same Type<[S]> the [tag] does **not** conflict with the same tags
/// used by other [dependencies] Types.
/// - [permanent] keeps the Instance in memory and persist it,
/// not following [Get.smartManagement]
/// rules. Although, can be removed by [GetInstance.reset()]
/// and [Get.delete()]
/// - [builder] If defined, the [dependency] must be returned from here
S put<S>(S dependency,
{String tag,
bool permanent = false,
InstanceBuilderCallback<S> builder}) =>
GetInstance()
.put<S>(dependency, tag: tag, permanent: permanent, builder: builder);
/// Clears all registered instances (and/or tags).
/// Even the persistent ones.
///
/// - [clearFactory] clears the callbacks registered by [Get.lazyPut()]
/// - [clearRouteBindings] clears Instances associated with Routes when using
/// [GetMaterialApp].
bool reset({bool clearFactory = true, bool clearRouteBindings = true}) =>
GetInstance().reset(
clearFactory: clearFactory, clearRouteBindings: clearRouteBindings);
/// Deletes the Instance<[S]>, cleaning the memory and closes any open
/// controllers ([DisposableInterface]).
///
/// - [tag] Optional "tag" used to register the Instance
/// - [force] Will delete an Instance even if marked as [permanent].
Future<bool> delete<S>({String tag, bool force = false}) async =>
GetInstance().delete<S>(tag: tag, force: force);
/// Checks if a Class Instance<[S]> (or [tag]) is registered in memory.
/// - [tag] optional, if you use a [tag] to register the Instance.
bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag);
/// Checks if an Instance<[S]> (or [tag]) returned from a factory builder
/// [Get.lazyPut()], is registered in memory.
/// - [tag] optional, if you use a [tag] to register the Instance.
bool isPrepared<S>({String tag}) => GetInstance().isPrepared<S>(tag: tag);
}
import 'dart:async';
import 'dart:collection';
import 'package:get_core/get_core.dart';
import 'lifecycle.dart';
class GetInstance {
factory GetInstance() => _getInstance ??= GetInstance._();
const GetInstance._();
static GetInstance _getInstance;
/// Holds references to every registered Instance when using
/// [Get.put()]
static final Map<String, _InstanceBuilderFactory> _singl = {};
/// Holds a reference to every registered callback when using
/// [Get.lazyPut()]
static final Map<String, _Lazy> _factory = {};
/// Holds a reference to [Get.reference] when the Instance was
/// created to manage the memory.
static final Map<String, String> _routesKey = {};
/// Stores the onClose() references of instances created with [Get.create()]
/// using the [Get.reference].
/// Experimental feature to keep the lifecycle and memory management with
/// non-singleton instances.
static final Map<String, HashSet<Function>> _routesByCreate = {};
/// Creates a new Instance<S> lazily from the [<S>builder()] callback.
///
/// The first time you call [Get.find()], the [builder()] callback will create
/// the Instance and persisted as a Singleton (like you would
/// use [Get.put()]).
///
/// Using [Get.smartManagement] as [SmartManagement.keepFactory] has
/// the same outcome as using [fenix:true] :
/// The internal register of [builder()] will remain in memory to recreate
/// the Instance if the Instance has been removed with [Get.delete()].
/// Therefore, future calls to [Get.find()] will return the same Instance.
///
/// If you need to make use of GetxController's life-cycle
/// ([onInit(), onStart(), onClose()]) [fenix] is a great choice to mix with
/// [GetBuilder()] and [GetX()] widgets, and/or [GetMaterialApp] Navigation.
///
/// You could use [Get.lazyPut(fenix:true)] in your app's [main()] instead
/// of [Bindings()] for each [GetPage].
/// And the memory management will be similar.
///
/// Subsequent calls to [Get.lazyPut()] with the same parameters
/// (<[S]> and optionally [tag] will **not** override the original).
void lazyPut<S>(
InstanceBuilderCallback<S> builder, {
String tag,
bool fenix = false,
}) {
final key = _getKey(S, tag);
_factory.putIfAbsent(key, () => _Lazy(builder, fenix));
}
/// async version of [Get.put()].
/// Awaits for the resolution of the Future from [builder()] parameter and
/// stores the Instance returned.
Future<S> putAsync<S>(
AsyncInstanceBuilderCallback<S> builder, {
String tag,
bool permanent = false,
}) async {
return put<S>(await builder(), tag: tag, permanent: permanent);
}
/// Injects an instance <[S]> in memory to be globally accessible.
///
/// No need to define the generic type <[S]> as it's inferred from
/// the [dependency]
///
/// - [dependency] The Instance to be injected.
/// - [tag] optionally, use a [tag] as an "id" to create multiple records of
/// the same Type<[S]>
/// - [permanent] keeps the Instance in memory, not following
/// [Get.smartManagement] rules.
S put<S>(
S dependency, {
String tag,
bool permanent = false,
InstanceBuilderCallback<S> builder,
}) {
_insert(
isSingleton: true,
name: tag,
permanent: permanent,
builder: builder ?? (() => dependency));
return find<S>(tag: tag);
}
/// Creates a new Class Instance [S] from the builder callback[S].
/// Every time [find]<[S]>() is used, it calls the builder method to generate
/// a new Instance [S].
/// It also registers each [instance.onClose()] with the current
/// Route [Get.reference] to keep the lifecycle active.
/// Is important to know that the instances created are only stored per Route.
/// So, if you call `Get.delete<T>()` the "instance factory" used in this
/// method ([Get.create<T>()]) will be removed, but NOT the instances
/// already created by it.
///
/// Example:
///
/// ```create(() => Repl());
/// Repl a = find();
/// Repl b = find();
/// print(a==b); (false)```
void create<S>(
InstanceBuilderCallback<S> builder, {
String tag,
bool permanent = true,
}) {
_insert(
isSingleton: false, name: tag, builder: builder, permanent: permanent);
}
/// Injects the Instance [S] builder into the [_singleton] HashMap.
void _insert<S>({
bool isSingleton,
String name,
bool permanent = false,
InstanceBuilderCallback<S> builder,
}) {
assert(builder != null);
final key = _getKey(S, name);
_singl.putIfAbsent(
key,
() =>
_InstanceBuilderFactory<S>(isSingleton, builder, permanent, false));
}
/// Clears from memory registered Instances associated with [routeName] when
/// using [Get.smartManagement] as [SmartManagement.full] or
/// [SmartManagement.keepFactory]
/// Meant for internal usage of [GetPageRoute] and [GetDialogRoute]
void removeDependencyByRoute(String routeName) {
final keysToRemove = <String>[];
_routesKey.forEach((key, value) {
if (value == routeName) {
keysToRemove.add(key);
}
});
/// Removes [Get.create()] instances registered in [routeName].
if (_routesByCreate.containsKey(routeName)) {
for (final onClose in _routesByCreate[routeName]) {
// assure the [DisposableInterface] instance holding a reference
// to [onClose()] wasn't disposed.
if (onClose != null) {
onClose();
}
}
_routesByCreate[routeName].clear();
_routesByCreate.remove(routeName);
}
for (final element in keysToRemove) {
delete(key: element);
}
for (final element in keysToRemove) {
_routesKey?.remove(element);
}
keysToRemove.clear();
}
/// Initializes the dependencies for a Class Instance [S] (or tag),
/// If its a Controller, it starts the lifecycle process.
/// Optionally associating the current Route to the lifetime of the instance,
/// if [Get.smartManagement] is marked as [SmartManagement.full] or
/// [Get.keepFactory]
/// Only flags `isInit` if it's using `Get.create()`
/// (not for Singletons access).
/// Returns the instance if not initialized, required for Get.create() to
/// work properly.
S _initDependencies<S>({String name}) {
final key = _getKey(S, name);
final isInit = _singl[key].isInit;
S i;
if (!isInit) {
i = _startController<S>(tag: name);
if (_singl[key].isSingleton) {
_singl[key].isInit = true;
if (Get.smartManagement != SmartManagement.onlyBuilder) {
_registerRouteInstance<S>(tag: name);
}
}
}
return i;
}
/// Links a Class instance [S] (or [tag]) to the current route.
/// Requires usage of [GetMaterialApp].
void _registerRouteInstance<S>({String tag}) {
_routesKey.putIfAbsent(_getKey(S, tag), () => Get.reference);
}
/// Finds and returns a Instance<[S]> (or [tag]) without further processing.
S findByType<S>(Type type, {String tag}) {
final key = _getKey(type, tag);
return _singl[key].getDependency() as S;
}
/// Initializes the controller
S _startController<S>({String tag}) {
final key = _getKey(S, tag);
final i = _singl[key].getDependency() as S;
if (i is GetLifeCycle) {
if (i.onStart != null) {
i.onStart();
Get.log('"$key" has been initialized');
}
if (!_singl[key].isSingleton && i.onClose != null) {
_routesByCreate[Get.reference] ??= HashSet<Function>();
_routesByCreate[Get.reference].add(i.onClose);
}
}
return i;
}
S putOrFind<S>(InstanceBuilderCallback<S> dep, {String tag}) {
final key = _getKey(S, tag);
if (_singl.containsKey(key)) {
return _singl[key].getDependency() as S;
} else {
if (_factory.containsKey(key)) {
final _value = put<S>((_factory[key].builder() as S), tag: tag);
if (Get.smartManagement != SmartManagement.keepFactory) {
if (!_factory[key].fenix) {
_factory.remove(key);
}
}
return _value;
}
return GetInstance().put(dep(), tag: tag);
}
}
/// Finds the registered type <[S]> (or [tag])
/// In case of using Get.[create] to register a type <[S]> or [tag],
/// it will create an instance each time you call [find].
/// If the registered type <[S]> (or [tag]) is a Controller,
/// it will initialize it's lifecycle.
S find<S>({String tag}) {
final key = _getKey(S, tag);
if (isRegistered<S>(tag: tag)) {
if (_singl[key] == null) {
if (tag == null) {
throw 'Class "$S" is not registered';
} else {
throw 'Class "$S" with tag "$tag" is not registered';
}
}
/// although dirty solution, the lifecycle starts inside
/// `initDependencies`, so we have to return the instance from there
/// to make it compatible with `Get.create()`.
final i = _initDependencies<S>(name: tag);
return i ?? _singl[key].getDependency() as S;
} else {
if (!_factory.containsKey(key)) {
// ignore: lines_longer_than_80_chars
throw '"$S" not found. You need to call "Get.put($S())" or "Get.lazyPut(()=>$S())"';
}
Get.log('Lazy instance "$S" created');
final _value = put<S>(_factory[key].builder() as S, tag: tag);
_initDependencies<S>(name: tag);
if (Get.smartManagement != SmartManagement.keepFactory &&
!_factory[key].fenix) {
_factory.remove(key);
}
return _value;
}
}
/// Generates the key based on [type] (and optionally a [name])
/// to register an Instance Builder in the hashmap.
String _getKey(Type type, String name) {
return name == null ? type.toString() : type.toString() + name;
}
/// Clears all registered instances (and/or tags).
/// Even the persistent ones.
///
/// [clearFactory] clears the callbacks registered by [lazyPut]
/// [clearRouteBindings] clears Instances associated with routes.
///
bool reset({bool clearFactory = true, bool clearRouteBindings = true}) {
if (clearFactory) _factory.clear();
if (clearRouteBindings) _routesKey.clear();
_singl.clear();
return true;
}
/// Delete registered Class Instance [S] (or [tag]) and, closes any open
/// controllers [DisposableInterface], cleans up the memory
///
/// /// Deletes the Instance<[S]>, cleaning the memory.
// ///
// /// - [tag] Optional "tag" used to register the Instance
// /// - [key] For internal usage, is the processed key used to register
// /// the Instance. **don't use** it unless you know what you are doing.
/// Deletes the Instance<[S]>, cleaning the memory and closes any open
/// controllers ([DisposableInterface]).
///
/// - [tag] Optional "tag" used to register the Instance
/// - [key] For internal usage, is the processed key used to register
/// the Instance. **don't use** it unless you know what you are doing.
/// - [force] Will delete an Instance even if marked as [permanent].
bool delete<S>({String tag, String key, bool force = false}) {
// return _queue.secure<bool>(() {
return _delete<S>(tag: tag, key: key, force: force);
// });
}
bool _delete<S>({String tag, String key, bool force = false}) {
final newKey = key ?? _getKey(S, tag);
if (!_singl.containsKey(newKey)) {
Get.log('Instance "$newKey" already removed.', isError: true);
return false;
}
final builder = _singl[newKey];
if (builder.permanent && !force) {
Get.log(
// ignore: lines_longer_than_80_chars
'"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.',
isError: true,
);
return false;
}
final i = builder.dependency;
if (i is GetxServiceMixin && !force) {
return false;
}
if (i is GetLifeCycle) {
i.onClose();
Get.log('"$newKey" onClose() called');
}
_singl.removeWhere((oldKey, value) => (oldKey == newKey));
if (_singl.containsKey(newKey)) {
Get.log('Error removing object "$newKey"', isError: true);
} else {
Get.log('"$newKey" deleted from memory');
}
// _routesKey?.remove(key);
return true;
}
/// Check if a Class Instance<[S]> (or [tag]) is registered in memory.
/// - [tag] is optional, if you used a [tag] to register the Instance.
bool isRegistered<S>({String tag}) => _singl.containsKey(_getKey(S, tag));
/// Checks if a lazy factory callback ([Get.lazyPut()] that returns an
/// Instance<[S]> is registered in memory.
/// - [tag] is optional, if you used a [tag] to register the lazy Instance.
bool isPrepared<S>({String tag}) => _factory.containsKey(_getKey(S, tag));
}
typedef InstanceBuilderCallback<S> = S Function();
typedef AsyncInstanceBuilderCallback<S> = Future<S> Function();
/// Internal class to register instances with Get.[put]<[S]>().
class _InstanceBuilderFactory<S> {
/// Marks the Builder as a single instance.
/// For reusing [dependency] instead of [builderFunc]
bool isSingleton;
/// Stores the actual object instance when [isSingleton]=true.
S dependency;
/// Generates (and regenerates) the instance when [isSingleton]=false.
/// Usually used by factory methods
InstanceBuilderCallback<S> builderFunc;
/// Flag to persist the instance in memory,
/// without considering [Get.smartManagement]
bool permanent = false;
bool isInit = false;
_InstanceBuilderFactory(
this.isSingleton,
this.builderFunc,
this.permanent,
this.isInit,
);
/// Gets the actual instance by it's [builderFunc] or the persisted instance.
S getDependency() {
return isSingleton ? dependency ??= builderFunc() : builderFunc();
}
}
/// Internal class to register a future instance with [lazyPut],
/// keeps a reference to the callback to be called.
class _Lazy {
bool fenix;
InstanceBuilderCallback builder;
_Lazy(this.builder, this.fenix);
}
/// Special callable class to keep the contract of a regular method, and avoid
/// overrides if you extend the class that uses it, as Dart has no final
/// methods.
/// Used in [DisposableInterface] to avoid the danger of overriding onStart.
///
class _InternalFinalCallback<T> {
T Function() callback;
_InternalFinalCallback();
T call() => callback.call();
}
abstract class GetLifeCycle {
/// Called at the exact moment the widget is allocated in memory.
/// It uses an internal "callable" type, to avoid any @overrides in subclases.
/// This method should be internal and is required to define the
/// lifetime cycle of the subclass.
final onStart = _InternalFinalCallback<void>();
/// Called immediately after the widget is allocated in memory.
/// You might use this to initialize something for the controller.
void onInit() {}
/// Called 1 frame after onInit(). It is the perfect place to enter
/// navigation events, like snackbar, dialogs, or a new route, or
/// async request.
void onReady() {}
/// Called before [onDelete] method. [onClose] might be used to
/// dispose resources used by the controller. Like closing events,
/// or streams before the controller is destroyed.
/// Or dispose objects that can potentially create some memory leaks,
/// like TextEditingControllers, AnimationControllers.
/// Might be useful as well to persist some data on disk.
void onClose() {}
}
/// Allow track difference between GetxServices and GetxControllers
mixin GetxServiceMixin {}
name: get_instance
description: A smart dependency injector to GetX™ framework.
version: 3.13.0
homepage: https://github.com/jonataslaw/getx
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
get_core: ">=3.13.0 <4.0.0"
dev_dependencies:
test: ">=1.0.0 <2.0.0"
test_coverage: ">=0.4.3 <1.0.0"
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
import 'package:get_instance/get_instance.dart';
import 'package:test/test.dart';
import 'package:get_core/get_core.dart';
import 'util/matcher.dart' as m;
class Mock {
static Future<String> test() async {
await Future.delayed(Duration.zero);
return 'test';
}
}
class Controller {}
class DisposableController extends GetLifeCycle {
DisposableController() {
onStart.callback = _onStart;
}
// Internal callback that starts the cycle of this controller.
void _onStart() {
onInit();
}
bool initialized = false;
void onInit() async {
initialized = true;
}
}
// ignore: one_member_abstracts
abstract class Service {
String post();
}
class Api implements Service {
@override
String post() {
return 'test';
}
}
void main() {
test('Get.putAsync test', () async {
await Get.putAsync<String>(Mock.test);
expect('test', Get.find<String>());
Get.reset();
});
test('Get.put test', () async {
final instance = Get.put<Controller>(Controller());
expect(instance, Get.find<Controller>());
Get.reset();
});
test('Get.put tag test', () async {
final instance = Get.put<Controller>(Controller(), tag: 'one');
final instance2 = Get.put<Controller>(Controller(), tag: 'two');
expect(instance == instance2, false);
expect(Get.find<Controller>(tag: 'one') == Get.find<Controller>(tag: 'two'),
false);
expect(Get.find<Controller>(tag: 'one') == Get.find<Controller>(tag: 'one'),
true);
expect(Get.find<Controller>(tag: 'two') == Get.find<Controller>(tag: 'two'),
true);
Get.reset();
});
test('Get.lazyPut tag test', () async {
Get.lazyPut<Controller>(() => Controller(), tag: 'one');
Get.lazyPut<Controller>(() => Controller(), tag: 'two');
expect(Get.find<Controller>(tag: 'one') == Get.find<Controller>(tag: 'two'),
false);
expect(Get.find<Controller>(tag: 'one') == Get.find<Controller>(tag: 'one'),
true);
expect(Get.find<Controller>(tag: 'two') == Get.find<Controller>(tag: 'two'),
true);
Get.reset();
});
test('Get.lazyPut test', () async {
final controller = Controller();
Get.lazyPut<Controller>(() => controller);
final ct1 = Get.find<Controller>();
expect(ct1, controller);
Get.reset();
});
test('Get.lazyPut with abstract class test', () async {
final api = Api();
Get.lazyPut<Service>(() => api);
final ct1 = Get.find<Service>();
expect(ct1, api);
Get.reset();
});
test('Get.create with abstract class test', () async {
Get.create<Service>(() => Api());
final ct1 = Get.find<Service>();
final ct2 = Get.find<Service>();
expect(ct1 is Service, true);
expect(ct2 is Service, true);
expect(ct1 == ct2, false);
Get.reset();
});
group('test put, delete and check onInit execution', () {
tearDownAll(Get.reset);
test('Get.put test with init check', () async {
final instance = Get.put<DisposableController>(DisposableController());
expect(instance, Get.find<DisposableController>());
expect(instance.initialized, true);
});
test('Get.delete test with disposable controller', () async {
expect(await Get.delete<DisposableController>(), true);
expect(() => Get.find<DisposableController>(),
throwsA(m.TypeMatcher<String>()));
});
test('Get.put test after delete with disposable controller and init check',
() async {
final instance = Get.put<DisposableController>(DisposableController());
expect(instance, Get.find<DisposableController>());
expect(instance.initialized, true);
});
});
}
import 'package:test/test.dart';
// Copyright 2014, the Dart project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class _FunctionMatcher<T> extends CustomMatcher {
final dynamic Function(T value) _feature;
_FunctionMatcher(String name, this._feature, matcher)
: super('`$name`:', '`$name`', matcher);
@override
Object featureValueOf(covariant T actual) => _feature(actual);
}
class HavingMatcher<T> implements TypeMatcher<T> {
final TypeMatcher<T> _parent;
final List<_FunctionMatcher<T>> _functionMatchers;
HavingMatcher(TypeMatcher<T> parent, String description,
Object Function(T) feature, dynamic matcher,
[Iterable<_FunctionMatcher<T>> existing])
: _parent = parent,
_functionMatchers = [
...?existing,
_FunctionMatcher<T>(description, feature, matcher)
];
@override
TypeMatcher<T> having(
Object Function(T) feature, String description, dynamic matcher) =>
HavingMatcher(_parent, description, feature, matcher, _functionMatchers);
@override
bool matches(dynamic item, Map matchState) {
for (var matcher in <Matcher>[_parent].followedBy(_functionMatchers)) {
if (!matcher.matches(item, matchState)) {
addStateInfo(matchState, {'matcher': matcher});
return false;
}
}
return true;
}
@override
Description describeMismatch(
dynamic item,
Description mismatchDescription,
Map matchState,
bool verbose,
) {
var matcher = matchState['matcher'] as Matcher;
matcher.describeMismatch(
item, mismatchDescription, matchState['state'] as Map, verbose);
return mismatchDescription;
}
@override
Description describe(Description description) => description
.add('')
.addDescriptionOf(_parent)
.add(' with ')
.addAll('', ' and ', '', _functionMatchers);
}
class TypeMatcher<T> extends Matcher {
const TypeMatcher();
TypeMatcher<T> having(
Object Function(T) feature, String description, dynamic matcher) =>
HavingMatcher(this, description, feature, matcher);
@override
Description describe(Description description) {
var name = _stripDynamic(T);
return description.add("<Instance of '$name'>");
}
@override
bool matches(Object item, Map matchState) => item is T;
@override
Description describeMismatch(
dynamic item,
Description mismatchDescription,
Map matchState,
bool verbose,
) {
var name = _stripDynamic(T);
return mismatchDescription.add("is not an instance of '$name'");
}
}
String _stripDynamic(Type type) =>
type.toString().replaceAll(_dart2DynamicArgs, '');
final _dart2DynamicArgs = RegExp('<dynamic(, dynamic)*>');
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: a27c242b0eea731317cfec5bbdd9d35452ab3ecb
channel: dev
project_type: package
## [3.13.0]
* Bump to Get 3.13.0
## [3.12.0]
* Bump to Get 3.12.0
* Fix defaultCustomTransition
## [3.10.2]
- initial release
MIT License
Copyright (c) 2019 Jonny Borges
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# get_navigation
A new Flutter package project.
## Getting Started
This project is a starting point for a Dart
[package](https://flutter.dev/developing-packages/),
a library module containing code that can be shared easily across
multiple Flutter or Dart projects.
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# Include option is buggy:
# https://github.com/flutter/flutter/issues/62591
# In case the include issue gets fixed, lines below INCLUDE_FIX
# can be removed
# include: package:effective_dart/analysis_options.1.2.0.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
await_only_futures: true
# This one is desirable, but that's a lot of work for now
public_member_api_docs: false
# Desirable, but would be breaking changes:
avoid_positional_boolean_parameters: false
constant_identifier_names: false
include_file_not_found: false
# INCLUDE_FIX (copy of effective dart 1.2.0)
# STYLE
camel_case_types: true
camel_case_extensions: true
library_names: true
file_names: true
library_prefixes: true
non_constant_identifier_names: true
directives_ordering: true
lines_longer_than_80_chars: true # avoid
curly_braces_in_flow_control_structures: true
# DOCUMENTATION
slash_for_doc_comments: true
package_api_docs: true # prefer
#- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
# USAGE
implementation_imports: true
avoid_relative_lib_imports: true # prefer
prefer_relative_imports: true # prefer
prefer_adjacent_string_concatenation: true
prefer_interpolation_to_compose_strings: true # prefer
unnecessary_brace_in_string_interps: true # avoid
prefer_collection_literals: true
avoid_function_literals_in_foreach_calls: true # avoid
prefer_iterable_whereType: true
prefer_function_declarations_over_variables: true
unnecessary_lambdas: true
prefer_equal_for_default_values: true
avoid_init_to_null: true
unnecessary_getters_setters: true
#- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
#- prefer_expression_function_bodies # consider
unnecessary_this: true
prefer_initializing_formals: true
type_init_formals: true
empty_constructor_bodies: true
unnecessary_new: true
unnecessary_const: true
avoid_catches_without_on_clauses: true # avoid
avoid_catching_errors: true
use_rethrow_when_possible: true
# DESIGN
use_to_and_as_if_applicable: true # prefer
one_member_abstracts: true # avoid
avoid_classes_with_only_static_members: true # avoid
prefer_mixin: true
prefer_final_fields: true # prefer
use_setters_to_change_properties: true
avoid_setters_without_getters: true
avoid_returning_null: true # avoid
avoid_returning_this: true # avoid
type_annotate_public_apis: true # prefer
#- prefer_typing_uninitialized_variables # consider
omit_local_variable_types: true # avoid
avoid_types_on_closure_parameters: true # avoid
avoid_return_types_on_setters: true # avoid
prefer_generic_function_type_aliases: true
avoid_private_typedef_functions: true # prefer
#- use_function_type_syntax_for_parameters # consider
hash_and_equals: true
avoid_equals_and_hash_code_on_mutable_classes: true # avoid
avoid_null_checks_in_equality_operators: true
library get_navigation;
export 'package:get_core/get_core.dart';
export 'src/bottomsheet/bottomsheet.dart';
export 'src/extension_navigation.dart';
export 'src/root/root_widget.dart';
export 'src/routes/custom_transition.dart';
export 'src/routes/default_route.dart';
export 'src/routes/default_route.dart';
export 'src/routes/get_route.dart';
export 'src/routes/observers/route_observer.dart';
export 'src/routes/transitions_type.dart';
export 'src/snackbar/snack.dart';
export 'src/snackbar/snack_route.dart';
import 'package:flutter/material.dart';
class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
GetModalBottomSheetRoute({
this.builder,
this.theme,
this.barrierLabel,
this.backgroundColor,
this.isPersistent,
this.elevation,
this.shape,
this.removeTop = true,
this.clipBehavior,
this.modalBarrierColor,
this.isDismissible = true,
this.enableDrag = true,
@required this.isScrollControlled,
RouteSettings settings,
this.enterBottomSheetDuration = const Duration(milliseconds: 250),
this.exitBottomSheetDuration = const Duration(milliseconds: 200),
}) : assert(isScrollControlled != null),
name = "BOTTOMSHEET: ${builder.hashCode}",
assert(isDismissible != null),
assert(enableDrag != null),
super(settings: settings);
final bool isPersistent;
final WidgetBuilder builder;
final ThemeData theme;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;
final Clip clipBehavior;
final Color modalBarrierColor;
final bool isDismissible;
final bool enableDrag;
final String name;
final Duration enterBottomSheetDuration;
final Duration exitBottomSheetDuration;
// remove safearea from top
final bool removeTop;
@override
Duration get transitionDuration => Duration(milliseconds: 700);
@override
bool get barrierDismissible => isDismissible;
@override
final String barrierLabel;
@override
Color get barrierColor => modalBarrierColor ?? Colors.black54;
AnimationController _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
_animationController =
BottomSheet.createAnimationController(navigator.overlay);
_animationController.duration = enterBottomSheetDuration;
_animationController.reverseDuration = exitBottomSheetDuration;
return _animationController;
}
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
final sheetTheme =
theme?.bottomSheetTheme ?? Theme.of(context).bottomSheetTheme;
// By definition, the bottom sheet is aligned to the bottom of the page
// and isn't exposed to the top padding of the MediaQuery.
Widget bottomSheet = MediaQuery.removePadding(
context: context,
removeTop: removeTop,
child: Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: _GetModalBottomSheet<T>(
route: this,
backgroundColor: backgroundColor ??
sheetTheme?.modalBackgroundColor ??
sheetTheme?.backgroundColor,
elevation:
elevation ?? sheetTheme?.modalElevation ?? sheetTheme?.elevation,
shape: shape,
clipBehavior: clipBehavior,
isScrollControlled: isScrollControlled,
enableDrag: enableDrag,
),
),
);
if (theme != null) bottomSheet = Theme(data: theme, child: bottomSheet);
return bottomSheet;
}
}
class _GetModalBottomSheet<T> extends StatefulWidget {
const _GetModalBottomSheet({
Key key,
this.route,
this.backgroundColor,
this.elevation,
this.shape,
this.clipBehavior,
this.isScrollControlled = false,
this.enableDrag = true,
this.isPersistent = false,
}) : assert(isScrollControlled != null),
assert(enableDrag != null),
super(key: key);
final bool isPersistent;
final GetModalBottomSheetRoute<T> route;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;
final Clip clipBehavior;
final bool enableDrag;
@override
_GetModalBottomSheetState<T> createState() => _GetModalBottomSheetState<T>();
}
class _GetModalBottomSheetState<T> extends State<_GetModalBottomSheet<T>> {
String _getRouteLabel(MaterialLocalizations localizations) {
if ((Theme.of(context).platform == TargetPlatform.android) ||
(Theme.of(context).platform == TargetPlatform.fuchsia)) {
return localizations.dialogLabel;
} else {
return '';
}
}
@override
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final mediaQuery = MediaQuery.of(context);
final localizations = MaterialLocalizations.of(context);
final routeLabel = _getRouteLabel(localizations);
return AnimatedBuilder(
animation: widget.route.animation,
builder: (context, child) {
// Disable the initial animation when accessible navigation is on so
// that the semantics are added to the tree at the correct time.
final animationValue = mediaQuery.accessibleNavigation
? 1.0
: widget.route.animation.value;
return Semantics(
scopesRoute: true,
namesRoute: true,
label: routeLabel,
explicitChildNodes: true,
child: ClipRect(
child: CustomSingleChildLayout(
delegate: _GetModalBottomSheetLayout(
animationValue, widget.isScrollControlled),
child: widget.isPersistent == false
? BottomSheet(
animationController: widget.route._animationController,
onClosing: () {
if (widget.route.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
clipBehavior: widget.clipBehavior,
enableDrag: widget.enableDrag,
)
: Scaffold(
bottomSheet: BottomSheet(
animationController:
widget.route._animationController,
onClosing: () {
// if (widget.route.isCurrent) {
// Navigator.pop(context);
// }
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
clipBehavior: widget.clipBehavior,
enableDrag: widget.enableDrag,
),
)),
),
);
},
);
}
}
class _GetPerModalBottomSheet<T> extends StatefulWidget {
const _GetPerModalBottomSheet({
Key key,
this.route,
this.isPersistent,
this.backgroundColor,
this.elevation,
this.shape,
this.clipBehavior,
this.isScrollControlled = false,
this.enableDrag = true,
}) : assert(isScrollControlled != null),
assert(enableDrag != null),
super(key: key);
final bool isPersistent;
final GetModalBottomSheetRoute<T> route;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;
final Clip clipBehavior;
final bool enableDrag;
@override
// ignore: lines_longer_than_80_chars
_GetPerModalBottomSheetState<T> createState() =>
_GetPerModalBottomSheetState<T>();
}
// ignore: lines_longer_than_80_chars
class _GetPerModalBottomSheetState<T>
extends State<_GetPerModalBottomSheet<T>> {
String _getRouteLabel(MaterialLocalizations localizations) {
if ((Theme.of(context).platform == TargetPlatform.android) ||
(Theme.of(context).platform == TargetPlatform.fuchsia)) {
return localizations.dialogLabel;
} else {
return '';
}
}
@override
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final mediaQuery = MediaQuery.of(context);
final localizations = MaterialLocalizations.of(context);
final routeLabel = _getRouteLabel(localizations);
return AnimatedBuilder(
animation: widget.route.animation,
builder: (context, child) {
// Disable the initial animation when accessible navigation is on so
// that the semantics are added to the tree at the correct time.
final animationValue = mediaQuery.accessibleNavigation
? 1.0
: widget.route.animation.value;
return Semantics(
scopesRoute: true,
namesRoute: true,
label: routeLabel,
explicitChildNodes: true,
child: ClipRect(
child: CustomSingleChildLayout(
delegate: _GetModalBottomSheetLayout(
animationValue, widget.isScrollControlled),
child: widget.isPersistent == false
? BottomSheet(
animationController: widget.route._animationController,
onClosing: () {
if (widget.route.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
clipBehavior: widget.clipBehavior,
enableDrag: widget.enableDrag,
)
: Scaffold(
bottomSheet: BottomSheet(
animationController:
widget.route._animationController,
onClosing: () {
// if (widget.route.isCurrent) {
// Navigator.pop(context);
// }
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
clipBehavior: widget.clipBehavior,
enableDrag: widget.enableDrag,
),
)),
),
);
},
);
}
}
class _GetModalBottomSheetLayout extends SingleChildLayoutDelegate {
_GetModalBottomSheetLayout(this.progress, this.isScrollControlled);
final double progress;
final bool isScrollControlled;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return BoxConstraints(
minWidth: constraints.maxWidth,
maxWidth: constraints.maxWidth,
minHeight: 0.0,
maxHeight: isScrollControlled
? constraints.maxHeight
: constraints.maxHeight * 9.0 / 16.0,
);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return Offset(0.0, size.height - childSize.height * progress);
}
@override
bool shouldRelayout(_GetModalBottomSheetLayout oldDelegate) {
return progress != oldDelegate.progress;
}
}
import 'package:flutter/widgets.dart';
import 'package:get_core/get_core.dart';
import 'package:get_state_manager/get_state_manager.dart';
class GetDialogRoute<T> extends PopupRoute<T> {
GetDialogRoute({
@required RoutePageBuilder pageBuilder,
bool barrierDismissible = true,
String barrierLabel,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
RouteSettings settings,
}) : assert(barrierDismissible != null),
widget = pageBuilder,
name = "DIALOG: ${pageBuilder.hashCode}",
_barrierDismissible = barrierDismissible,
_barrierLabel = barrierLabel,
_barrierColor = barrierColor,
_transitionDuration = transitionDuration,
_transitionBuilder = transitionBuilder,
super(settings: settings);
final RoutePageBuilder widget;
@override
bool get barrierDismissible => _barrierDismissible;
final bool _barrierDismissible;
final String name;
@override
void dispose() {
if (Get.smartManagement != SmartManagement.onlyBuilder) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => GetInstance().removeDependencyByRoute(name));
}
super.dispose();
}
@override
String get barrierLabel => _barrierLabel;
final String _barrierLabel;
@override
Color get barrierColor => _barrierColor;
final Color _barrierColor;
@override
Duration get transitionDuration => _transitionDuration;
final Duration _transitionDuration;
final RouteTransitionsBuilder _transitionBuilder;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return Semantics(
child: widget(context, animation, secondaryAnimation),
scopesRoute: true,
explicitChildNodes: true,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
if (_transitionBuilder == null) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.linear,
),
child: child);
} // Some default transition
return _transitionBuilder(context, animation, secondaryAnimation, child);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get_core/get_core.dart';
import 'package:get_state_manager/get_state_manager.dart';
import 'package:get_utils/get_utils.dart';
import '../get_navigation.dart';
import 'dialog/dialog_route.dart';
import 'root/parse_route.dart';
import 'root/root_controller.dart';
import 'routes/transitions_type.dart';
//TODO: Split this class on "Snackbar" "Dialog" "bottomSheet"
//and "navigation" extensions
extension GetNavigation on GetInterface {
/// **Navigation.push()** shortcut.<br><br>
///
/// Pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> to<T>(
Widget page, {
bool opaque,
Transition transition,
Curve curve,
Duration duration,
int id,
bool fullscreenDialog = false,
dynamic arguments,
Bindings binding,
bool preventDuplicates = true,
bool popGesture,
}) {
var routeName = "/${page.runtimeType.toString()}";
if (preventDuplicates && routeName == currentRoute) {
return null;
}
return global(id)?.currentState?.push(
GetPageRoute(
opaque: opaque ?? true,
page: () => page,
routeName: routeName,
settings: RouteSettings(
// name: forceRouteName ? '${a.runtimeType}' : '',
arguments: arguments,
),
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
curve: curve ?? defaultTransitionCurve,
fullscreenDialog: fullscreenDialog,
binding: binding,
transitionDuration: duration ?? defaultTransitionDuration,
),
);
}
/// **Navigation.pushNamed()** shortcut.<br><br>
///
/// Pushes a new named [page] to the stack.
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> toNamed<T>(
String page, {
dynamic arguments,
int id,
bool preventDuplicates = true,
}) {
if (preventDuplicates && page == currentRoute) {
return null;
}
return global(id)?.currentState?.pushNamed(page, arguments: arguments);
}
/// **Navigation.pushReplacementNamed()** shortcut.<br><br>
///
/// Pop the current named [page] in the stack and push a new one in its place
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamed<T>(
String page, {
dynamic arguments,
int id,
bool preventDuplicates = true,
}) {
if (preventDuplicates && page == currentRoute) {
return null;
}
return global(id)
?.currentState
?.pushReplacementNamed(page, arguments: arguments);
}
/// **Navigation.popUntil()** shortcut.<br><br>
///
/// Calls pop several times in the stack until [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the
/// dialog is closed
void until(RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id)?.currentState?.popUntil(predicate);
}
/// **Navigation.pushAndRemoveUntil()** shortcut.<br><br>
///
/// Push the given [page], and then pop several pages in the stack until
/// [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Obs: unlike other get methods, this one you need to send a function
/// that returns the widget to the page argument, like this:
/// Get.offUntil( () => HomePage() )
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id)?.currentState?.pushAndRemoveUntil(page, predicate);
}
/// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
///
/// Push the given named [page], and then pop several pages in the stack
/// until [predicate] returns true
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamedUntil<T>(
String page,
RoutePredicate predicate, {
int id,
dynamic arguments,
}) {
return global(id)
?.currentState
?.pushNamedAndRemoveUntil(page, predicate, arguments: arguments);
}
/// **Navigation.popAndPushNamed()** shortcut.<br><br>
///
/// Pop the current named page and pushes a new [page] to the stack
/// in its place
///
/// You can send any type of value to the other route in the [arguments].
/// It is very similar to `offNamed()` but use a different approach
///
/// The `offNamed()` pop a page, and goes to the next. The
/// `offAndToNamed()` goes to the next page, and removes the previous one.
/// The route transition animation is different.
Future<T> offAndToNamed<T>(
String page, {
dynamic arguments,
int id,
dynamic result,
}) {
return global(id)
?.currentState
?.popAndPushNamed(page, arguments: arguments, result: result);
}
/// **Navigation.removeRoute()** shortcut.<br><br>
///
/// Remove a specific [route] from the stack
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void removeRoute(Route<dynamic> route, {int id}) {
return global(id)?.currentState?.removeRoute(route);
}
/// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
///
/// Push a named [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context, so you can
/// call from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
Future<T> offAllNamed<T>(
String newRouteName, {
RoutePredicate predicate,
dynamic arguments,
int id,
}) {
return global(id)?.currentState?.pushNamedAndRemoveUntil(
newRouteName,
predicate ?? (_) => false,
arguments: arguments,
);
}
/// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN
bool get isOverlaysOpen =>
(isSnackbarOpen || isDialogOpen || isBottomSheetOpen);
/// Returns true if there is no Snackbar, Dialog or BottomSheet open
bool get isOverlaysClosed =>
(!isSnackbarOpen && !isDialogOpen && !isBottomSheetOpen);
/// **Navigation.popUntil()** shortcut.<br><br>
///
/// Pop the current page, snackbar, dialog or bottomsheet in the stack
///
/// if your set [closeOverlays] to true, Get.back() will close the
/// currently open snackbar/dialog/bottomsheet AND the current page
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
void back({
dynamic result,
bool closeOverlays = false,
bool canPop = true,
int id,
}) {
if (closeOverlays && isOverlaysOpen) {
navigator?.popUntil((route) {
return (isOverlaysClosed);
});
}
if (canPop) {
if (global(id)?.currentState?.canPop() == true) {
global(id)?.currentState?.pop(result);
}
} else {
global(id)?.currentState?.pop(result);
}
}
/// **Navigation.popUntil()** (with predicate) shortcut .<br><br>
///
/// Close as many routes as defined by [times]
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void close(int times, [int id]) {
if ((times == null) || (times < 1)) {
times = 1;
}
var count = 0;
var back = global(id)?.currentState?.popUntil((route) => count++ == times);
return back;
}
/// **Navigation.pushReplacement()** shortcut .<br><br>
///
/// Pop the current page and pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], define a Tween [curve],
/// and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> off<T>(
Widget page, {
bool opaque = false,
Transition transition,
Curve curve,
bool popGesture,
int id,
dynamic arguments,
Bindings binding,
bool fullscreenDialog = false,
bool preventDuplicates = true,
Duration duration,
}) {
var routeName = "/${page.runtimeType.toString()}";
if (preventDuplicates && routeName == currentRoute) {
return null;
}
return global(id)?.currentState?.pushReplacement(GetPageRoute(
opaque: opaque ?? true,
page: () => page,
binding: binding,
settings: RouteSettings(arguments: arguments),
routeName: routeName,
fullscreenDialog: fullscreenDialog,
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
curve: curve ?? defaultTransitionCurve,
transitionDuration: duration ?? defaultTransitionDuration));
}
/// **Navigation.pushAndRemoveUntil()** shortcut .<br><br>
///
/// Push a [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], a [curve] and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> offAll<T>(
Widget page, {
RoutePredicate predicate,
bool opaque = false,
bool popGesture,
int id,
dynamic arguments,
Bindings binding,
bool fullscreenDialog = false,
Transition transition,
Curve curve,
Duration duration,
}) {
var routeName = "/${page.runtimeType.toString()}";
return global(id)?.currentState?.pushAndRemoveUntil(
GetPageRoute(
opaque: opaque ?? true,
popGesture: popGesture ?? defaultPopGesture,
page: () => page,
binding: binding,
settings: RouteSettings(arguments: arguments),
fullscreenDialog: fullscreenDialog,
routeName: routeName,
transition: transition ?? defaultTransition,
curve: curve ?? defaultTransitionCurve,
transitionDuration: duration ?? defaultTransitionDuration,
),
predicate ?? (route) => false);
}
/// Show a dialog.
/// You can pass a [transitionDuration] and/or [transitionCurve],
/// overriding the defaults when the dialog shows up and closes.
/// When the dialog closes, uses those animations in reverse.
Future<T> dialog<T>(
Widget widget, {
bool barrierDismissible = true,
Color barrierColor,
bool useSafeArea = true,
bool useRootNavigator = true,
RouteSettings routeSettings,
Duration transitionDuration,
Curve transitionCurve,
}) {
assert(widget != null);
assert(barrierDismissible != null);
assert(useSafeArea != null);
assert(useRootNavigator != null);
assert(debugCheckHasMaterialLocalizations(context));
final theme = Theme.of(context, shadowThemeOnly: true);
return generalDialog(
pageBuilder: (buildContext, animation, secondaryAnimation) {
final pageChild = widget;
Widget dialog = Builder(builder: (context) {
return theme != null
? Theme(data: theme, child: pageChild)
: pageChild;
});
if (useSafeArea) {
dialog = SafeArea(child: dialog);
}
return dialog;
},
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: barrierColor ?? Colors.black54,
transitionDuration: transitionDuration ?? defaultDialogTransitionDuration,
transitionBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: transitionCurve ?? defaultDialogTransitionCurve,
),
child: child,
);
},
useRootNavigator: useRootNavigator,
routeSettings: routeSettings,
);
}
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
bool barrierDismissible = false,
String barrierLabel,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
}) {
assert(pageBuilder != null);
assert(useRootNavigator != null);
assert(!barrierDismissible || barrierLabel != null);
return Navigator.of(overlayContext, rootNavigator: useRootNavigator)
.push<T>(GetDialogRoute<T>(
pageBuilder: pageBuilder,
barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel,
barrierColor: barrierColor,
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
settings: routeSettings,
));
}
/// Custom UI Dialog.
Future<T> defaultDialog<T>({
String title = "Alert",
TextStyle titleStyle,
Widget content,
VoidCallback onConfirm,
VoidCallback onCancel,
VoidCallback onCustom,
Color cancelTextColor,
Color confirmTextColor,
String textConfirm,
String textCancel,
String textCustom,
Widget confirm,
Widget cancel,
Widget custom,
Color backgroundColor,
bool barrierDismissible = true,
Color buttonColor,
String middleText = "Dialog made in 3 lines of code",
TextStyle middleTextStyle,
double radius = 20.0,
// ThemeData themeData,
List<Widget> actions,
}) {
var leanCancel = onCancel != null || textCancel != null;
var leanConfirm = onConfirm != null || textConfirm != null;
actions ??= [];
if (cancel != null) {
actions.add(cancel);
} else {
if (leanCancel) {
actions.add(FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onPressed: () {
onCancel?.call();
back();
},
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
child: Text(
textCancel ?? "Cancel",
style: TextStyle(color: cancelTextColor ?? theme.accentColor),
),
shape: RoundedRectangleBorder(
side: BorderSide(
color: buttonColor ?? theme.accentColor,
width: 2,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(100)),
));
}
}
if (confirm != null) {
actions.add(confirm);
} else {
if (leanConfirm) {
actions.add(FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: buttonColor ?? theme.accentColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100)),
child: Text(
textConfirm ?? "Ok",
style: TextStyle(color: confirmTextColor ?? theme.primaryColor),
),
onPressed: () {
onConfirm?.call();
}));
}
}
return dialog(
AlertDialog(
titlePadding: EdgeInsets.all(8),
contentPadding: EdgeInsets.all(8),
backgroundColor: backgroundColor ?? theme.dialogBackgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(radius))),
title: Text(title, textAlign: TextAlign.center, style: titleStyle),
content: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
content ??
Text(middleText ?? "",
textAlign: TextAlign.center, style: middleTextStyle),
SizedBox(height: 16),
ButtonTheme(
minWidth: 78.0,
height: 34.0,
child: Wrap(
alignment: WrapAlignment.center,
spacing: 8,
runSpacing: 8,
children: actions,
),
)
],
),
// actions: actions, // ?? <Widget>[cancelButton, confirmButton],
buttonPadding: EdgeInsets.zero,
),
barrierDismissible: barrierDismissible,
);
}
Future<T> bottomSheet<T>(
Widget bottomsheet, {
Color backgroundColor,
double elevation,
bool persistent = true,
ShapeBorder shape,
Clip clipBehavior,
Color barrierColor,
bool ignoreSafeArea,
bool isScrollControlled = false,
bool useRootNavigator = false,
bool isDismissible = true,
bool enableDrag = true,
RouteSettings settings,
Duration enterBottomSheetDuration,
Duration exitBottomSheetDuration,
}) {
assert(bottomsheet != null);
assert(persistent != null);
assert(isScrollControlled != null);
assert(useRootNavigator != null);
assert(isDismissible != null);
assert(enableDrag != null);
return Navigator.of(overlayContext, rootNavigator: useRootNavigator)
.push(GetModalBottomSheetRoute<T>(
builder: (_) => bottomsheet,
isPersistent: persistent,
theme: Theme.of(key.currentContext, shadowThemeOnly: true),
isScrollControlled: isScrollControlled,
barrierLabel:
MaterialLocalizations.of(key.currentContext).modalBarrierDismissLabel,
backgroundColor: backgroundColor ?? Colors.transparent,
elevation: elevation,
shape: shape,
removeTop: ignoreSafeArea ?? true,
clipBehavior: clipBehavior,
isDismissible: isDismissible,
modalBarrierColor: barrierColor,
settings: settings,
enableDrag: enableDrag,
));
}
void rawSnackbar({
String title,
String message,
Widget titleText,
Widget messageText,
Widget icon,
bool instantInit = true,
bool shouldIconPulse = true,
double maxWidth,
EdgeInsets margin = const EdgeInsets.all(0.0),
EdgeInsets padding = const EdgeInsets.all(16),
double borderRadius = 0.0,
Color borderColor,
double borderWidth = 1.0,
Color backgroundColor = const Color(0xFF303030),
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
Duration duration = const Duration(seconds: 3),
bool isDismissible = true,
SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,
bool showProgressIndicator = false,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackPosition snackPosition = SnackPosition.BOTTOM,
SnackStyle snackStyle = SnackStyle.FLOATING,
Curve forwardAnimationCurve = Curves.easeOutCirc,
Curve reverseAnimationCurve = Curves.easeOutCirc,
Duration animationDuration = const Duration(seconds: 1),
SnackbarStatusCallback snackbarStatus,
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor,
Form userInputForm,
}) async {
final getBar = GetBar(
snackbarStatus: snackbarStatus,
title: title,
message: message,
titleText: titleText,
messageText: messageText,
snackPosition: snackPosition,
borderRadius: borderRadius,
margin: margin,
duration: duration,
barBlur: barBlur,
backgroundColor: backgroundColor,
icon: icon,
shouldIconPulse: shouldIconPulse,
maxWidth: maxWidth,
padding: padding,
borderColor: borderColor,
borderWidth: borderWidth,
leftBarIndicatorColor: leftBarIndicatorColor,
boxShadows: boxShadows,
backgroundGradient: backgroundGradient,
mainButton: mainButton,
onTap: onTap,
isDismissible: isDismissible,
dismissDirection: dismissDirection,
showProgressIndicator: showProgressIndicator ?? false,
progressIndicatorController: progressIndicatorController,
progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
progressIndicatorValueColor: progressIndicatorValueColor,
snackStyle: snackStyle,
forwardAnimationCurve: forwardAnimationCurve,
reverseAnimationCurve: reverseAnimationCurve,
animationDuration: animationDuration,
overlayBlur: overlayBlur,
overlayColor: overlayColor,
userInputForm: userInputForm,
);
if (instantInit) {
getBar.show();
} else {
SchedulerBinding.instance.addPostFrameCallback((_) {
getBar.show();
});
}
}
Future<T> showSnackbar<T>(GetBar snackbar) {
return key?.currentState?.push(SnackRoute<T>(snack: snackbar));
}
void snackbar(
String title,
String message, {
Color colorText,
Duration duration,
/// with instantInit = false you can put snackbar on initState
bool instantInit = true,
SnackPosition snackPosition,
Widget titleText,
Widget messageText,
Widget icon,
bool shouldIconPulse,
double maxWidth,
EdgeInsets margin,
EdgeInsets padding,
double borderRadius,
Color borderColor,
double borderWidth,
Color backgroundColor,
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
bool isDismissible,
bool showProgressIndicator,
SnackDismissDirection dismissDirection,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackStyle snackStyle,
Curve forwardAnimationCurve,
Curve reverseAnimationCurve,
Duration animationDuration,
double barBlur,
double overlayBlur,
SnackbarStatusCallback snackbarStatus,
Color overlayColor,
Form userInputForm,
}) async {
final getBar = GetBar(
snackbarStatus: snackbarStatus,
titleText: (title == null)
? null
: titleText ??
Text(
title,
style: TextStyle(
color: colorText ?? iconColor ?? Colors.black,
fontWeight: FontWeight.w800,
fontSize: 16,
),
),
messageText: messageText ??
Text(
message,
style: TextStyle(
color: colorText ?? iconColor ?? Colors.black,
fontWeight: FontWeight.w300,
fontSize: 14,
),
),
snackPosition: snackPosition ?? SnackPosition.TOP,
borderRadius: borderRadius ?? 15,
margin: margin ?? EdgeInsets.symmetric(horizontal: 10),
duration: duration ?? Duration(seconds: 3),
barBlur: barBlur ?? 7.0,
backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2),
icon: icon,
shouldIconPulse: shouldIconPulse ?? true,
maxWidth: maxWidth,
padding: padding ?? EdgeInsets.all(16),
borderColor: borderColor,
borderWidth: borderWidth,
leftBarIndicatorColor: leftBarIndicatorColor,
boxShadows: boxShadows,
backgroundGradient: backgroundGradient,
mainButton: mainButton,
onTap: onTap,
isDismissible: isDismissible ?? true,
dismissDirection: dismissDirection ?? SnackDismissDirection.VERTICAL,
showProgressIndicator: showProgressIndicator ?? false,
progressIndicatorController: progressIndicatorController,
progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
progressIndicatorValueColor: progressIndicatorValueColor,
snackStyle: snackStyle ?? SnackStyle.FLOATING,
forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc,
reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc,
animationDuration: animationDuration ?? Duration(seconds: 1),
overlayBlur: overlayBlur ?? 0.0,
overlayColor: overlayColor ?? Colors.transparent,
userInputForm: userInputForm);
if (instantInit) {
showSnackbar(getBar);
} else {
routing.isSnackbar = true;
SchedulerBinding.instance.addPostFrameCallback((_) {
showSnackbar(getBar);
});
}
}
void addPages(List<GetPage> getPages) {
if (getPages != null) {
if (routeTree == null) {
routeTree = ParseRouteTree();
}
for (final element in getPages) {
routeTree.addRoute(element);
}
}
}
void addPage(GetPage getPage) {
if (getPage != null) {
if (routeTree == null) routeTree = ParseRouteTree();
routeTree.addRoute(getPage);
}
}
/// change default config of Get
void config(
{bool enableLog,
LogWriterCallback logWriterCallback,
bool defaultPopGesture,
bool defaultOpaqueRoute,
Duration defaultDurationTransition,
bool defaultGlobalState,
Transition defaultTransition}) {
if (enableLog != null) {
Get.isLogEnable = enableLog;
}
if (logWriterCallback != null) {
Get.log = logWriterCallback;
}
if (defaultPopGesture != null) {
getxController.defaultPopGesture = defaultPopGesture;
}
if (defaultOpaqueRoute != null) {
getxController.defaultOpaqueRoute = defaultOpaqueRoute;
}
if (defaultTransition != null) {
getxController.defaultTransition = defaultTransition;
}
if (defaultDurationTransition != null) {
getxController.defaultTransitionDuration = defaultDurationTransition;
}
}
void updateLocale(Locale l) {
Get.locale = l;
forceAppUpdate();
}
void forceAppUpdate() {
void restart(Element element) {
element.markNeedsBuild();
element.visitChildren(restart);
}
restart(Get.context as Element);
}
void appUpdate() => getxController.update();
void changeTheme(ThemeData theme) {
getxController.setTheme(theme);
}
void changeThemeMode(ThemeMode themeMode) {
getxController.setThemeMode(themeMode);
}
GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) {
getxController.key = newKey;
return key;
}
GlobalKey<NavigatorState> nestedKey(int key) {
keys.putIfAbsent(key, () => GlobalKey<NavigatorState>());
return keys[key];
}
GlobalKey<NavigatorState> global(int k) {
GlobalKey<NavigatorState> _key;
if (k == null) {
_key = key;
} else {
if (!keys.containsKey(k)) {
throw 'Route id ($k) not found';
}
_key = keys[k];
}
if (_key.currentContext == null) {
throw """You are trying to use contextless navigation without
a GetMaterialApp or Get.key.
If you are testing your app, you can use:
[Get.testMode = true], or if you are running your app on
a physical device or emulator, you must exchange your [MaterialApp]
for a [GetMaterialApp].
""";
}
return _key;
}
@Deprecated('''
Since version 2.8 it is possible to access the properties
[Get.arguments] and [Get.currentRoute] directly.
[routeSettings] is useless and should not be used.''')
RouteSettings get routeSettings => null;
/// give current arguments
dynamic get arguments => routing.args;
/// give name from current route
String get currentRoute => routing.current;
/// give name from previous route
String get previousRoute => routing.previous;
/// check if snackbar is open
bool get isSnackbarOpen => routing.isSnackbar;
/// check if dialog is open
bool get isDialogOpen => routing.isDialog;
/// check if bottomsheet is open
bool get isBottomSheetOpen => routing.isBottomSheet;
/// check a raw current route
Route<dynamic> get rawRoute => routing.route;
/// check if popGesture is enable
bool get isPopGestureEnable => defaultPopGesture;
/// check if default opaque route is enable
bool get isOpaqueRouteDefault => defaultOpaqueRoute;
/// give access to currentContext
BuildContext get context => key?.currentContext;
/// give access to current Overlay Context
BuildContext get overlayContext => key?.currentState?.overlay?.context;
/// give access to Theme.of(context)
ThemeData get theme {
ThemeData _theme;
if (context != null) {
_theme = Theme.of(context);
}
return _theme;
}
/// give access to TextTheme.of(context)
TextTheme get textTheme => theme?.textTheme;
/// give access to Mediaquery.of(context)
MediaQueryData get mediaQuery => MediaQuery.of(context);
/// Check if dark mode theme is enable
bool get isDarkMode => (theme.brightness == Brightness.dark);
/// Check if dark mode theme is enable on platform on android Q+
bool get isPlatformDarkMode =>
(mediaQuery.platformBrightness == Brightness.dark);
/// give access to Theme.of(context).iconTheme.color
Color get iconColor => theme?.iconTheme?.color;
/// give access to FocusScope.of(context)
FocusNode get focusScope => FocusManager.instance.primaryFocus;
/// give access to Immutable MediaQuery.of(context).size.height
double get height => MediaQuery.of(context).size.height;
/// give access to Immutable MediaQuery.of(context).size.width
double get width => MediaQuery.of(context).size.width;
GlobalKey<NavigatorState> get key {
final _key = getxController?.key;
return _key;
}
Map<int, GlobalKey<NavigatorState>> get keys => getxController?.keys;
GetMaterialController get rootController => getxController;
bool get defaultPopGesture => getxController.defaultPopGesture;
bool get defaultOpaqueRoute => getxController.defaultOpaqueRoute;
Transition get defaultTransition => getxController.defaultTransition;
Duration get defaultTransitionDuration {
return getxController.defaultTransitionDuration;
}
Curve get defaultTransitionCurve => getxController.defaultTransitionCurve;
Curve get defaultDialogTransitionCurve {
return getxController.defaultDialogTransitionCurve;
}
Duration get defaultDialogTransitionDuration {
return getxController.defaultDialogTransitionDuration;
}
Routing get routing => getxController.routing;
Map<String, String> get parameters => getxController.parameters;
set parameters(Map<String, String> newParameters) =>
getxController.parameters = newParameters;
ParseRouteTree get routeTree => getxController.routeTree;
set routeTree(ParseRouteTree tree) => getxController.routeTree = tree;
CustomTransition get customTransition => getxController.customTransition;
set customTransition(CustomTransition newTransition) =>
getxController.customTransition = newTransition;
bool get testMode => getxController.testMode;
set testMode(bool isTest) => getxController.testMode = isTest;
static GetMaterialController getxController = GetMaterialController();
}
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather
/// Navigator.push(context, YourRoute());
NavigatorState get navigator => GetNavigation(Get).key.currentState;
import 'package:flutter/widgets.dart';
import '../routes/get_route.dart';
class ParseRouteTree {
final List<_ParseRouteTreeNode> _nodes = <_ParseRouteTreeNode>[];
// bool _hasDefaultRoute = false;
void addRoute(GetPage route) {
var path = route.name;
if (path == Navigator.defaultRouteName) {
// if (_hasDefaultRoute) {
// throw ("Default route was already defined");
// }
var node = _ParseRouteTreeNode(path, _ParseRouteTreeNodeType.component);
node.routes = [route];
_nodes.add(node);
// _hasDefaultRoute = true;
return;
}
if (path.startsWith("/")) {
path = path.substring(1);
}
var pathComponents = path.split('/');
_ParseRouteTreeNode parent;
for (var i = 0; i < pathComponents.length; i++) {
var component = pathComponents[i];
var node = _nodeForComponent(component, parent);
if (node == null) {
var type = _typeForComponent(component);
node = _ParseRouteTreeNode(component, type);
node.parent = parent;
if (parent == null) {
_nodes.add(node);
} else {
parent.nodes.add(node);
}
}
if (i == pathComponents.length - 1) {
if (node.routes == null) {
node.routes = [route];
} else {
node.routes.add(route);
}
}
parent = node;
}
}
_GetPageMatch matchRoute(String path) {
var usePath = path;
if (usePath.startsWith("/")) {
usePath = path.substring(1);
}
// should take off url parameters first..
final uri = Uri.tryParse(usePath);
// List<String> components = usePath.split("/");
var components = uri.pathSegments;
if (path == Navigator.defaultRouteName) {
components = ["/"];
}
var nodeMatches = <_ParseRouteTreeNode, _ParseRouteTreeNodeMatch>{};
var nodesToCheck = _nodes;
for (final checkComponent in components) {
final currentMatches = <_ParseRouteTreeNode, _ParseRouteTreeNodeMatch>{};
final nextNodes = <_ParseRouteTreeNode>[];
for (final node in nodesToCheck) {
var pathPart = checkComponent;
var queryMap = <String, String>{};
if (checkComponent.contains("?") && !checkComponent.contains("=")) {
var splitParam = checkComponent.split("?");
pathPart = splitParam[0];
queryMap = {pathPart: splitParam[1]};
} else if (checkComponent.contains("?")) {
var splitParam = checkComponent.split("?");
var splitParam2 = splitParam[1].split("=");
if (!splitParam2[1].contains("&")) {
pathPart = splitParam[0];
queryMap = {splitParam2[0]: splitParam2[1]};
} else {
pathPart = splitParam[0];
final second = splitParam[1];
var other = second.split(RegExp(r"[&,=]"));
for (var i = 0; i < (other.length - 1); i++) {
var isOdd = (i % 2 == 0);
if (isOdd) {
queryMap.addAll({other[0 + i]: other[1 + i]});
}
}
}
}
final isMatch = (node.part == pathPart || node.isParameter());
if (isMatch) {
final parentMatch = nodeMatches[node.parent];
final match = _ParseRouteTreeNodeMatch.fromMatch(parentMatch, node);
// TODO: find a way to clean this implementation.
match.parameters.addAll(uri.queryParameters);
if (node.isParameter()) {
final paramKey = node.part.substring(1);
match.parameters[paramKey] = pathPart;
}
if (queryMap != null) {
match.parameters.addAll(queryMap);
}
currentMatches[node] = match;
if (node.nodes != null) {
nextNodes.addAll(node.nodes);
}
}
}
nodeMatches = currentMatches;
nodesToCheck = nextNodes;
if (currentMatches.values.length == 0) {
return null;
}
}
var matches = nodeMatches.values.toList();
if (matches.length > 0) {
var match = matches.first;
var nodeToUse = match.node;
if (nodeToUse != null &&
nodeToUse.routes != null &&
nodeToUse.routes.length > 0) {
var routes = nodeToUse.routes;
var routeMatch = _GetPageMatch(routes[0]);
routeMatch.parameters = match.parameters;
return routeMatch;
}
}
return null;
}
_ParseRouteTreeNode _nodeForComponent(
String component,
_ParseRouteTreeNode parent,
) {
var nodes = _nodes;
if (parent != null) {
nodes = parent.nodes;
}
for (var node in nodes) {
if (node.part == component) {
return node;
}
}
return null;
}
_ParseRouteTreeNodeType _typeForComponent(String component) {
var type = _ParseRouteTreeNodeType.component;
if (_isParameterComponent(component)) {
type = _ParseRouteTreeNodeType.parameter;
}
return type;
}
bool _isParameterComponent(String component) {
return component.startsWith(":");
}
Map<String, String> parseQueryString(String query) {
var search = RegExp('([^&=]+)=?([^&]*)');
var params = <String, String>{};
if (query.startsWith('?')) query = query.substring(1);
decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
for (Match match in search.allMatches(query)) {
var key = decode(match.group(1));
final value = decode(match.group(2));
params[key] = value;
}
return params;
}
}
class _ParseRouteTreeNodeMatch {
_ParseRouteTreeNodeMatch(this.node);
_ParseRouteTreeNodeMatch.fromMatch(
_ParseRouteTreeNodeMatch match, this.node) {
parameters = <String, String>{};
if (match != null) {
parameters.addAll(match.parameters);
}
}
_ParseRouteTreeNode node;
Map<String, String> parameters = <String, String>{};
}
class _ParseRouteTreeNode {
_ParseRouteTreeNode(this.part, this.type);
String part;
_ParseRouteTreeNodeType type;
List<GetPage> routes = <GetPage>[];
List<_ParseRouteTreeNode> nodes = <_ParseRouteTreeNode>[];
_ParseRouteTreeNode parent;
bool isParameter() {
return type == _ParseRouteTreeNodeType.parameter;
}
}
class _GetPageMatch {
_GetPageMatch(this.route);
GetPage route;
Map<String, String> parameters = <String, String>{};
}
enum _ParseRouteTreeNodeType {
component,
parameter,
}
import 'package:flutter/material.dart';
import 'package:get_state_manager/get_state_manager.dart';
import 'package:get_utils/get_utils.dart';
import '../routes/custom_transition.dart';
import '../routes/observers/route_observer.dart';
import '../routes/transitions_type.dart';
import 'parse_route.dart';
class GetMaterialController extends GetxController {
bool testMode = false;
Key unikey;
ThemeData theme;
ThemeMode themeMode;
bool defaultPopGesture = GetPlatform.isIOS;
bool defaultOpaqueRoute = true;
Transition defaultTransition;
Duration defaultTransitionDuration = Duration(milliseconds: 300);
Curve defaultTransitionCurve = Curves.easeOutQuad;
Curve defaultDialogTransitionCurve = Curves.easeOutQuad;
Duration defaultDialogTransitionDuration = Duration(milliseconds: 300);
final routing = Routing();
Map<String, String> parameters = {};
ParseRouteTree routeTree;
CustomTransition customTransition;
GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
Map<int, GlobalKey<NavigatorState>> keys = {};
void setTheme(ThemeData value) {
theme = value;
update();
}
void setThemeMode(ThemeMode value) {
themeMode = value;
update();
}
void restartApp() {
unikey = UniqueKey();
update();
}
}
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_core/get_core.dart';
import 'package:get_state_manager/get_state_manager.dart';
import 'package:get_utils/get_utils.dart';
import '../../get_navigation.dart';
import 'root_controller.dart';
class GetMaterialApp extends StatelessWidget {
const GetMaterialApp({
Key key,
this.navigatorKey,
this.home,
this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
this.onGenerateRoute,
this.onGenerateInitialRoutes,
this.onUnknownRoute,
this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.translationsKeys,
this.translations,
this.textDirection,
this.title = '',
this.onGenerateTitle,
this.color,
this.customTransition,
this.onInit,
this.onDispose,
this.theme,
this.darkTheme,
this.themeMode = ThemeMode.system,
this.locale,
this.fallbackLocale,
this.localizationsDelegates,
this.localeListResolutionCallback,
this.localeResolutionCallback,
this.supportedLocales = const <Locale>[Locale('en', 'US')],
this.debugShowMaterialGrid = false,
this.showPerformanceOverlay = false,
this.checkerboardRasterCacheImages = false,
this.checkerboardOffscreenLayers = false,
this.showSemanticsDebugger = false,
this.debugShowCheckedModeBanner = true,
this.shortcuts,
this.smartManagement = SmartManagement.full,
this.initialBinding,
this.unknownRoute,
this.routingCallback,
this.defaultTransition,
// this.actions,
this.getPages,
this.opaqueRoute,
this.enableLog,
this.logWriterCallback,
this.popGesture,
this.transitionDuration,
this.defaultGlobalState,
}) : assert(routes != null),
assert(navigatorObservers != null),
assert(title != null),
assert(debugShowMaterialGrid != null),
assert(showPerformanceOverlay != null),
assert(checkerboardRasterCacheImages != null),
assert(checkerboardOffscreenLayers != null),
assert(showSemanticsDebugger != null),
assert(debugShowCheckedModeBanner != null),
super(key: key);
final GlobalKey<NavigatorState> navigatorKey;
final Widget home;
final Map<String, WidgetBuilder> routes;
final String initialRoute;
final RouteFactory onGenerateRoute;
final InitialRouteListFactory onGenerateInitialRoutes;
final RouteFactory onUnknownRoute;
final List<NavigatorObserver> navigatorObservers;
final TransitionBuilder builder;
final String title;
final GenerateAppTitle onGenerateTitle;
final ThemeData theme;
final ThemeData darkTheme;
final ThemeMode themeMode;
final CustomTransition customTransition;
final Color color;
final Map<String, Map<String, String>> translationsKeys;
final Translations translations;
final TextDirection textDirection;
final Locale locale;
final Locale fallbackLocale;
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
final LocaleListResolutionCallback localeListResolutionCallback;
final LocaleResolutionCallback localeResolutionCallback;
final Iterable<Locale> supportedLocales;
final bool showPerformanceOverlay;
final bool checkerboardRasterCacheImages;
final bool checkerboardOffscreenLayers;
final bool showSemanticsDebugger;
final bool debugShowCheckedModeBanner;
final Map<LogicalKeySet, Intent> shortcuts;
// final Map<LocalKey, ActionFactory> actions;
final bool debugShowMaterialGrid;
final Function(Routing) routingCallback;
final Transition defaultTransition;
final bool opaqueRoute;
final VoidCallback onInit;
final VoidCallback onDispose;
final bool enableLog;
final LogWriterCallback logWriterCallback;
final bool popGesture;
final SmartManagement smartManagement;
final Bindings initialBinding;
final Duration transitionDuration;
final bool defaultGlobalState;
final List<GetPage> getPages;
final GetPage unknownRoute;
Route<dynamic> generator(RouteSettings settings) {
final match = Get.routeTree.matchRoute(settings.name);
Get.parameters = match?.parameters;
if (match?.route == null) {
return GetPageRoute(
page: unknownRoute.page,
parameter: unknownRoute.parameter,
settings:
RouteSettings(name: settings.name, arguments: settings.arguments),
curve: unknownRoute.curve,
opaque: unknownRoute.opaque,
customTransition: unknownRoute.customTransition,
binding: unknownRoute.binding,
bindings: unknownRoute.bindings,
transitionDuration:
(unknownRoute.transitionDuration ?? Get.defaultTransitionDuration),
transition: unknownRoute.transition,
popGesture: unknownRoute.popGesture,
fullscreenDialog: unknownRoute.fullscreenDialog,
);
}
return GetPageRoute(
page: match.route.page,
parameter: match.route.parameter,
settings:
RouteSettings(name: settings.name, arguments: settings.arguments),
curve: match.route.curve,
opaque: match.route.opaque,
customTransition: match.route.customTransition,
binding: match.route.binding,
bindings: match.route.bindings,
transitionDuration:
(match.route.transitionDuration ?? Get.defaultTransitionDuration),
transition: match.route.transition,
popGesture: match.route.popGesture,
fullscreenDialog: match.route.fullscreenDialog,
);
}
List<Route<dynamic>> initialRoutesGenerate(String name) {
final match = Get.routeTree.matchRoute(name);
Get.parameters = match?.parameters;
//Route can be nullable, just pass the unknown route
if (match?.route == null) {
return [
GetPageRoute(
page: unknownRoute.page,
parameter: unknownRoute.parameter,
settings: RouteSettings(name: name, arguments: null),
curve: unknownRoute.curve,
opaque: unknownRoute.opaque,
customTransition: unknownRoute.customTransition,
binding: unknownRoute.binding,
bindings: unknownRoute.bindings,
transitionDuration: (unknownRoute.transitionDuration ??
Get.defaultTransitionDuration),
transition: unknownRoute.transition,
popGesture: unknownRoute.popGesture,
fullscreenDialog: unknownRoute.fullscreenDialog,
)
];
}
return [
GetPageRoute(
page: match.route.page,
parameter: match.route.parameter,
settings: RouteSettings(name: name, arguments: null),
curve: match.route.curve,
opaque: match.route.opaque,
binding: match.route.binding,
bindings: match.route.bindings,
transitionDuration:
(match.route.transitionDuration ?? Get.defaultTransitionDuration),
transition: match.route.transition,
popGesture: match.route.popGesture,
fullscreenDialog: match.route.fullscreenDialog,
)
];
}
@override
Widget build(BuildContext context) {
return GetBuilder<GetMaterialController>(
init: Get.rootController,
dispose: (d) {
onDispose?.call();
},
initState: (i) {
if (locale != null) Get.locale = locale;
if (fallbackLocale != null) Get.fallbackLocale = fallbackLocale;
if (translations != null) {
Get.addTranslations(translations.keys);
} else if (translationsKeys != null) {
Get.addTranslations(translationsKeys);
}
Get.customTransition = customTransition;
initialBinding?.dependencies();
Get.addPages(getPages);
Get.smartManagement = smartManagement;
onInit?.call();
Get.config(
enableLog: enableLog ?? Get.isLogEnable,
logWriterCallback: logWriterCallback,
defaultTransition: defaultTransition ?? Get.defaultTransition,
defaultOpaqueRoute: opaqueRoute ?? Get.isOpaqueRouteDefault,
defaultPopGesture: popGesture ?? Get.isPopGestureEnable,
defaultDurationTransition:
transitionDuration ?? Get.defaultTransitionDuration,
);
},
builder: (_) {
return MaterialApp(
key: _.unikey,
navigatorKey:
(navigatorKey == null ? Get.key : Get.addKey(navigatorKey)),
home: home,
routes: routes ?? const <String, WidgetBuilder>{},
initialRoute: initialRoute,
onGenerateRoute: (getPages != null ? generator : onGenerateRoute),
onGenerateInitialRoutes: (getPages == null || home != null)
? onGenerateInitialRoutes
: initialRoutesGenerate,
onUnknownRoute: onUnknownRoute,
navigatorObservers: (navigatorObservers == null
? <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
: <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
..addAll(navigatorObservers)),
builder: (context, child) {
return Directionality(
textDirection: textDirection ??
(rtlLanguages.contains(Get.locale?.languageCode)
? TextDirection.rtl
: TextDirection.ltr),
child: builder == null ? child : builder(context, child),
);
},
title: title ?? '',
onGenerateTitle: onGenerateTitle,
color: color,
theme: _.theme ?? theme ?? ThemeData.fallback(),
darkTheme: darkTheme,
themeMode: _.themeMode ?? themeMode ?? ThemeMode.system,
locale: Get.locale ?? locale,
localizationsDelegates: localizationsDelegates,
localeListResolutionCallback: localeListResolutionCallback,
localeResolutionCallback: localeResolutionCallback,
supportedLocales:
supportedLocales ?? const <Locale>[Locale('en', 'US')],
debugShowMaterialGrid: debugShowMaterialGrid ?? false,
showPerformanceOverlay: showPerformanceOverlay ?? false,
checkerboardRasterCacheImages:
checkerboardRasterCacheImages ?? false,
checkerboardOffscreenLayers: checkerboardOffscreenLayers ?? false,
showSemanticsDebugger: showSemanticsDebugger ?? false,
debugShowCheckedModeBanner: debugShowCheckedModeBanner ?? true,
shortcuts: shortcuts,
// actions: actions,
);
});
}
}
const List<String> rtlLanguages = <String>[
'ar', // Arabic
'fa', // Farsi
'he', // Hebrew
'ps', // Pashto
'ur',
];
abstract class Translations {
Map<String, Map<String, String>> get keys;
}