Renat Fakhrutdinov
Committed by GitHub

Merge pull request #3 from jonataslaw/master

update
Showing 53 changed files with 1139 additions and 660 deletions
## [3.5.1]
- Remove unnecessary whitespaces
## [3.5.0]
- Added logwritter (@stefandevo)
- Added responsiveValue (@juanjoseleca)
- Fixed ghost url for snackbar, bottomsheets, and dialogs and unnamed navigation.
## [3.4.6]
- Fix TextField dispose throw on last Flutter hotfix
... ... @@ -6,7 +14,8 @@
- Remove initialization console print
## [3.4.4]
- Fix exception 'isInit called null' when tags are used in conjunction with dependencies. (@djade007)
- Fix exception 'isInit called null' when tags are used in conjunction with dependencies. (@djade007)
- Fix typos (@tiagocpeixoto)
## [3.4.3]
- Fix onInit fired only first time
... ...
... ... @@ -4,7 +4,7 @@
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![Gitter](https://badges.gitter.im/flutter_get/community.svg)](https://gitter.im/flutter_get/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Discord Shield](https://discordapp.com/api/guilds/722900883784073290/widget.png?style=shield)](https://discord.com/invite/9Hpt99N)
<a href="https://github.com/Solido/awesome-flutter">
<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
</a>
... ... @@ -40,7 +40,7 @@
[**Slack (English)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Discord (English and Portuguese)**](https://discord.com/invite/9Hpt99N)
[**Discord (English, Spanish and Portuguese)**](https://discord.com/invite/9Hpt99N)
[**Telegram (Portuguese)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
... ... @@ -431,6 +431,14 @@ context.isLargeTablet()
/// True if the current device is Tablet
context.isTablet()
/// Returns a value according to the screen size
/// can give value for
/// swatch: if the shortestSide is smaller than 300
/// mobile: if the shortestSide is smaller than 600
/// tablet: if the shortestSide is smaller than 1200
/// desktop: if width is largest than 1200
context.responsiveValue<T>()
```
### Optional Global Settings and Manual configurations
... ... @@ -474,6 +482,22 @@ Get.config(
)
```
You can optionally redirect all the logging messages from Get. If you want to use your own favourite logging package and want to capture the logs there.
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// pass the message to your favourite logging package here
// please note that even if enableLog: false log messages will be pushed in this callback
// you get check the flag if you want through GetConfig.isLogEnable
}
```
## Video explanation of Other GetX Features
... ...
... ... @@ -473,6 +473,22 @@ Get.config(
)
```
É possível redirecionar todas as mensagens de log do GetX. Útil quando se tem um package de logging e vc quer que ele lide com todos os logs
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// passage a mensagem para seu package de logging favorito aqui
// Obs: mesmo que as mensagens de log estejam desativadas
// com o comando "enableLog: false", as mensagens ainda vão passar por aqui
// Você precisa checar essa config manualmente aqui se quiser respeitá-la
}
```
## Video explanation of Other GetX Features
... ...
... ... @@ -15,6 +15,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.39.10"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
args:
dependency: transitive
description:
... ... @@ -28,7 +35,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.2"
version: "2.5.0-nullsafety"
bloc:
dependency: "direct main"
description:
... ... @@ -42,7 +49,7 @@ packages:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
build:
dependency: transitive
description:
... ... @@ -105,14 +112,14 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety"
version: "1.1.0-nullsafety.2"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
version: "1.2.0-nullsafety"
checked_yaml:
dependency: transitive
description:
... ... @@ -126,7 +133,7 @@ packages:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.1.0-nullsafety"
code_builder:
dependency: transitive
description:
... ... @@ -140,7 +147,7 @@ packages:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0-nullsafety"
version: "1.15.0-nullsafety.2"
convert:
dependency: transitive
description:
... ... @@ -154,7 +161,7 @@ packages:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "2.1.4"
csslib:
dependency: transitive
description:
... ... @@ -189,7 +196,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.0-nullsafety"
fixnum:
dependency: transitive
description:
... ... @@ -270,6 +277,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
image:
dependency: transitive
description:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.12"
io:
dependency: transitive
description:
... ... @@ -304,14 +318,14 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.8"
version: "0.12.10-nullsafety"
meta:
dependency: "direct main"
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety"
version: "1.3.0-nullsafety.2"
mime:
dependency: transitive
description:
... ... @@ -367,7 +381,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety"
pedantic:
dependency: transitive
description:
... ... @@ -375,6 +389,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
pool:
dependency: transitive
description:
... ... @@ -456,21 +477,21 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.5"
version: "1.10.0-nullsafety"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
stream_transform:
dependency: transitive
description:
... ... @@ -484,21 +505,21 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "1.1.0-nullsafety"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0-nullsafety"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.17"
version: "0.2.19-nullsafety"
timing:
dependency: transitive
description:
... ... @@ -512,7 +533,7 @@ packages:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety"
version: "1.3.0-nullsafety.2"
uuid:
dependency: "direct main"
description:
... ... @@ -526,7 +547,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0-nullsafety"
version: "2.1.0-nullsafety.2"
watcher:
dependency: transitive
description:
... ... @@ -541,6 +562,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.6.1"
yaml:
dependency: transitive
description:
... ... @@ -549,5 +577,5 @@ packages:
source: hosted
version: "2.2.1"
sdks:
dart: ">=2.9.0-18.0 <2.9.0"
dart: ">=2.10.0-0.0.dev <2.10.0"
flutter: ">=1.16.0"
... ...
... ... @@ -476,7 +476,7 @@ Get.bottomSheet(
),
],
),
);
)
);
```
... ...
... ... @@ -476,7 +476,7 @@ Get.bottomSheet(
),
],
),
);
)
);
```
... ...
... ... @@ -20,7 +20,7 @@ Em vez de instanciar sua classe dentro da classe que você está usando, você e
Para que então você possa usar seu controller (ou uma classe Bloc) normalmente
**Tip:** O gerenciamento de dependência do get é desaclpado de outras partes do package, então se por exemplo seu aplicativo já está usando um outro gerenciador de estado (qualquer um, não importa), você não precisa de reescrever tudo, pode simplesmente usar só a injeção de dependência sem problemas
**Tip:** O gerenciamento de dependência do get é desacoplado de outras partes do package, então se por exemplo seu aplicativo já está usando um outro gerenciador de estado (qualquer um, não importa), você não precisa de reescrever tudo, pode simplesmente usar só a injeção de dependência sem problemas
```dart
controller.fetchApi();
... ... @@ -71,11 +71,11 @@ Para remover a instância do Get:
Get.delete<Controller>();
```
## Opções
## Métodos de instanciamento.
Quando você usa Get.put, lazyPut e putAsync, existe algumas opções que você pode alterar se quiser
Apesar do Get já entregar configurações muito boas para uso, é possível refiná-las ainda mais para que sejam de utilidade ainda maior para você programador. Os métodos e seus parâmetros configuráveis são:
- No Get.put():
- Get.put():
```dart
Get.put<S>(
... ... @@ -95,17 +95,12 @@ Get.put<S>(
// padrão: false
bool permanent = false,
// opcional: permite que depois de usar uma classe abstrata num teste,
// trocar por outra e continuar com o teste
// padrão: false
bool overrideAbstract = false,
// opcional: permite criar a dependência usando uma função em vez da dependênia em si
FcBuilderFunc<S> builder,
)
```
- No Get.lazyPut:
- Get.lazyPut:
```dart
Get.lazyPut<S>(
... ... @@ -126,7 +121,7 @@ Get.lazyPut<S>(
)
```
- No Get.putAsync:
- Get.putAsync:
```dart
Get.putAsync<S>(
... ... @@ -143,6 +138,44 @@ Get.putAsync<S>(
bool permanent = false
```
- Get.create:
```dart
Get.create<S>(
// Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado
// Exemplo: Get.create<YourClass>(() => YourClass())
FcBuilderFunc<S> builder,
// opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe.
// Útil caso você tenha uma lista em que cada item precise de um controller próprio
// precisa ser uma string única. Apenas mudou o nome de tag para name.
String name,
// opcional: igual ao Get.put(), usado quando você precisa manter a instância ativa no app inteiro. A diferença
// é que com Get.create o permanent está habilitado por padrão
bool permanent = true
```
### Diferenças entre os métodos:
Primeiramente, vamos falar das variáveis `_factory` e `_singl`. Ambas são essenciais no processo de criação e uso de suas dependências, pois é através delas que podemos armazenar, apagar, recriar nossas instâncias.
Primeiro, vamos falar do `fenix` do Get.lazyPut e o `permanent` dos outros métodos.
- O `fenix` diz respeito ao armazenamento da instância. Quando você manipula os parâmetros `fenix` ou `smartManagement` para não perder as instâncias da sua dependência, elas serão salvas na para serem chamadas posteriormente.
- O `permanent` diz respeito ao uso. Se a instância permanece ativa, ou se é apagada, quando não está em uso na tela.
A diferença fundamental entre `permanent` e `fenix` está em como você quer armazenar as suas instâncias. Reforçando: por padrão, o Get apaga as instâncias quando elas não estão em uso (Digamos que a tela 1 tenha o controlador A e tela 2, controlador B. Ao mover-se de 1 para 2, o controlador A perde o uso e portanto é apagado), mas se você optar por algo `permanent: true`, então ela não se perde nessa transição - o que é muito útil para serviços que você quer manter rodando na aplicação inteira. Já o `fenix`, é para serviços que você não se preocupa em perder por uma tela ou outra, mas quando você precisar chamar o serviço, você espera que ele "retorne das cinzas" (`fenix: true`), criando uma nova instância.
Prosseguindo com as diferenças entre os métodos:
- Get.put e Get.putAsync seguem a mesma ordem de criação, com a diferença que o Async opta por aplicar um método assíncrono: Esses dois métodos criam e já inicializam a instância. Esta é inserida diretamente na memória, através do método interno `insert` com os parâmetros `permanent: false` e `isSingleton: true` (esse parâmetro `isSingleton` serve apenas para dizer se é para utilizar a dependência colocada em `dependency`, ou se é para usar a dependência colocada no `FcBuilderFunc`). Depois disso, é chamado o `Get.find` que imediatamente inicializa as instâncias que estão na memória.
- Get.create: Como o nome indica, você vai "criar" a sua dependência! Similar ao `Get.put`, ela também chama o método interno `insert` para instanciamento. Contudo, `permanent` e `isSingleton` passam a ser `true` e `false` (Como estamos "criando" a nossa dependência, não tem como ela ser um Singleton de algo, logo, `false`). E por ser `permanent: true`, temos por padrão o benefício de não se perder entre telas! Além disso, não é chamado o `Get.find`, logo ela fica esperando ser chamada para ser usada. Ele é criado dessa forma para aproveitar o uso do parâmetro `permanent`, já que, vale ressaltar, o Get.create foi criado com o objetivo de criar instâncias não compartilhadas, mas que não se perdem, como por exemplo um botão em um listView, que você quer uma instância única para aquela lista - por conta disso, o Get.create deve ser usado em conjunto com o GetWidget.
- Get.lazyPut: Como o nome dá a entender, é um processo preguiçoso (lazy). A instância é criada, mas ela não é chamada para uso logo em seguida, ela fica aguardando ser chamada. Diferente dos outros métodos, o `insert` não é chamado. Ao invés disso, a instância é inserida em outra parte na memória, uma parte responsável por dizer se a instância pode ser recriada ou não, vamos chamá-la de "fábrica". Se queremos criar algo para ser chamado só depois, não vamos misturá-lo com as coisas que estão sendo usadas agora. E é aqui que entra a mágica do `fenix`. Se você optou por deixar `fenix: false`, e seu `smartManagement` não for `keepFactory`, então ao usar o `Get.find` a instância passa da "fábrica" para a área comum das instância. Em seguinda, por padrão é removida da "fábrica". Agora, se você optou por `fenix: true`, a instância continua a existir nessa parte dedicada, mesmo indo para a área comum, para ser chamada futuramente caso precise.
## Bindings
Um dos grandes diferenciais desse package, talvez, seja a possibilidade de integração total com rotas, gerenciador de estado e gerenciador de dependências.
... ...
# 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/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
... ...
# 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: 7c6f9dd2396dfe7deb6fd11edc12c10786490083
channel: dev
project_type: app
... ...
# example
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
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 app_configuration.mk
# Default build type.
BUILD=debug
FLUTTER_MANAGED_DIR=flutter
FLUTTER_EPHEMERAL_DIR=$(FLUTTER_MANAGED_DIR)/ephemeral
# Configuration provided via flutter tool.
FLUTTER_CONFIG_FILE=$(FLUTTER_EPHEMERAL_DIR)/generated_config.mk
include $(FLUTTER_CONFIG_FILE)
# Dependency locations
FLUTTER_APP_DIR=$(CURDIR)/..
FLUTTER_APP_BUILD_DIR=$(FLUTTER_APP_DIR)/build
OUT_DIR=$(FLUTTER_APP_BUILD_DIR)/linux
OBJ_DIR=$(OUT_DIR)/obj/$(BUILD)
# Libraries
FLUTTER_LIB_NAME=flutter_linux_glfw
FLUTTER_LIB=$(FLUTTER_EPHEMERAL_DIR)/lib$(FLUTTER_LIB_NAME).so
# Tools
FLUTTER_BIN=$(FLUTTER_ROOT)/bin/flutter
LINUX_BUILD=$(FLUTTER_ROOT)/packages/flutter_tools/bin/tool_backend.sh
# Resources
ICU_DATA_NAME=icudtl.dat
ICU_DATA_SOURCE=$(FLUTTER_EPHEMERAL_DIR)/$(ICU_DATA_NAME)
FLUTTER_ASSETS_NAME=flutter_assets
FLUTTER_ASSETS_SOURCE=$(FLUTTER_APP_BUILD_DIR)/$(FLUTTER_ASSETS_NAME)
# Bundle structure
BUNDLE_OUT_DIR=$(OUT_DIR)/$(BUILD)
BUNDLE_DATA_DIR=$(BUNDLE_OUT_DIR)/data
BUNDLE_LIB_DIR=$(BUNDLE_OUT_DIR)/lib
BIN_OUT=$(BUNDLE_OUT_DIR)/$(BINARY_NAME)
ICU_DATA_OUT=$(BUNDLE_DATA_DIR)/$(ICU_DATA_NAME)
FLUTTER_LIB_OUT=$(BUNDLE_LIB_DIR)/$(notdir $(FLUTTER_LIB))
ALL_LIBS_OUT=$(FLUTTER_LIB_OUT) \
$(foreach lib,$(EXTRA_BUNDLED_LIBRARIES),$(BUNDLE_LIB_DIR)/$(notdir $(lib)))
# Add relevant code from the wrapper library, which is intended to be statically
# built into the client.
# Use abspath for the wrapper root, which can contain relative paths; the
# intermediate build files will be based on the source path, which will cause
# issues if they start with one or more '../'s.
WRAPPER_ROOT=$(abspath $(FLUTTER_EPHEMERAL_DIR)/cpp_client_wrapper_glfw)
WRAPPER_SOURCES= \
$(WRAPPER_ROOT)/flutter_window_controller.cc \
$(WRAPPER_ROOT)/plugin_registrar.cc \
$(WRAPPER_ROOT)/engine_method_result.cc
# Use abspath for extra sources, which may also contain relative paths (see
# note above about WRAPPER_ROOT).
SOURCES=main.cc window_configuration.cc \
flutter/generated_plugin_registrant.cc \
$(WRAPPER_SOURCES) $(abspath $(EXTRA_SOURCES))
# Headers
WRAPPER_INCLUDE_DIR=$(WRAPPER_ROOT)/include
INCLUDE_DIRS=$(FLUTTER_EPHEMERAL_DIR) $(WRAPPER_INCLUDE_DIR)
# Build settings
ifneq ($(strip $(SYSTEM_LIBRARIES)),)
EXTRA_CPPFLAGS+=$(patsubst -I%,-isystem%,$(shell pkg-config --cflags $(SYSTEM_LIBRARIES)))
EXTRA_LDFLAGS+=$(shell pkg-config --libs $(SYSTEM_LIBRARIES))
endif
CXX=clang++
CPPFLAGS.release=-DNDEBUG
CPPFLAGS.profile=$(CPPFLAGS.release)
CXXFLAGS.release=-O2
CXXFLAGS.profile=$(CXXFLAGS.release)
CXXFLAGS=-std=c++14 -Wall -Werror $(CXXFLAGS.$(BUILD)) $(EXTRA_CXXFLAGS)
CPPFLAGS=$(patsubst %,-I%,$(INCLUDE_DIRS)) \
$(CPPFLAGS.$(BUILD)) $(EXTRA_CPPFLAGS)
LDFLAGS=-L$(BUNDLE_LIB_DIR) \
-l$(FLUTTER_LIB_NAME) \
$(EXTRA_LDFLAGS) \
-Wl,-rpath=\$$ORIGIN/lib
# Intermediate files.
OBJ_FILES=$(SOURCES:%.cc=$(OBJ_DIR)/%.o)
DEPENDENCY_FILES=$(OBJ_FILES:%.o=%.d)
# Targets
.PHONY: all
all: $(BIN_OUT) bundle
# Add the plugin targets, and their associated settings.
include $(FLUTTER_MANAGED_DIR)/generated_plugins.mk
EXTRA_BUNDLED_LIBRARIES+=$(PLUGIN_LIBRARIES)
EXTRA_LDFLAGS+=$(PLUGIN_LDFLAGS)
EXTRA_CPPFLAGS+=$(PLUGIN_CPPFLAGS)
# This is a phony target because the flutter tool cannot describe
# its inputs and outputs yet.
.PHONY: sync
sync: $(FLUTTER_CONFIG_FILE)
$(LINUX_BUILD) linux-x64 $(BUILD)
.PHONY: bundle
bundle: $(ICU_DATA_OUT) $(ALL_LIBS_OUT) bundleflutterassets
$(BIN_OUT): $(OBJ_FILES) $(ALL_LIBS_OUT)
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OBJ_FILES) $(LDFLAGS) -o $@
$(WRAPPER_SOURCES) $(FLUTTER_LIB) $(ICU_DATA_SOURCE) $(FLUTTER_ASSETS_SOURCE) \
$(PLUGIN_TARGETS): | sync
# Plugin library bundling pattern.
$(BUNDLE_LIB_DIR)/%: $(OUT_DIR)/%
mkdir -p $(BUNDLE_LIB_DIR)
cp $< $@
$(FLUTTER_LIB_OUT): $(FLUTTER_LIB)
mkdir -p $(@D)
cp $< $@
$(ICU_DATA_OUT): $(ICU_DATA_SOURCE)
mkdir -p $(@D)
cp $< $@
-include $(DEPENDENCY_FILES)
$(OBJ_DIR)/%.o : %.cc | sync
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -c $< -o $@
# Fully re-copy the assets directory on each build to avoid having to keep a
# comprehensive list of all asset files here, which would be fragile to changes
# in other files (e.g., adding a new font to pubspec.yaml).
.PHONY: bundleflutterassets
bundleflutterassets: $(FLUTTER_ASSETS_SOURCE)
mkdir -p $(BUNDLE_DATA_DIR)
rsync -rpu --delete $(FLUTTER_ASSETS_SOURCE) $(BUNDLE_DATA_DIR)
.PHONY: clean
clean:
rm -rf $(OUT_DIR); \
cd $(FLUTTER_APP_DIR); \
$(FLUTTER_BIN) clean
# This file contains variables that applications are likely to need to
# change, to isolate them from the main Makefile where the build rules are still
# in flux. This should simplify re-creating the runner while preserving local
# changes.
# Executable name.
BINARY_NAME=get_state
# Any extra source files to build.
EXTRA_SOURCES=
# Paths of any additional libraries to be bundled in the output directory.
EXTRA_BUNDLED_LIBRARIES=
# Extra flags (e.g., for library dependencies).
SYSTEM_LIBRARIES=
EXTRA_CXXFLAGS=
EXTRA_CPPFLAGS=
EXTRA_LDFLAGS=
\ No newline at end of file
//
// 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)
# Plugins to include in the build.
GENERATED_PLUGINS=\
GENERATED_PLUGINS_DIR=flutter/ephemeral/.plugin_symlinks
# A plugin library name plugin name with _plugin appended.
GENERATED_PLUGIN_LIB_NAMES=$(foreach plugin,$(GENERATED_PLUGINS),$(plugin)_plugin)
# Variables for use in the enclosing Makefile. Changes to these names are
# breaking changes.
PLUGIN_TARGETS=$(GENERATED_PLUGINS)
PLUGIN_LIBRARIES=$(foreach plugin,$(GENERATED_PLUGIN_LIB_NAMES),\
$(OUT_DIR)/lib$(plugin).so)
PLUGIN_LDFLAGS=$(patsubst %,-l%,$(GENERATED_PLUGIN_LIB_NAMES))
PLUGIN_CPPFLAGS=$(foreach plugin,$(GENERATED_PLUGINS),\
-I$(GENERATED_PLUGINS_DIR)/$(plugin)/linux)
# Targets
# Implicit rules don't match phony targets, so list plugin builds explicitly.
.PHONY: $(GENERATED_PLUGINS)
$(GENERATED_PLUGINS):
make -C $(GENERATED_PLUGINS_DIR)/$@/linux \
OUT_DIR=$(OUT_DIR) \
FLUTTER_EPHEMERAL_DIR="$(abspath flutter/ephemeral)"
#include <flutter/flutter_window_controller.h>
#include <linux/limits.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <vector>
#include "flutter/generated_plugin_registrant.h"
#include "window_configuration.h"
namespace {
// Returns the path of the directory containing this executable, or an empty
// string if the directory cannot be found.
std::string GetExecutableDirectory() {
char buffer[PATH_MAX + 1];
ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
if (length > PATH_MAX) {
std::cerr << "Couldn't locate executable" << std::endl;
return "";
}
std::string executable_path(buffer, length);
size_t last_separator_position = executable_path.find_last_of('/');
if (last_separator_position == std::string::npos) {
std::cerr << "Unabled to find parent directory of " << executable_path
<< std::endl;
return "";
}
return executable_path.substr(0, last_separator_position);
}
} // namespace
int main(int argc, char **argv) {
// Resources are located relative to the executable.
std::string base_directory = GetExecutableDirectory();
if (base_directory.empty()) {
base_directory = ".";
}
std::string data_directory = base_directory + "/data";
std::string assets_path = data_directory + "/flutter_assets";
std::string icu_data_path = data_directory + "/icudtl.dat";
// Arguments for the Flutter Engine.
std::vector<std::string> arguments;
flutter::FlutterWindowController flutter_controller(icu_data_path);
flutter::WindowProperties window_properties = {};
window_properties.title = kFlutterWindowTitle;
window_properties.width = kFlutterWindowWidth;
window_properties.height = kFlutterWindowHeight;
// Start the engine.
if (!flutter_controller.CreateWindow(window_properties, assets_path,
arguments)) {
return EXIT_FAILURE;
}
RegisterPlugins(&flutter_controller);
// Run until the window is closed.
while (flutter_controller.RunEventLoopWithTimeout(
std::chrono::milliseconds::max())) {
}
return EXIT_SUCCESS;
}
#include "window_configuration.h"
const char *kFlutterWindowTitle = "get_state";
const unsigned int kFlutterWindowWidth = 800;
const unsigned int kFlutterWindowHeight = 600;
#ifndef WINDOW_CONFIGURATION_
#define WINDOW_CONFIGURATION_
// This is a temporary approach to isolate common customizations from main.cpp,
// where the APIs are still in flux. This should simplify re-creating the
// runner while preserving local changes.
//
// Longer term there should be simpler configuration options for common
// customizations like this, without requiring native code changes.
extern const char *kFlutterWindowTitle;
extern const unsigned int kFlutterWindowWidth;
extern const unsigned int kFlutterWindowHeight;
#endif // WINDOW_CONFIGURATION_
... ... @@ -7,42 +7,42 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.2"
version: "2.5.0-nullsafety"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety"
version: "1.1.0-nullsafety.2"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
version: "1.2.0-nullsafety"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.1.0-nullsafety"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0-nullsafety"
version: "1.15.0-nullsafety.2"
dio:
dependency: "direct main"
description:
... ... @@ -56,7 +56,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.0-nullsafety"
flutter:
dependency: "direct main"
description: flutter
... ... @@ -70,10 +70,10 @@ packages:
get:
dependency: "direct main"
description:
name: get
url: "https://pub.dartlang.org"
source: hosted
version: "3.4.3"
path: ".."
relative: true
source: path
version: "3.5.1"
http_parser:
dependency: transitive
description:
... ... @@ -87,21 +87,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.8"
version: "0.12.10-nullsafety"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety"
version: "1.3.0-nullsafety.2"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety"
sky_engine:
dependency: transitive
description: flutter
... ... @@ -113,55 +113,55 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.5"
version: "1.10.0-nullsafety"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "1.1.0-nullsafety"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0-nullsafety"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.17"
version: "0.2.19-nullsafety"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety"
version: "1.3.0-nullsafety.2"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0-nullsafety"
version: "2.1.0-nullsafety.2"
sdks:
dart: ">=2.9.0-18.0 <2.9.0"
dart: ">=2.10.0-0.0.dev <2.10.0"
... ...
import 'package:get/src/core/log.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'package:get/src/utils/queue/get_queue.dart';
class GetConfig {
static SmartManagement smartManagement = SmartManagement.full;
... ... @@ -196,6 +197,14 @@ class GetInstance {
return true;
}
static GetQueue queue = GetQueue();
// Future<bool> delete<S>({String tag, String key, bool force = false}) async {
// final s = await queue
// .add<bool>(() async => dele<S>(tag: tag, key: key, force: force));
// return s;
// }
/// Delete class instance on [S] and clean memory
Future<bool> delete<S>({String tag, String key, bool force = false}) async {
String newKey;
... ... @@ -205,36 +214,39 @@ class GetInstance {
newKey = key;
}
if (!_singl.containsKey(newKey)) {
GetConfig.log('Instance $newKey not found', isError: true);
return false;
}
return queue.add<bool>(() async {
if (!_singl.containsKey(newKey)) {
GetConfig.log('[GETX] Instance $newKey already been removed.',
isError: true);
return false;
}
FcBuilder builder = _singl[newKey] as FcBuilder;
if (builder.permanent && !force) {
GetConfig.log(
'[GETX] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.',
isError: true);
return false;
}
final i = builder.dependency;
FcBuilder builder = _singl[newKey] as FcBuilder;
if (builder.permanent && !force) {
GetConfig.log(
'[GETX] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.',
isError: true);
return false;
}
final i = builder.dependency;
if (i is GetxService && !force) {
return false;
}
if (i is DisposableInterface) {
await i.onClose();
GetConfig.log('[GETX] onClose of $newKey called');
}
if (i is GetxService && !force) {
return false;
}
if (i is DisposableInterface) {
await i.onClose();
GetConfig.log('[GETX] onClose of $newKey called');
}
_singl.removeWhere((oldKey, value) => (oldKey == newKey));
if (_singl.containsKey(newKey)) {
GetConfig.log('[GETX] error on remove object $newKey', isError: true);
} else {
GetConfig.log('[GETX] $newKey deleted from memory');
}
// _routesKey?.remove(key);
return true;
_singl.removeWhere((oldKey, value) => (oldKey == newKey));
if (_singl.containsKey(newKey)) {
GetConfig.log('[GETX] error on remove object $newKey', isError: true);
} else {
GetConfig.log('[GETX] $newKey deleted from memory');
}
// _routesKey?.remove(key);
return true;
});
}
/// check if instance is registered
... ...
export 'get_instance.dart';
export 'extension_instance.dart';
export '../navigation/routes/bindings_interface.dart';
... ... @@ -16,6 +16,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
@required this.isScrollControlled,
RouteSettings settings,
}) : assert(isScrollControlled != null),
name = "BOTTOMSHEET: ${builder.hashCode}",
assert(isDismissible != null),
assert(enableDrag != null),
super(settings: settings);
... ... @@ -30,6 +31,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
final Color modalBarrierColor;
final bool isDismissible;
final bool enableDrag;
final String name;
// remove safearea from top
final bool removeTop;
... ...
import 'package:flutter/widgets.dart';
import '../../../instance_manager.dart';
import '../../../route_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 (GetConfig.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);
}
}
... ...
... ... @@ -4,6 +4,7 @@ import 'package:get/src/core/get_interface.dart';
import 'package:get/instance_manager.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/core/log.dart';
import 'dialog/dialog_route.dart';
import 'root/parse_route.dart';
import 'routes/bindings_interface.dart';
... ... @@ -43,18 +44,20 @@ extension GetNavigation on GetInterface {
bool fullscreenDialog = false,
Object arguments,
Bindings binding,
preventDuplicates = true,
bool preventDuplicates = true,
bool popGesture,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
String 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: '/${page.runtimeType}',
// name: forceRouteName ? '${a.runtimeType}' : '',
arguments: arguments,
),
popGesture: popGesture ?? defaultPopGesture,
... ... @@ -318,15 +321,16 @@ extension GetNavigation on GetInterface {
preventDuplicates = true,
Duration duration,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
String 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(name: '/${page.runtimeType}', arguments: arguments),
settings: RouteSettings(arguments: arguments),
routeName: routename,
fullscreenDialog: fullscreenDialog,
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
... ... @@ -375,15 +379,17 @@ extension GetNavigation on GetInterface {
}) {
var route = (Route<dynamic> rota) => false;
String routename = "/${page.runtimeType.toString()}";
return global(id).currentState.pushAndRemoveUntil(
GetPageRoute(
opaque: opaque ?? true,
popGesture: popGesture ?? defaultPopGesture,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
settings: RouteSettings(arguments: arguments),
fullscreenDialog: fullscreenDialog,
routeName: routename,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition,
),
... ... @@ -392,44 +398,76 @@ extension GetNavigation on GetInterface {
/// Show a dialog
Future<T> dialog<T>(
Widget child, {
Widget widget, {
bool barrierDismissible = true,
Color barrierColor,
bool useSafeArea = true,
bool useRootNavigator = true,
// RouteSettings routeSettings
RouteSettings routeSettings,
}) {
return showDialog(
assert(widget != null);
assert(barrierDismissible != null);
assert(useSafeArea != null);
assert(useRootNavigator != null);
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context, shadowThemeOnly: true);
return generalDialog(
pageBuilder: (BuildContext buildContext, Animation<double> animation,
Animation<double> secondaryAnimation) {
final Widget pageChild = widget;
Widget dialog = Builder(builder: (BuildContext context) {
return theme != null
? Theme(data: theme, child: pageChild)
: pageChild;
});
if (useSafeArea) {
dialog = SafeArea(child: dialog);
}
return dialog;
},
barrierDismissible: barrierDismissible,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
builder: (_) {
return child;
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: barrierColor ?? Colors.black54,
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
},
useRootNavigator: useRootNavigator,
routeSettings: routeSettings,
);
}
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
String barrierLabel = "Dismiss",
bool barrierDismissible = true,
bool barrierDismissible = false,
String barrierLabel,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
}) {
return showGeneralDialog(
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,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
);
settings: routeSettings,
));
}
Future<T> defaultDialog<T>({
... ... @@ -561,7 +599,7 @@ extension GetNavigation on GetInterface {
clipBehavior: clipBehavior,
isDismissible: isDismissible,
modalBarrierColor: barrierColor,
settings: RouteSettings(name: "bottomsheet"),
settings: settings,
enableDrag: enableDrag,
));
}
... ...
... ... @@ -279,17 +279,21 @@ extension Trans on String {
Get.translations[Get.locale.languageCode].containsKey(this)) {
return Get.translations[Get.locale.languageCode][this];
// If there is no corresponding language or corresponding key, return the key.
} else if (Get.fallbackLocale != null &&
Get.translations.containsKey(
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}") &&
Get.translations[
} else if (Get.fallbackLocale != null) {
if (Get.translations.containsKey(
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}") &&
Get.translations[
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}"]
.containsKey(this)) {
return Get.translations[
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}"]
.containsKey(this)) {
return Get.translations[
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}"]
[this];
// Checks if there is a callback language in the absence of the specific country, and if it contains that key.
[this];
}
if (Get.translations.containsKey(Get.fallbackLocale.languageCode) &&
Get.translations[Get.fallbackLocale.languageCode].containsKey(this)) {
return Get.translations[Get.fallbackLocale.languageCode][this];
}
return this;
} else {
return this;
}
... ...
export 'routes/custom_transition.dart';
export 'routes/transitions_type.dart';
export 'routes/get_route.dart';
export 'routes/default_route.dart';
export 'routes/observers/route_observer.dart';
export 'root/root_widget.dart';
export 'snackbar/snack_route.dart';
export 'bottomsheet/bottomsheet.dart';
export 'snackbar/snack.dart';
export '../core/get_main.dart';
export 'routes/default_route.dart';
export 'root/smart_management.dart';
export 'extension_navigation.dart';
... ... @@ -27,6 +27,7 @@ class GetPageRoute<T> extends PageRoute<T> {
this.barrierColor,
this.binding,
this.bindings,
this.routeName,
this.page,
this.barrierLabel,
this.maintainState = true,
... ... @@ -42,6 +43,8 @@ class GetPageRoute<T> extends PageRoute<T> {
final GetPageBuilder page;
final String routeName;
final CustomTransition customTransition;
final Bindings binding;
... ... @@ -119,8 +122,9 @@ class GetPageRoute<T> extends PageRoute<T> {
element.dependencies();
}
}
GetConfig.currentRoute = settings.name;
return page();
final pageWidget = page();
GetConfig.currentRoute = settings.name ?? routeName;
return pageWidget;
}
static bool isPopGestureInProgress(PageRoute<dynamic> route) {
... ... @@ -389,8 +393,8 @@ class GetPageRoute<T> extends PageRoute<T> {
@override
void dispose() {
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => GetInstance().removeDependencyByRoute("${settings.name}"));
WidgetsBinding.instance.addPostFrameCallback((_) => GetInstance()
.removeDependencyByRoute("${settings?.name ?? routeName}"));
}
super.dispose();
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/navigation/dialog/dialog_route.dart';
import 'package:get/src/navigation/routes/default_route.dart';
import 'package:get/src/navigation/snackbar/snack_route.dart';
class Routing {
String current;
... ... @@ -25,7 +29,6 @@ class Routing {
void update(void fn(Routing value)) {
fn(this);
GetConfig.currentRoute = this.current;
}
}
... ... @@ -46,28 +49,49 @@ class GetObserver extends NavigatorObserver {
// String previousArgs;
String removed;
String name(Route<dynamic> route) {
if (route?.settings?.name != null) {
return route?.settings?.name;
} else if (route is GetPageRoute) {
return route.routeName;
} else if (route is GetDialogRoute) {
return route.name;
} else if (route is GetModalBottomSheetRoute) {
return route.name;
} else {
return route?.settings?.name;
}
}
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
if ('${route?.settings?.name}' == 'snackbar') {
GetConfig.log("[GETX] OPEN SNACKBAR ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'bottomsheet') {
GetConfig.log("[GETX] OPEN BOTTOMSHEET ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'dialog') {
GetConfig.log("[GETX] OPEN DIALOG ${route?.settings?.name}");
} else {
GetConfig.log("[GETX] GOING TO ROUTE ${route?.settings?.name}");
bool isGetPageRoute = route is GetPageRoute;
bool isSnackbar = route is SnackRoute;
bool isDialog = route is GetDialogRoute;
bool isBottomSheet = route is GetModalBottomSheetRoute;
String routeName = name(route);
if (isSnackbar) {
GetConfig.log("[GETX] OPEN SNACKBAR $routeName");
} else if (isBottomSheet) {
GetConfig.log("[GETX] OPEN $routeName");
} else if (isDialog) {
GetConfig.log("[GETX] OPEN $routeName");
} else if (isGetPageRoute) {
GetConfig.log("[GETX] GOING TO ROUTE $routeName");
}
GetConfig.currentRoute = routeName;
_routeSend.update((value) {
if (route is PageRoute) value.current = '${route?.settings?.name}';
if (route is PageRoute) value.current = routeName;
value.args = route?.settings?.arguments;
value.route = route;
value.isBack = false;
value.removed = '';
value.previous = '${previousRoute?.settings?.name}';
value.isSnackbar = '${route?.settings?.name}' == 'snackbar';
value.isBottomSheet = '${route?.settings?.name}' == 'bottomsheet';
value.isDialog = '${route?.settings?.name}' == 'dialog';
value.isSnackbar = isSnackbar;
value.isBottomSheet = isBottomSheet;
value.isDialog = isDialog;
});
if (routing != null) routing(_routeSend);
}
... ... @@ -76,15 +100,22 @@ class GetObserver extends NavigatorObserver {
void didPop(Route route, Route previousRoute) {
super.didPop(route, previousRoute);
if ('${route?.settings?.name}' == 'snackbar') {
GetConfig.log("[GETX] CLOSE SNACKBAR ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'bottomsheet') {
GetConfig.log("[GETX] CLOSE BOTTOMSHEET ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'dialog') {
GetConfig.log("[GETX] CLOSE DIALOG ${route?.settings?.name}");
} else {
GetConfig.log("[GETX] BACK ROUTE ${route?.settings?.name}");
bool isGetPageRoute = route is GetPageRoute;
bool isSnackbar = route is SnackRoute;
bool isDialog = route is GetDialogRoute;
bool isBottomSheet = route is GetModalBottomSheetRoute;
String routeName = name(route);
if (isSnackbar) {
GetConfig.log("[GETX] CLOSE SNACKBAR $routeName");
} else if (isBottomSheet) {
GetConfig.log("[GETX] CLOSE $routeName");
} else if (isDialog) {
GetConfig.log("[GETX] CLOSE $routeName");
} else if (isGetPageRoute) {
GetConfig.log("[GETX] CLOSE TO ROUTE $routeName");
}
GetConfig.currentRoute = routeName;
_routeSend.update((value) {
if (previousRoute is PageRoute)
... ... @@ -104,9 +135,12 @@ class GetObserver extends NavigatorObserver {
@override
void didReplace({Route newRoute, Route oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
GetConfig.log("[GETX] REPLACE ROUTE ${oldRoute?.settings?.name}");
GetConfig.log("[GETX] NEW ROUTE ${newRoute?.settings?.name}");
GetConfig.currentRoute = name(newRoute);
_routeSend.update((value) {
if (newRoute is PageRoute) value.current = '${newRoute?.settings?.name}';
value.args = newRoute?.settings?.arguments;
... ...
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'rx_impl.dart';
Widget obx(Widget Function() builder) {
... ... @@ -24,6 +27,13 @@ class Obxx extends StatelessWidget {
}
}
/// The simplest reactive widget in GetX.
///
/// Just pass your Rx variable in the root scope of the callback to have it
/// automatically registered for changes.
///
/// final _name = "GetX".obs;
/// Obx(() => Text( _name.value )),... ;
class Obx extends StatefulWidget {
final Widget Function() builder;
... ... @@ -33,6 +43,7 @@ class Obx extends StatefulWidget {
class _ObxState extends State<Obx> {
RxInterface _observer;
StreamSubscription subs;
_ObxState() {
_observer = Rx();
... ... @@ -40,12 +51,13 @@ class _ObxState extends State<Obx> {
@override
void initState() {
_observer.subject.stream.listen((data) => setState(() {}));
subs = _observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
@override
void dispose() {
subs.cancel();
_observer.close();
super.dispose();
}
... ... @@ -71,3 +83,59 @@ class _ObxState extends State<Obx> {
@override
Widget build(BuildContext context) => notifyChilds;
}
/// Similar to Obx, but manages a local state.
/// Pass the initial data in constructor.
/// Useful for simple local states, like toggles, visibility, themes,
/// button states, etc.
/// Sample:
/// ObxValue((data) => Switch(
/// value: data.value,
/// onChanged: (flag) => data.value = flag,
/// ),
/// false.obs,
/// ),
// TODO: change T to a proper Rx interfase, that includes the accessor for ::value
class ObxValue<T extends RxInterface> extends StatefulWidget {
final Widget Function(T) builder;
final T data;
const ObxValue(this.builder, this.data, {Key key}) : super(key: key);
_ObxValueState createState() => _ObxValueState();
}
class _ObxValueState extends State<ObxValue> {
RxInterface _observer;
StreamSubscription subs;
_ObxValueState() {
_observer = Rx();
}
@override
void initState() {
subs = _observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
@override
void dispose() {
subs.cancel();
_observer.close();
super.dispose();
}
Widget get notifyChilds {
final observer = getObs;
getObs = _observer;
// observable is implicity taken from the constructor.
final result = widget.builder(widget.data);
getObs = observer;
return result;
}
@override
Widget build(BuildContext context) => notifyChilds;
}
... ...
... ... @@ -3,6 +3,9 @@ import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'package:get/state_manager.dart';
import 'simple_builder.dart';
typedef Disposer = void Function();
... ... @@ -48,121 +51,6 @@ class GetxController extends DisposableInterface {
void onClose() async {}
}
// class GetBuilder<T extends GetxController> extends StatefulWidget {
// final Widget Function(T) builder;
// final bool global;
// final String id;
// final String tag;
// final bool autoRemove;
// final bool assignId;
// final void Function(State state) initState, dispose, didChangeDependencies;
// final void Function(GetBuilder oldWidget, State state) didUpdateWidget;
// final T init;
// const GetBuilder({
// Key key,
// this.init,
// this.global = true,
// @required this.builder,
// this.autoRemove = true,
// this.assignId = false,
// this.initState,
// this.tag,
// this.dispose,
// this.id,
// this.didChangeDependencies,
// this.didUpdateWidget,
// }) : assert(builder != null),
// super(key: key);
// @override
// _GetBuilderState<T> createState() => _GetBuilderState<T>();
// }
// class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
// GetxController controller;
// bool isCreator = false;
// @override
// void initState() {
// super.initState();
// if (widget.initState != null) widget.initState(this);
// if (widget.global) {
// final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
// final isRegistred = GetInstance().isRegistred<T>(tag: widget.tag);
// if (isPrepared) {
// if (GetConfig.smartManagement != SmartManagement.keepFactory) {
// isCreator = true;
// }
// controller = GetInstance().find<T>(tag: widget.tag);
// } else if (isRegistred) {
// controller = GetInstance().find<T>(tag: widget.tag);
// isCreator = false;
// } else {
// controller = widget.init;
// isCreator = true;
// GetInstance().put<T>(controller, tag: widget.tag);
// }
// } else {
// controller = widget.init;
// isCreator = true;
// controller?.onStart();
// }
// if (widget.global &&
// GetConfig.smartManagement == SmartManagement.onlyBuilder) {
// controller?.onStart();
// }
// (widget.id == null)
// ? controller.addListener(setState)
// : controller.addListenerId(widget.id, setState);
// }
// @override
// void dispose() {
// super.dispose();
// if (widget.dispose != null) widget.dispose(this);
// if (isCreator || widget.assignId) {
// if (widget.autoRemove && GetInstance().isRegistred<T>(tag: widget.tag)) {
// (widget.id == null)
// ? controller.removeListener(setState)
// : controller.removeListenerId(widget.id);
// GetInstance().delete<T>(tag: widget.tag);
// }
// } else {
// (widget.id == null)
// ? controller.removeListener(setState)
// : controller.removeListenerId(widget.id);
// }
// }
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// if (widget.didChangeDependencies != null) {
// widget.didChangeDependencies(this);
// }
// }
// @override
// void didUpdateWidget(GetBuilder oldWidget) {
// super.didUpdateWidget(oldWidget as GetBuilder<T>);
// if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
// }
// @override
// Widget build(BuildContext context) {
// return widget.builder(controller);
// }
// }
// class Updater {
// final StateSetter updater;
// final String id;
// const Updater({this.updater, this.id});
// }
// typedef UpdaterBuilder = Updater Function();
class GetBuilder<T extends GetxController> extends StatefulWidget {
final Widget Function(T) builder;
final bool global;
... ... @@ -268,73 +156,23 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
}
Widget get notifyChildren {
final old = Value._remove;
Value._remove = disposers;
final observer = Value._setter;
Value._setter = setState;
final result = widget.builder(controller);
Value._setter = observer;
Value._remove = old;
return result;
}
@override
Widget build(BuildContext context) => notifyChildren;
Widget build(BuildContext context) => widget.builder(controller);
}
/// This is a experimental feature
class Value<T> extends GetxController {
Value([this._value]);
T _value;
T get value {
if (_setter != null) {
if (!_updaters.contains(_setter)) {
final add = addListener(_setter);
_remove.add(add);
}
}
TaskManager.instance.notify(_updaters);
return _value;
}
static StateSetter _setter;
static HashSet<Disposer> _remove;
set value(T newValue) {
if (_value == newValue) return;
_value = newValue;
update();
}
}
class SimpleBuilder extends StatefulWidget {
final Widget Function(BuildContext) builder;
const SimpleBuilder({Key key, @required this.builder})
: assert(builder != null),
super(key: key);
@override
_SimpleBuilderState createState() => _SimpleBuilderState();
}
class _SimpleBuilderState extends State<SimpleBuilder> {
final HashSet<Disposer> disposers = HashSet<Disposer>();
@override
void dispose() {
super.dispose();
disposers.forEach((element) => element());
}
@override
Widget build(BuildContext context) {
HashSet<Disposer> old = Value._remove;
Value._remove = disposers;
StateSetter observer = Value._setter;
Value._setter = setState;
Widget result = widget.builder(context);
Value._remove = old;
Value._setter = observer;
return result;
}
}
... ...
import 'dart:async';
import 'dart:collection';
import 'package:flutter/widgets.dart';
import 'get_state.dart';
typedef ValueBuilderUpdateCallback<T> = void Function(T snapshot);
typedef ValueBuilderBuilder<T> = Widget Function(
T snapshot, ValueBuilderUpdateCallback<T> updater);
/// Manages a local state like ObxValue, but uses a callback instead of a Rx value.
///
/// Sample:
/// ValueBuilder<bool>(
/// initialValue: false,
/// builder: (value, update) => Switch(
/// value: value,
/// onChanged: (flag) {
/// update( flag );
/// },),
/// onUpdate: (value) => print("Value updated: $value"),
/// ),
class ValueBuilder<T> extends StatefulWidget {
final T initialValue;
final ValueBuilderBuilder builder;
final void Function() onDispose;
final void Function(T) onUpdate;
const ValueBuilder({
Key key,
this.initialValue,
this.onDispose,
this.onUpdate,
@required this.builder,
}) : super(key: key);
@override
_ValueBuilderState<T> createState() => _ValueBuilderState<T>();
}
class _ValueBuilderState<T> extends State<ValueBuilder<T>> {
T value;
@override
void initState() {
super.initState();
value = widget.initialValue;
}
@override
Widget build(BuildContext context) => widget.builder(value, updater);
void updater(T newValue) {
if (widget.onUpdate != null) {
widget.onUpdate(newValue);
}
setState(() {
value = newValue;
});
}
@override
void dispose() {
super.dispose();
widget?.onDispose?.call();
if (value is ChangeNotifier) {
(value as ChangeNotifier)?.dispose();
} else if (value is StreamController) {
(value as StreamController)?.close();
}
value = null;
}
}
// It's a experimental feature
class SimpleBuilder extends StatefulWidget {
final Widget Function(BuildContext) builder;
const SimpleBuilder({Key key, @required this.builder})
: assert(builder != null),
super(key: key);
@override
_SimpleBuilderState createState() => _SimpleBuilderState();
}
class _SimpleBuilderState extends State<SimpleBuilder> {
final HashSet<Disposer> disposers = HashSet<Disposer>();
@override
void dispose() {
super.dispose();
disposers.forEach((element) => element());
}
@override
Widget build(BuildContext context) {
return TaskManager.instance
.exchange(disposers, setState, widget.builder, context);
}
}
class TaskManager {
TaskManager._();
static TaskManager _instance;
static TaskManager get instance => _instance ??= TaskManager._();
StateSetter _setter;
HashSet<Disposer> _remove;
notify(HashSet<StateSetter> _updaters) {
if (_setter != null) {
if (!_updaters.contains(_setter)) {
_updaters.add(_setter);
_remove.add(() => _updaters.remove(_setter));
}
}
}
Widget exchange(
HashSet<Disposer> disposers,
StateSetter setState,
Widget Function(BuildContext) builder,
BuildContext context,
) {
_remove = disposers;
_setter = setState;
final result = builder(context);
_remove = null;
_setter = null;
return result;
}
}
... ...
export 'simple/get_state.dart';
export 'simple/immutable_state.dart';
export 'simple/get_view.dart';
export 'simple/mixin_state.dart';
export 'rx/rx_interface.dart';
export 'rx/rx_impl.dart';
export 'rx/rx_event.dart';
export 'rx/rx_obx.dart';
export 'rx/rx_getbuilder.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
extension ContextExtensionss on BuildContext {
/// The same of [MediaQuery.of(context).size]
... ... @@ -102,4 +103,27 @@ extension ContextExtensionss on BuildContext {
/// True if the current device is Tablet
bool get isTablet => isSmallTablet || isLargeTablet;
/// Returns a specific value according to the screen size
/// if the device width is higher than or equal to 1200 return [desktop] value.
/// if the device width is higher than or equal to 600 and less than 1200
/// return [tablet] value.
/// if the device width is less than 300 return [watch] value.
/// in other cases return [mobile] value.
T responsiveValue<T>({
T mobile,
T tablet,
T desktop,
T watch,
}) {
double deviceWidth = mediaQuerySize.shortestSide;
if (kIsWeb) {
deviceWidth = mediaQuerySize.width;
}
if (deviceWidth >= 1200 && desktop != null) return desktop;
if (deviceWidth >= 600 && tablet != null) return tablet;
if (deviceWidth < 300 && watch != null) return watch;
return mobile;
}
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
extension ContextExtensionss on BuildContext {
/// The same of [MediaQuery.of(context).size]
Size get mediaQuerySize => MediaQuery.of(this).size;
/// The same of [MediaQuery.of(context).size.height]
/// Note: updates when you rezise your screen (like on a browser or desktop window)
double get height => mediaQuerySize.height;
/// The same of [MediaQuery.of(context).size.width]
/// Note: updates when you rezise your screen (like on a browser or desktop window)
double get width => mediaQuerySize.width;
/// Gives you the power to get a portion of the height.
/// Useful for responsive applications.
///
/// [dividedBy] is for when you want to have a portion of the value you would get
/// like for example: if you want a value that represents a third of the screen
/// you can set it to 3, and you will get a third of the height
///
/// [reducedBy] is a percentage value of how much of the height you want
/// if you for example want 46% of the height, then you reduce it by 56%.
double heightTransformer({double dividedBy = 1, double reducedBy = 0.0}) {
return (mediaQuerySize.height -
((mediaQuerySize.height / 100) * reducedBy)) /
dividedBy;
}
/// Gives you the power to get a portion of the width.
/// Useful for responsive applications.
///
/// [dividedBy] is for when you want to have a portion of the value you would get
/// like for example: if you want a value that represents a third of the screen
/// you can set it to 3, and you will get a third of the width
///
/// [reducedBy] is a percentage value of how much of the width you want
/// if you for example want 46% of the width, then you reduce it by 56%.
double widthTransformer({double dividedBy = 1, double reducedBy = 0.0}) {
return (mediaQuerySize.width - ((mediaQuerySize.width / 100) * reducedBy)) /
dividedBy;
}
/// Divide the height proportionally by the given value
double ratio({
double dividedBy = 1,
double reducedByW = 0.0,
double reducedByH = 0.0,
}) {
return heightTransformer(dividedBy: dividedBy, reducedBy: reducedByH) /
widthTransformer(dividedBy: dividedBy, reducedBy: reducedByW);
}
/// similar to [MediaQuery.of(context).padding]
ThemeData get theme => Theme.of(this);
/// similar to [MediaQuery.of(context).padding]
TextTheme get textTheme => Theme.of(this).textTheme;
/// similar to [MediaQuery.of(context).padding]
EdgeInsets get mediaQueryPadding => MediaQuery.of(this).padding;
/// similar to [MediaQuery.of(context).padding]
MediaQueryData get mediaQuery => MediaQuery.of(this);
/// similar to [MediaQuery.of(context).viewPadding]
EdgeInsets get mediaQueryViewPadding => MediaQuery.of(this).viewPadding;
/// similar to [MediaQuery.of(context).viewInsets]
EdgeInsets get mediaQueryViewInsets => MediaQuery.of(this).viewInsets;
/// similar to [MediaQuery.of(context).orientation]
Orientation get orientation => MediaQuery.of(this).orientation;
/// check if device is on landscape mode
bool get isLandscape => orientation == Orientation.landscape;
/// check if device is on portrait mode
bool get isPortrait => orientation == Orientation.portrait;
/// similar to [MediaQuery.of(this).devicePixelRatio]
double get devicePixelRatio => MediaQuery.of(this).devicePixelRatio;
/// similar to [MediaQuery.of(this).textScaleFactor]
double get textScaleFactor => MediaQuery.of(this).textScaleFactor;
/// get the shortestSide from screen
double get mediaQueryShortestSide => mediaQuerySize.shortestSide;
/// True if width be larger than 800
bool get showNavbar => (width > 800);
/// True if the shortestSide is smaller than 600p
bool get isPhone => (mediaQueryShortestSide < 600);
/// True if the shortestSide is largest than 600p
bool get isSmallTablet => (mediaQueryShortestSide >= 600);
/// True if the shortestSide is largest than 720p
bool get isLargeTablet => (mediaQueryShortestSide >= 720);
/// True if the current device is Tablet
bool get isTablet => isSmallTablet || isLargeTablet;
/// Returns a specific value according to the screen size
/// if the device width is higher than or equal to 1200 return [desktop] value.
/// if the device width is higher than or equal to 600 and less than 1200
/// return [tablet] value.
/// if the device width is less than 300 return [watch] value.
/// in other cases return [mobile] value.
T responsiveValue<T>({
T mobile,
T tablet,
T desktop,
T watch,
}) {
double deviceWidth = mediaQuerySize.shortestSide;
if (kIsWeb) {
deviceWidth = mediaQuerySize.width;
}
if (deviceWidth >= 1200 && desktop != null) return desktop;
if (deviceWidth >= 600 && tablet != null) return tablet;
if (deviceWidth < 300 && watch != null) return watch;
return mobile;
}
}
... ...
import 'dart:math';
extension Precision on double {
double toPrecision(int fractionDigits) {
double mod = pow(10, fractionDigits.toDouble());
return ((this * mod).round().toDouble() / mod);
}
}
... ...
import '../regex/get_utils.dart';
extension GetDynamicUtils on dynamic {
/// It's This is overloading the IDE's options. Only the most useful and popular options will stay here.
bool get isNull => GetUtils.isNull(this);
bool get isNullOrBlank => GetUtils.isNullOrBlank(this);
// bool get isOneAKind => GetUtils.isOneAKind(this);
// bool isLengthLowerThan(int maxLength) =>
// GetUtils.isLengthLowerThan(this, maxLength);
// bool isLengthGreaterThan(int maxLength) =>
// GetUtils.isLengthGreaterThan(this, maxLength);
// bool isLengthGreaterOrEqual(int maxLength) =>
// GetUtils.isLengthGreaterOrEqual(this, maxLength);
// bool isLengthLowerOrEqual(int maxLength) =>
// GetUtils.isLengthLowerOrEqual(this, maxLength);
// bool isLengthEqualTo(int maxLength) =>
// GetUtils.isLengthEqualTo(this, maxLength);
// bool isLengthBetween(int minLength, int maxLength) =>
// GetUtils.isLengthBetween(this, minLength, maxLength);
}
... ...
export 'context_extensions.dart';
export 'double_extensions.dart';
export 'dynamic_extensions.dart';
export 'num_extensions.dart';
export 'string_extensions.dart';
export 'widget_extensions.dart';
... ...
import '../regex/get_utils.dart';
extension GetNumUtils on num {
bool isLowerThan(num b) => GetUtils.isLowerThan(this, b);
bool isGreaterThan(num b) => GetUtils.isGreaterThan(this, b);
bool isEqual(num b) => GetUtils.isEqual(this, b);
}
... ...
import '../regex/get_utils.dart';
extension GetStringUtils on String {
bool get isNum => GetUtils.isNum(this);
bool get isNumericOnly => GetUtils.isNumericOnly(this);
bool get isAlphabetOnly => GetUtils.isAlphabetOnly(this);
bool get isBool => GetUtils.isBool(this);
bool get isVectorFileName => GetUtils.isVector(this);
bool get isImageFileName => GetUtils.isImage(this);
bool get isAudioFileName => GetUtils.isAudio(this);
bool get isVideoFileName => GetUtils.isVideo(this);
bool get isTxtFileName => GetUtils.isTxt(this);
bool get isDocumentFileName => GetUtils.isDocument(this);
bool get isExcelFileName => GetUtils.isExcel(this);
bool get isPPTFileName => GetUtils.isPPT(this);
bool get isAPKFileName => GetUtils.isAPK(this);
bool get isPDFFileName => GetUtils.isPDF(this);
bool get isHTMLFileName => GetUtils.isHTML(this);
bool get isURL => GetUtils.isURL(this);
bool get isEmail => GetUtils.isEmail(this);
bool get isPhoneNumber => GetUtils.isPhoneNumber(this);
bool get isDateTime => GetUtils.isDateTime(this);
bool get isMD5 => GetUtils.isMD5(this);
bool get isSHA1 => GetUtils.isSHA1(this);
bool get isSHA256 => GetUtils.isSHA256(this);
bool get isISBN => GetUtils.isISBN(this);
bool get isBinary => GetUtils.isBinary(this);
bool get isIPv4 => GetUtils.isIPv4(this);
bool get isIPv6 => GetUtils.isIPv6(this);
bool get isHexadecimal => GetUtils.isHexadecimal(this);
bool get isPalindrom => GetUtils.isPalindrom(this);
bool get isPassport => GetUtils.isPassport(this);
bool get isCurrency => GetUtils.isCurrency(this);
bool isCpf(String s) => GetUtils.isCpf(this);
bool isCnpj(String s) => GetUtils.isCnpj(this);
bool isCaseInsensitiveContains(String b) =>
GetUtils.isCaseInsensitiveContains(this, b);
bool isCaseInsensitiveContainsAny(String b) =>
GetUtils.isCaseInsensitiveContainsAny(this, b);
String capitalize(String s, {bool firstOnly = false}) =>
GetUtils.capitalize(this, firstOnly: firstOnly);
String capitalizeFirst(String s) => GetUtils.capitalizeFirst(this);
String removeAllWhitespace(String s) => GetUtils.removeAllWhitespace(this);
String camelCase(String s) => GetUtils.camelCase(this);
String numericOnly(String s, {bool firstWordOnly = false}) =>
GetUtils.numericOnly(this, firstWordOnly: firstWordOnly);
}
... ...
import 'package:flutter/widgets.dart';
extension WidgetPaddingX on Widget {
Widget paddingAll(double padding) =>
Padding(padding: EdgeInsets.all(padding), child: this);
Widget paddingSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
Padding(
padding:
EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
child: this);
Widget paddingOnly({
double left = 0.0,
double top = 0.0,
double right = 0.0,
double bottom = 0.0,
}) =>
Padding(
padding: EdgeInsets.only(
top: top, left: left, right: right, bottom: bottom),
child: this);
Widget get paddingZero => Padding(padding: EdgeInsets.zero, child: this);
}
extension WidgetMarginX on Widget {
Widget marginAll(double margin) =>
Container(margin: EdgeInsets.all(margin), child: this);
Widget marginSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
Container(
margin:
EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
child: this);
Widget marginOnly({
double left = 0.0,
double top = 0.0,
double right = 0.0,
double bottom = 0.0,
}) =>
Container(
margin: EdgeInsets.only(
top: top, left: left, right: right, bottom: bottom),
child: this);
Widget get marginZero => Container(margin: EdgeInsets.zero, child: this);
}
... ...
... ... @@ -27,7 +27,7 @@ class GetUtils {
}
/// Checks if string consist only numeric.
/// Numeric only doesnt accepting "." which double data type have
/// Numeric only doesn't accepting "." which double data type have
static bool isNumericOnly(String s) =>
RegexValidation.hasMatch(s, regex.numericOnly);
... ...
export 'context_extensions/extensions.dart';
export 'queue/get_queue.dart';
export 'platform/platform.dart';
export 'regex/get_utils.dart';
export 'regex/get_utils_extensions.dart';
export 'src/state_manager/simple/get_state.dart';
export 'src/state_manager/simple/immutable_state.dart';
export 'src/state_manager/simple/get_view.dart';
export 'src/state_manager/simple/simple_builder.dart';
export 'src/state_manager/simple/mixin_state.dart';
export 'src/state_manager/rx/rx_interface.dart';
export 'src/state_manager/rx/rx_impl.dart';
... ...
export 'src/utils/context_extensions/extensions.dart';
export 'src/utils/extensions/export.dart';
export 'src/utils/queue/get_queue.dart';
export 'src/utils/platform/platform.dart';
export 'src/utils/regex/get_utils.dart';
export 'src/utils/regex/get_utils_extensions.dart';
... ...
name: get
description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with GetX.
version: 3.4.6
version: 3.5.1
homepage: https://github.com/jonataslaw/get
environment:
sdk: ">=2.6.0 <3.0.0"
sdk: ">=2.8.0 <3.0.0"
dependencies:
flutter:
... ...
import 'package:flutter_test/flutter_test.dart';
void main() {
test('', () {});
}
... ...
import 'package:flutter_test/flutter_test.dart';
import 'package:get/utils.dart';
void main() {
test('Test for toPrecision on Double', () {
double testVar = 5.4545454;
expect(testVar.toPrecision(2), equals(5.45));
});
}
... ...
import 'package:flutter_test/flutter_test.dart';
void main() {
test('', () {});
}
... ...
import 'package:flutter_test/flutter_test.dart';
import 'package:get/utils.dart';
void main() {
num x = 5;
num y = 7;
test('Test for var.isLowerThan(value)', () {
expect(x.isLowerThan(y), true);
expect(y.isLowerThan(x), false);
});
test('Test for var.isGreaterThan(value)', () {
expect(x.isGreaterThan(y), false);
expect(y.isGreaterThan(x), true);
});
test('Test for var.isGreaterThan(value)', () {
expect(x.isEqual(y), false);
expect(y.isEqual(x), false);
expect(x.isEqual(5), true);
expect(y.isEqual(7), true);
});
}
... ...
import 'package:flutter_test/flutter_test.dart';
import 'package:get/utils.dart';
void main() {
group('Test group for extension: isNullOrBlank', () {
String testString;
test('String extension: isNullOrBlank', () {
expect(testString.isNullOrBlank, equals(true));
});
test('String extension: isNullOrBlank', () {
testString = 'Not null anymore';
expect(testString.isNullOrBlank, equals(false));
});
test('String extension: isNullOrBlank', () {
testString = '';
expect(testString.isNullOrBlank, equals(true));
});
});
}
... ...
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/utils.dart';
void main() {
group('Group test for PaddingX Extension', () {
testWidgets('Test of paddingAll', (WidgetTester tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
await tester.pumpWidget(containerTest.paddingAll(16));
expect(find.byType(Padding), findsOneWidget);
});
testWidgets('Test of paddingOnly', (WidgetTester tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
await tester.pumpWidget(containerTest.paddingOnly(top: 16));
expect(find.byType(Padding), findsOneWidget);
});
testWidgets('Test of paddingSymmetric', (WidgetTester tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
await tester.pumpWidget(containerTest.paddingSymmetric(vertical: 16));
expect(find.byType(Padding), findsOneWidget);
});
testWidgets('Test of paddingZero', (WidgetTester tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
await tester.pumpWidget(containerTest.paddingZero);
expect(find.byType(Padding), findsOneWidget);
});
});
group('Group test for MarginX Extension', () {
testWidgets('Test of marginAll', (WidgetTester tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginAll(16));
expect(find.byType(Container), findsOneWidget);
});
testWidgets('Test of marginOnly', (WidgetTester tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginOnly(top: 16));
expect(find.byType(Container), findsOneWidget);
});
testWidgets('Test of marginSymmetric', (WidgetTester tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginSymmetric(vertical: 16));
expect(find.byType(Container), findsOneWidget);
});
testWidgets('Test of marginZero', (WidgetTester tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginZero);
expect(find.byType(Container), findsOneWidget);
});
});
}
... ...