Jonny Borges
Committed by GitHub

Merge pull request #564 from Grohden/fix/lint-and-strong-mode

fix(lint/analyser): Added analyser + effective dart
Showing 67 changed files with 1104 additions and 792 deletions
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
... ...
... ... @@ -4,13 +4,15 @@ import 'package:get_state/pages/home/domain/entity/cases_model.dart';
class HomeRepository implements IHomeRepository {
HomeRepository({this.dio});
final Dio dio;
@override
Future<CasesModel> getCases() async {
try {
final response = await dio.get("https://api.covid19api.com/summary");
return CasesModel.fromJson(response.data);
return CasesModel.fromJson(response.data as Map<String, dynamic>);
} catch (e) {
print(e.toString());
return Future.error(e.toString());
... ...
... ... @@ -16,17 +16,21 @@ class CasesModel {
});
factory CasesModel.fromRawJson(String str) =>
CasesModel.fromJson(json.decode(str));
CasesModel.fromJson(json.decode(str) as Map<String, dynamic>);
String toRawJson() => json.encode(toJson());
factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel(
global: json["Global"] == null ? null : Global.fromJson(json["Global"]),
global: json["Global"] == null
? null
: Global.fromJson(json["Global"] as Map<String, dynamic>),
countries: json["Countries"] == null
? null
: List<Country>.from(
json["Countries"].map((x) => Country.fromJson(x))),
date: json["Date"] == null ? null : json["Date"],
(json["Countries"] as List<dynamic>)
.map((x) => Country.fromJson(x as Map<String, dynamic>)),
),
date: json["Date"] == null ? null : json["Date"] as String,
);
Map<String, dynamic> toJson() => {
... ... @@ -63,25 +67,30 @@ class Country {
this.date,
});
factory Country.fromRawJson(String str) => Country.fromJson(json.decode(str));
factory Country.fromRawJson(String str) =>
Country.fromJson(json.decode(str) as Map<String, dynamic>);
String toRawJson() => json.encode(toJson());
factory Country.fromJson(Map<String, dynamic> json) => Country(
country: json["Country"] == null ? null : json["Country"],
countryCode: json["CountryCode"] == null ? null : json["CountryCode"],
slug: json["Slug"] == null ? null : json["Slug"],
country: json["Country"] == null ? null : json["Country"] as String,
countryCode:
json["CountryCode"] == null ? null : json["CountryCode"] as String,
slug: json["Slug"] == null ? null : json["Slug"] as String,
newConfirmed:
json["NewConfirmed"] == null ? null : json["NewConfirmed"],
totalConfirmed:
json["TotalConfirmed"] == null ? null : json["TotalConfirmed"],
newDeaths: json["NewDeaths"] == null ? null : json["NewDeaths"],
totalDeaths: json["TotalDeaths"] == null ? null : json["TotalDeaths"],
json["NewConfirmed"] == null ? null : json["NewConfirmed"] as int,
totalConfirmed: json["TotalConfirmed"] == null
? null
: json["TotalConfirmed"] as int,
newDeaths: json["NewDeaths"] == null ? null : json["NewDeaths"] as int,
totalDeaths:
json["TotalDeaths"] == null ? null : json["TotalDeaths"] as int,
newRecovered:
json["NewRecovered"] == null ? null : json["NewRecovered"],
totalRecovered:
json["TotalRecovered"] == null ? null : json["TotalRecovered"],
date: json["Date"] == null ? null : json["Date"],
json["NewRecovered"] == null ? null : json["NewRecovered"] as int,
totalRecovered: json["TotalRecovered"] == null
? null
: json["TotalRecovered"] as int,
date: json["Date"] == null ? null : json["Date"] as String,
);
Map<String, dynamic> toJson() => {
... ... @@ -115,21 +124,25 @@ class Global {
this.totalRecovered,
});
factory Global.fromRawJson(String str) => Global.fromJson(json.decode(str));
factory Global.fromRawJson(String str) =>
Global.fromJson(json.decode(str) as Map<String, dynamic>);
String toRawJson() => json.encode(toJson());
factory Global.fromJson(Map<String, dynamic> json) => Global(
newConfirmed:
json["NewConfirmed"] == null ? null : json["NewConfirmed"],
totalConfirmed:
json["TotalConfirmed"] == null ? null : json["TotalConfirmed"],
newDeaths: json["NewDeaths"] == null ? null : json["NewDeaths"],
totalDeaths: json["TotalDeaths"] == null ? null : json["TotalDeaths"],
json["NewConfirmed"] == null ? null : json["NewConfirmed"] as int,
totalConfirmed: json["TotalConfirmed"] == null
? null
: json["TotalConfirmed"] as int,
newDeaths: json["NewDeaths"] == null ? null : json["NewDeaths"] as int,
totalDeaths:
json["TotalDeaths"] == null ? null : json["TotalDeaths"] as int,
newRecovered:
json["NewRecovered"] == null ? null : json["NewRecovered"],
totalRecovered:
json["TotalRecovered"] == null ? null : json["TotalRecovered"],
json["NewRecovered"] == null ? null : json["NewRecovered"] as int,
totalRecovered: json["TotalRecovered"] == null
? null
: json["TotalRecovered"] as int,
);
Map<String, dynamic> toJson() => {
... ...
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
... ... @@ -6,14 +7,16 @@ import 'package:get_state/pages/home/domain/entity/cases_model.dart';
class DetailsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
Country country = Get.arguments;
Country country = Get.arguments as Country;
return Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
colorFilter: ColorFilter.linearToSrgbGamma(),
image: NetworkImage(
"https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"))),
"https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
child: Container(
... ...
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
... ... @@ -13,7 +14,9 @@ class HomeView extends GetView<HomeController> {
fit: BoxFit.cover,
colorFilter: ColorFilter.linearToSrgbGamma(),
image: NetworkImage(
"https://images.pexels.com/photos/3902882/pexels-photo-3902882.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"))),
"https://images.pexels.com/photos/3902882/pexels-photo-3902882.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"),
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
... ...
import 'dart:math';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
... ... @@ -6,21 +7,24 @@ import 'package:get_state/pages/home/domain/entity/cases_model.dart';
import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
import 'package:matcher/matcher.dart';
class MockReposity implements IHomeRepository {
class MockRepository implements IHomeRepository {
@override
Future<CasesModel> getCases() async {
await Future.delayed(Duration(milliseconds: 100));
return Random().nextBool()
? CasesModel(
if (Random().nextBool()) {
return CasesModel(
global: Global(totalDeaths: 100, totalConfirmed: 200),
)
: Future.error('error');
);
}
return Future<CasesModel>.error('error');
}
}
void main() {
final binding = BindingsBuilder(() {
Get.lazyPut<IHomeRepository>(() => MockReposity());
Get.lazyPut<IHomeRepository>(() => MockRepository());
Get.lazyPut<HomeController>(
() => HomeController(homeRepository: Get.find()));
});
... ...
export 'src/instance/get_instance.dart';
export 'src/instance/extension_instance.dart';
export 'src/instance/get_instance.dart';
export 'src/navigation/routes/bindings_interface.dart';
... ...
export 'src/core/get_main.dart';
export 'src/navigation/bottomsheet/bottomsheet.dart';
export 'src/navigation/extension_navigation.dart';
export 'src/navigation/root/root_widget.dart';
export 'src/navigation/root/smart_management.dart';
export 'src/navigation/routes/custom_transition.dart';
export 'src/navigation/routes/transitions_type.dart';
export 'src/navigation/routes/get_route.dart';
export 'src/navigation/routes/default_route.dart';
export 'src/navigation/routes/default_route.dart';
export 'src/navigation/routes/get_route.dart';
export 'src/navigation/routes/observers/route_observer.dart';
export 'src/navigation/root/root_widget.dart';
export 'src/navigation/snackbar/snack_route.dart';
export 'src/navigation/bottomsheet/bottomsheet.dart';
export 'src/navigation/routes/transitions_type.dart';
export 'src/navigation/snackbar/snack.dart';
export 'src/core/get_main.dart';
export 'src/navigation/routes/default_route.dart';
export 'src/navigation/root/smart_management.dart';
export 'src/navigation/extension_navigation.dart';
export 'src/navigation/snackbar/snack_route.dart';
... ...
import 'package:flutter/material.dart';
import '../../utils.dart';
import '../navigation/root/parse_route.dart';
import '../navigation/root/root_controller.dart';
import '../navigation/routes/custom_transition.dart';
import '../navigation/routes/observers/route_observer.dart';
import '../navigation/routes/transitions_type.dart';
import '../../utils.dart';
///Use Get.to instead of Navigator.push, Get.off instead of Navigator.pushReplacement,
///Get.offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
///after them. Example: Get.toNamed, Get.offNamed, and Get.AllNamed.
///To return to the previous screen, use Get.back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
/// Use Get.to instead of Navigator.push, Get.off instead
/// of Navigator.pushReplacement,
/// Get.offAll instead of Navigator.pushAndRemoveUntil.
/// For named routes just add "named" after them. Example: Get.toNamed,
/// Get.offNamed, and Get.AllNamed.
/// To return to the previous screen, use Get.back().
/// No need to pass any context to Get, just put the name of the route inside
/// the parentheses and the magic will occur.
abstract class GetInterface {
bool defaultPopGesture = GetPlatform.isIOS;
... ...
import 'package:get/src/core/get_interface.dart';
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.
///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.
... ...
import 'package:get/instance_manager.dart';
import 'dart:developer' as developer;
import '../../instance_manager.dart';
typedef LogWriterCallback = void Function(String text, {bool isError});
void defaultLogWriterCallback(String value, {bool isError = false}) {
... ...
import 'package:get/src/core/get_interface.dart';
import '../core/get_interface.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()]).
/// the Instance and persisted as a Singleton (like you would use
/// [Get.put()]).
///
/// Using [GetConfig.smartManagement] as [SmartManagement.keepFactory] has the same outcome
/// Using [GetConfig.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()].
/// 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.
/// 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].
/// 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).
/// 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);
... ... @@ -55,14 +59,17 @@ extension Inst on GetInterface {
/// Injects an [Instance<S>] in memory.
///
/// No need to define the generic type <[S]> as it's inferred from the [dependency]
/// parameter.
/// 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 [GetConfig.smartManagement]
/// rules. Although, can be removed by [GetInstance.reset()] and [Get.delete()]
/// - [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 [GetConfig.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,
... ...
import 'package:get/src/core/log.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_core/rx_interface.dart';
import 'package:get/src/utils/queue/get_queue.dart';
import '../core/log.dart';
import '../navigation/root/smart_management.dart';
import '../state_manager/rx/rx_core/rx_interface.dart';
import '../utils/queue/get_queue.dart';
// ignore: avoid_classes_with_only_static_members
class GetConfig {
static SmartManagement smartManagement = SmartManagement.full;
static bool isLogEnable = true;
... ... @@ -19,59 +20,70 @@ class GetInstance {
/// Holds references to every registered Instance when using
/// [Get.put()]
static Map<String, _InstanceBuilderFactory> _singl = {};
static final Map<String, _InstanceBuilderFactory> _singl = {};
/// Holds a reference to every registered callback when using
/// [Get.lazyPut()]
static Map<String, _Lazy> _factory = {};
static final Map<String, _Lazy> _factory = {};
/// Holds a reference to [GetConfig.currentRoute] when the Instance was
/// created to manage the memory.
static Map<String, String> _routesKey = {};
static final Map<String, String> _routesKey = {};
static GetQueue _queue = GetQueue();
static final _queue = GetQueue();
/// 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()]).
/// the Instance and persisted as a Singleton (like you would
/// use [Get.put()]).
///
/// Using [GetConfig.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()].
/// Using [GetConfig.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.
/// 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].
/// 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}) {
String key = _getKey(S, tag);
/// 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 {
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]
/// 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 [GetConfig.smartManagement]
/// rules.
/// - [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
/// [GetConfig.smartManagement] rules.
S put<S>(
S dependency, {
String tag,
... ... @@ -121,7 +133,8 @@ class GetInstance {
}
/// Clears from memory registered Instances associated with [routeName] when
/// using [GetConfig.smartManagement] as [SmartManagement.full] or [SmartManagement.keepFactory]
/// using [GetConfig.smartManagement] as [SmartManagement.full] or
/// [SmartManagement.keepFactory]
/// Meant for internal usage of [GetPageRoute] and [GetDialogRoute]
Future<void> removeDependencyByRoute(String routeName) async {
final keysToRemove = <String>[];
... ... @@ -131,12 +144,13 @@ class GetInstance {
}
});
keysToRemove.forEach((element) async {
for (final element in keysToRemove) {
await delete(key: element);
});
keysToRemove.forEach((element) {
}
for (final element in keysToRemove) {
_routesKey?.remove(element);
});
}
keysToRemove.clear();
}
... ... @@ -147,7 +161,7 @@ class GetInstance {
/// [GetConfig.keepFactory]
bool _initDependencies<S>({String name}) {
final key = _getKey(S, name);
bool isInit = _singl[key].isInit;
final isInit = _singl[key].isInit;
if (!isInit) {
_startController<S>(tag: name);
_singl[key].isInit = true;
... ... @@ -166,7 +180,7 @@ class GetInstance {
/// Finds and returns a Instance<[S]> (or [tag]) without further processing.
S findByType<S>(Type type, {String tag}) {
String key = _getKey(type, tag);
final key = _getKey(type, tag);
return _singl[key].getDependency() as S;
}
... ... @@ -204,12 +218,12 @@ class GetInstance {
// }
/// 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.
/// 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}) {
String key = _getKey(S, tag);
final key = _getKey(S, tag);
if (isRegistered<S>(tag: tag)) {
if (_singl[key] == null) {
if (tag == null) {
... ... @@ -221,12 +235,14 @@ class GetInstance {
_initDependencies<S>(name: tag);
return _singl[key].getDependency() as S;
} else {
if (!_factory.containsKey(key))
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())"';
}
GetConfig.log('Lazy instance "$S" created');
S _value = put<S>(_factory[key].builder() as S);
var _value = put<S>(_factory[key].builder() as S);
_initDependencies<S>(name: tag);
... ... @@ -258,11 +274,15 @@ class GetInstance {
return true;
}
// 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;
// }
// 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 registered Class Instance [S] (or [tag]) and, closes any open
/// controllers [DisposableInterface], cleans up the memory
... ... @@ -292,6 +312,7 @@ class GetInstance {
final builder = _singl[newKey];
if (builder.permanent && !force) {
GetConfig.log(
// ignore: lines_longer_than_80_chars
'"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.',
isError: true,
);
... ... @@ -352,7 +373,11 @@ class _InstanceBuilderFactory<S> {
bool isInit = false;
_InstanceBuilderFactory(
this.isSingleton, this.builderFunc, this.permanent, this.isInit);
this.isSingleton,
this.builderFunc,
this.permanent,
this.isInit,
);
/// Gets the actual instance by it's [builderFunc] or the persisted instance.
S getDependency() {
... ... @@ -365,5 +390,6 @@ class _InstanceBuilderFactory<S> {
class _Lazy {
bool fenix;
InstanceBuilderCallback builder;
_Lazy(this.builder, this.fenix);
}
... ...
... ... @@ -61,7 +61,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
final BottomSheetThemeData sheetTheme =
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.
... ... @@ -130,17 +130,16 @@ class _GetModalBottomSheetState<T> extends State<_GetModalBottomSheet<T>> {
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final MediaQueryData mediaQuery = MediaQuery.of(context);
final MaterialLocalizations localizations =
MaterialLocalizations.of(context);
final String routeLabel = _getRouteLabel(localizations);
final mediaQuery = MediaQuery.of(context);
final localizations = MaterialLocalizations.of(context);
final routeLabel = _getRouteLabel(localizations);
return AnimatedBuilder(
animation: widget.route.animation,
builder: (BuildContext context, Widget child) {
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 double animationValue = mediaQuery.accessibleNavigation
final animationValue = mediaQuery.accessibleNavigation
? 1.0
: widget.route.animation.value;
return Semantics(
... ...
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/instance_manager.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/core/get_interface.dart';
import 'package:get/src/core/log.dart';
import '../../instance_manager.dart';
import '../../route_manager.dart';
import '../core/get_interface.dart';
import '../core/log.dart';
import 'dialog/dialog_route.dart';
import 'root/parse_route.dart';
import 'routes/bindings_interface.dart';
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather Navigator.push(context, YourRoute());
/// You can to use navigator.push(YourRoute()) rather
/// Navigator.push(context, YourRoute());
NavigatorState get navigator => Get.key.currentState;
extension GetNavigation on GetInterface {
... ... @@ -50,15 +51,15 @@ extension GetNavigation on GetInterface {
bool preventDuplicates = true,
bool popGesture,
}) {
String routename = "/${page.runtimeType.toString()}";
if (preventDuplicates && routename == currentRoute) {
var routeName = "/${page.runtimeType.toString()}";
if (preventDuplicates && routeName == currentRoute) {
return null;
}
return global(id).currentState.push(
GetPageRoute(
opaque: opaque ?? true,
page: () => page,
routeName: routename,
routeName: routeName,
settings: RouteSettings(
// name: forceRouteName ? '${a.runtimeType}' : '',
arguments: arguments,
... ... @@ -141,7 +142,8 @@ extension GetNavigation on GetInterface {
/// `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
/// `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
... ... @@ -164,7 +166,8 @@ extension GetNavigation on GetInterface {
/// `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
/// `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
... ... @@ -184,7 +187,8 @@ extension GetNavigation on GetInterface {
/// [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
/// `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>(
... ... @@ -200,14 +204,15 @@ extension GetNavigation on GetInterface {
/// **Navigation.popAndPushNamed()** shortcut.<br><br>
///
/// Pop the current named page and pushes a new [page] to the stack in its place
/// 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.
/// 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,
{Object arguments, int id, dynamic result}) {
return global(id)
... ... @@ -238,19 +243,24 @@ extension GetNavigation on GetInterface {
/// [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
/// `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, Object arguments, int id}) {
var route = (Route<dynamic> rota) => false;
Future<T> offAllNamed<T>(
String newRouteName, {
RoutePredicate predicate,
Object arguments,
int id,
}) {
return global(id).currentState.pushNamedAndRemoveUntil(
newRouteName, predicate ?? route,
arguments: arguments);
newRouteName,
predicate ?? (_) => false,
arguments: arguments,
);
}
/// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN
... ... @@ -265,8 +275,8 @@ extension GetNavigation on GetInterface {
///
/// 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
/// 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
... ... @@ -303,10 +313,9 @@ extension GetNavigation on GetInterface {
if ((times == null) || (times < 1)) {
times = 1;
}
int count = 0;
void back = global(id).currentState.popUntil((route) {
return count++ == times;
});
var count = 0;
var back = global(id).currentState.popUntil((route) => count++ == times);
return back;
}
... ... @@ -346,8 +355,8 @@ extension GetNavigation on GetInterface {
bool preventDuplicates = true,
Duration duration,
}) {
String routename = "/${page.runtimeType.toString()}";
if (preventDuplicates && routename == currentRoute) {
var routeName = "/${page.runtimeType.toString()}";
if (preventDuplicates && routeName == currentRoute) {
return null;
}
return global(id).currentState.pushReplacement(GetPageRoute(
... ... @@ -355,7 +364,7 @@ extension GetNavigation on GetInterface {
page: () => page,
binding: binding,
settings: RouteSettings(arguments: arguments),
routeName: routename,
routeName: routeName,
fullscreenDialog: fullscreenDialog,
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
... ... @@ -380,7 +389,8 @@ extension GetNavigation on GetInterface {
/// [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
/// `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
... ... @@ -404,9 +414,7 @@ extension GetNavigation on GetInterface {
Duration duration,
Transition transition,
}) {
var route = (Route<dynamic> rota) => false;
String routename = "/${page.runtimeType.toString()}";
var routeName = "/${page.runtimeType.toString()}";
return global(id).currentState.pushAndRemoveUntil(
GetPageRoute(
... ... @@ -416,11 +424,12 @@ extension GetNavigation on GetInterface {
binding: binding,
settings: RouteSettings(arguments: arguments),
fullscreenDialog: fullscreenDialog,
routeName: routename,
routeName: routeName,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition,
),
predicate ?? route);
predicate ?? (_) => false,
);
}
/// Show a dialog
... ... @@ -438,12 +447,11 @@ extension GetNavigation on GetInterface {
assert(useRootNavigator != null);
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context, shadowThemeOnly: true);
final 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) {
pageBuilder: (buildContext, animation, secondaryAnimation) {
final pageChild = widget;
Widget dialog = Builder(builder: (context) {
return theme != null
? Theme(data: theme, child: pageChild)
: pageChild;
... ... @@ -518,8 +526,8 @@ extension GetNavigation on GetInterface {
double radius = 20.0,
List<Widget> actions,
}) {
bool leanCancel = onCancel != null || textCancel != null;
bool leanConfirm = onConfirm != null || textConfirm != null;
var leanCancel = onCancel != null || textCancel != null;
var leanConfirm = onConfirm != null || textConfirm != null;
actions ??= [];
if (cancel != null) {
... ... @@ -632,8 +640,8 @@ extension GetNavigation on GetInterface {
));
}
void rawSnackbar(
{String title,
void rawSnackbar({
String title,
String message,
Widget titleText,
Widget messageText,
... ... @@ -668,8 +676,9 @@ extension GetNavigation on GetInterface {
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor,
Form userInputForm}) async {
GetBar getBar = GetBar(
Form userInputForm,
}) async {
final getBar = GetBar(
snackbarStatus: snackbarStatus,
title: title,
message: message,
... ... @@ -704,7 +713,8 @@ extension GetNavigation on GetInterface {
animationDuration: animationDuration,
overlayBlur: overlayBlur,
overlayColor: overlayColor,
userInputForm: userInputForm);
userInputForm: userInputForm,
);
if (instantInit) {
getBar.show();
... ... @@ -715,8 +725,10 @@ extension GetNavigation on GetInterface {
}
}
void snackbar(String title, String message,
{Color colorText,
void snackbar(
String title,
String message, {
Color colorText,
Duration duration,
/// with instantInit = false you can put snackbar on initState
... ... @@ -752,8 +764,9 @@ extension GetNavigation on GetInterface {
double overlayBlur,
SnackbarStatusCallback snackbarStatus,
Color overlayColor,
Form userInputForm}) async {
GetBar getBar = GetBar(
Form userInputForm,
}) async {
final getBar = GetBar(
snackbarStatus: snackbarStatus,
titleText: (title == null)
? null
... ... @@ -763,7 +776,8 @@ extension GetNavigation on GetInterface {
style: TextStyle(
color: colorText ?? Colors.black,
fontWeight: FontWeight.w800,
fontSize: 16),
fontSize: 16,
),
),
messageText: messageText ??
Text(
... ... @@ -771,7 +785,8 @@ extension GetNavigation on GetInterface {
style: TextStyle(
color: colorText ?? Colors.black,
fontWeight: FontWeight.w300,
fontSize: 14),
fontSize: 14,
),
),
snackPosition: snackPosition ?? SnackPosition.TOP,
borderRadius: borderRadius ?? 15,
... ... @@ -816,10 +831,13 @@ extension GetNavigation on GetInterface {
void addPages(List<GetPage> getPages) {
if (getPages != null) {
if (routeTree == null) routeTree = ParseRouteTree();
getPages.forEach((element) {
if (routeTree == null) {
routeTree = ParseRouteTree();
}
for (final element in getPages) {
routeTree.addRoute(element);
});
}
}
}
... ... @@ -922,6 +940,8 @@ extension GetNavigation on GetInterface {
RouteSettings get routeSettings => settings;
// FIXME: wouldn't a direct set suffice here?
// ignore: use_setters_to_change_properties
void setSettings(RouteSettings settings) {
this.settings = settings;
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/navigation/routes/get_route.dart';
import '../routes/get_route.dart';
class ParseRouteTree {
final List<_ParseRouteTreeNode> _nodes = <_ParseRouteTreeNode>[];
... ... @@ -7,7 +8,7 @@ class ParseRouteTree {
// bool _hasDefaultRoute = false;
void addRoute(GetPage route) {
String path = route.name;
var path = route.name;
if (path == Navigator.defaultRouteName) {
// if (_hasDefaultRoute) {
... ... @@ -22,13 +23,13 @@ class ParseRouteTree {
if (path.startsWith("/")) {
path = path.substring(1);
}
List<String> pathComponents = path.split('/');
var pathComponents = path.split('/');
_ParseRouteTreeNode parent;
for (int i = 0; i < pathComponents.length; i++) {
String component = pathComponents[i];
_ParseRouteTreeNode node = _nodeForComponent(component, parent);
for (var i = 0; i < pathComponents.length; i++) {
var component = pathComponents[i];
var node = _nodeForComponent(component, parent);
if (node == null) {
_ParseRouteTreeNodeType type = _typeForComponent(component);
var type = _typeForComponent(component);
node = _ParseRouteTreeNode(component, type);
node.parent = parent;
if (parent == null) {
... ... @@ -49,7 +50,7 @@ class ParseRouteTree {
}
_GetPageMatch matchRoute(String path) {
String usePath = path;
var usePath = path;
if (usePath.startsWith("/")) {
usePath = path.substring(1);
}
... ... @@ -57,20 +58,18 @@ class ParseRouteTree {
// should take off url parameters first..
final uri = Uri.tryParse(usePath);
// List<String> components = usePath.split("/");
List<String> components = uri.pathSegments;
var components = uri.pathSegments;
if (path == Navigator.defaultRouteName) {
components = ["/"];
}
Map<_ParseRouteTreeNode, _ParseRouteTreeNodeMatch> nodeMatches =
<_ParseRouteTreeNode, _ParseRouteTreeNodeMatch>{};
List<_ParseRouteTreeNode> nodesToCheck = _nodes;
for (String checkComponent in components) {
Map<_ParseRouteTreeNode, _ParseRouteTreeNodeMatch> currentMatches =
<_ParseRouteTreeNode, _ParseRouteTreeNodeMatch>{};
List<_ParseRouteTreeNode> nextNodes = <_ParseRouteTreeNode>[];
for (_ParseRouteTreeNode node in nodesToCheck) {
String pathPart = checkComponent;
Map<String, String> queryMap = {};
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("?");
... ... @@ -84,28 +83,27 @@ class ParseRouteTree {
queryMap = {splitParam2[0]: splitParam2[1]};
} else {
pathPart = splitParam[0];
final segunda = splitParam[1];
var other = segunda.split(RegExp(r"[&,=]"));
final second = splitParam[1];
var other = second.split(RegExp(r"[&,=]"));
for (var i = 0; i < (other.length - 1); i++) {
bool impar = (i % 2 == 0);
if (impar) {
var isOdd = (i % 2 == 0);
if (isOdd) {
queryMap.addAll({other[0 + i]: other[1 + i]});
}
}
}
}
bool isMatch = (node.part == pathPart || node.isParameter());
final isMatch = (node.part == pathPart || node.isParameter());
if (isMatch) {
_ParseRouteTreeNodeMatch parentMatch = nodeMatches[node.parent];
_ParseRouteTreeNodeMatch match =
_ParseRouteTreeNodeMatch.fromMatch(parentMatch, node);
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()) {
String paramKey = node.part.substring(1);
final paramKey = node.part.substring(1);
match.parameters[paramKey] = pathPart;
}
if (queryMap != null) {
... ... @@ -124,16 +122,16 @@ class ParseRouteTree {
return null;
}
}
List<_ParseRouteTreeNodeMatch> matches = nodeMatches.values.toList();
var matches = nodeMatches.values.toList();
if (matches.length > 0) {
_ParseRouteTreeNodeMatch match = matches.first;
_ParseRouteTreeNode nodeToUse = match.node;
var match = matches.first;
var nodeToUse = match.node;
if (nodeToUse != null &&
nodeToUse.routes != null &&
nodeToUse.routes.length > 0) {
List<GetPage> routes = nodeToUse.routes;
_GetPageMatch routeMatch = _GetPageMatch(routes[0]);
var routes = nodeToUse.routes;
var routeMatch = _GetPageMatch(routes[0]);
routeMatch.parameters = match.parameters;
... ... @@ -144,12 +142,14 @@ class ParseRouteTree {
}
_ParseRouteTreeNode _nodeForComponent(
String component, _ParseRouteTreeNode parent) {
List<_ParseRouteTreeNode> nodes = _nodes;
String component,
_ParseRouteTreeNode parent,
) {
var nodes = _nodes;
if (parent != null) {
nodes = parent.nodes;
}
for (_ParseRouteTreeNode node in nodes) {
for (var node in nodes) {
if (node.part == component) {
return node;
}
... ... @@ -158,7 +158,7 @@ class ParseRouteTree {
}
_ParseRouteTreeNodeType _typeForComponent(String component) {
_ParseRouteTreeNodeType type = _ParseRouteTreeNodeType.component;
var type = _ParseRouteTreeNodeType.component;
if (_isParameterComponent(component)) {
type = _ParseRouteTreeNodeType.parameter;
}
... ... @@ -171,12 +171,13 @@ class ParseRouteTree {
Map<String, String> parseQueryString(String query) {
var search = RegExp('([^&=]+)=?([^&]*)');
var params = Map<String, String>();
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)) {
String key = decode(match.group(1));
String value = decode(match.group(2));
var key = decode(match.group(1));
final value = decode(match.group(2));
params[key] = value;
}
return params;
... ...
import 'package:flutter/material.dart';
import 'package:get/src/state_manager/simple/get_state.dart';
import '../../state_manager/simple/get_state.dart';
class GetMaterialController extends GetxController {
Key key;
... ...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/src/core/log.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/navigation/routes/get_route.dart';
import '../../../get.dart';
import '../../core/log.dart';
import '../../instance/get_instance.dart';
import '../routes/get_route.dart';
import 'root_controller.dart';
import 'smart_management.dart';
... ... @@ -97,6 +98,7 @@ class GetMaterialApp extends StatelessWidget {
final bool showSemanticsDebugger;
final bool debugShowCheckedModeBanner;
final Map<LogicalKeySet, Intent> shortcuts;
// final Map<LocalKey, ActionFactory> actions;
final bool debugShowMaterialGrid;
final Function(Routing) routingCallback;
... ... @@ -266,7 +268,8 @@ extension Trans on String {
// Returns the key if locale is null.
if (Get.locale?.languageCode == null) return this;
// Checks whether the language code and country code are present, and whether the key is also present.
// Checks whether the language code and country code are present, and
// whether the key is also present.
if (Get.translations.containsKey(
"${Get.locale.languageCode}_${Get.locale.countryCode}") &&
Get.translations["${Get.locale.languageCode}_${Get.locale.countryCode}"]
... ... @@ -274,24 +277,24 @@ extension Trans on String {
return Get.translations[
"${Get.locale.languageCode}_${Get.locale.countryCode}"][this];
// Checks if there is a callback language in the absence of the specific country, and if it contains that key.
// Checks if there is a callback language in the absence of the specific
// country, and if it contains that key.
} else if (Get.translations.containsKey(Get.locale.languageCode) &&
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.
// If there is no corresponding language or corresponding key, return
// the key.
} 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}"]
[this];
final fallback = Get.fallbackLocale;
final key = "${fallback.languageCode}_${fallback.countryCode}";
if (Get.translations.containsKey(key) &&
Get.translations[key].containsKey(this)) {
return Get.translations[key][this];
}
if (Get.translations.containsKey(Get.fallbackLocale.languageCode) &&
Get.translations[Get.fallbackLocale.languageCode].containsKey(this)) {
return Get.translations[Get.fallbackLocale.languageCode][this];
if (Get.translations.containsKey(fallback.languageCode) &&
Get.translations[fallback.languageCode].containsKey(this)) {
return Get.translations[fallback.languageCode][this];
}
return this;
} else {
... ... @@ -300,11 +303,11 @@ extension Trans on String {
}
String trArgs([List<String> args]) {
String key = tr;
var key = tr;
if (args != null) {
args.forEach((arg) {
for (final arg in args) {
key = key.replaceFirst(RegExp(r'%s'), arg.toString());
});
}
}
return key;
}
... ...
import 'package:get/get.dart';
import '../../../get.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
/// 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();
}
... ...
import 'package:flutter/widgets.dart';
// ignore: one_member_abstracts
abstract class CustomTransition {
Widget buildTransition(
BuildContext context,
... ...
import 'dart:math';
import 'dart:ui' show lerpDouble;
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/core/get_main.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/utils.dart';
import '../../../route_manager.dart';
import '../../../utils.dart';
import '../../core/get_main.dart';
import '../../instance/get_instance.dart';
import 'bindings_interface.dart';
import 'custom_transition.dart';
import 'default_transitions.dart';
... ... @@ -78,7 +80,8 @@ class GetPageRoute<T> extends PageRoute<T> {
@override
bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
// Don't perform outgoing animation if the next route is a fullscreen dialog.
// Don't perform outgoing animation if the next route is a
// fullscreen dialog.
return nextRoute is PageRoute && !nextRoute.fullscreenDialog;
}
... ... @@ -93,8 +96,9 @@ class GetPageRoute<T> extends PageRoute<T> {
if (route.animation.status != AnimationStatus.completed) return false;
if (route.secondaryAnimation.status != AnimationStatus.dismissed)
if (route.secondaryAnimation.status != AnimationStatus.dismissed) {
return false;
}
if (isPopGestureInProgress(route)) return false;
... ... @@ -112,14 +116,17 @@ class GetPageRoute<T> extends PageRoute<T> {
}
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
if (binding != null) {
binding.dependencies();
}
if (bindings != null) {
for (Bindings element in bindings) {
element.dependencies();
for (final binding in bindings) {
binding.dependencies();
}
}
final pageWidget = page();
... ... @@ -144,8 +151,8 @@ class GetPageRoute<T> extends PageRoute<T> {
linearTransition: true);
}
if (this.customTransition != null) {
return this.customTransition.buildTransition(
if (customTransition != null) {
return customTransition.buildTransition(
context,
curve,
alignment,
... ... @@ -156,7 +163,8 @@ class GetPageRoute<T> extends PageRoute<T> {
enabledCallback: () => _isPopGestureEnabled<T>(this),
onStartPopGesture: () => _startPopGesture<T>(this),
child: child)
: child);
: child,
);
}
switch (transition ?? Get.defaultTransition) {
... ... @@ -335,7 +343,7 @@ class GetPageRoute<T> extends PageRoute<T> {
: child);
case Transition.native:
if (GetPlatform.isIOS)
if (GetPlatform.isIOS) {
return CupertinoTransitions().buildTransitions(
context,
curve,
... ... @@ -348,6 +356,7 @@ class GetPageRoute<T> extends PageRoute<T> {
onStartPopGesture: () => _startPopGesture<T>(this),
child: child)
: child);
}
return FadeUpwardsPageTransitionsBuilder().buildTransitions(
this,
... ... @@ -362,7 +371,7 @@ class GetPageRoute<T> extends PageRoute<T> {
: child);
default:
if (GetPlatform.isIOS)
if (GetPlatform.isIOS) {
return CupertinoTransitions().buildTransitions(
context,
curve,
... ... @@ -375,6 +384,7 @@ class GetPageRoute<T> extends PageRoute<T> {
onStartPopGesture: () => _startPopGesture<T>(this),
child: child)
: child);
}
return FadeUpwardsPageTransitionsBuilder().buildTransitions(
this,
... ... @@ -475,8 +485,8 @@ class _CupertinoBackGestureDetectorState<T>
void _handleDragCancel() {
assert(mounted);
// This can be called even if start is not called, paired with the "down" event
// that we don't consider here.
// This can be called even if start is not called, paired with
// the "down" event that we don't consider here.
_backGestureController?.dragEnd(0.0);
_backGestureController = null;
}
... ... @@ -492,6 +502,9 @@ class _CupertinoBackGestureDetectorState<T>
case TextDirection.ltr:
return value;
}
// FIXME: shouldn't we return a default here?
// or perhaps throw error
// ignore: avoid_returning_null
return null;
}
... ... @@ -500,7 +513,7 @@ class _CupertinoBackGestureDetectorState<T>
assert(debugCheckHasDirectionality(context));
// For devices with notches, the drag area needs to be larger on the side
// that has the notch.
double dragAreaWidth = Directionality.of(context) == TextDirection.ltr
var dragAreaWidth = Directionality.of(context) == TextDirection.ltr
? MediaQuery.of(context).padding.left
: MediaQuery.of(context).padding.right;
dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
... ... @@ -569,10 +582,12 @@ class _CupertinoBackGestureController<T> {
// The closer the panel is to dismissing, the shorter the animation is.
// We want to cap the animation time, but we want to use a linear curve
// to determine it.
final int droppedPageForwardAnimationTime = min(
final droppedPageForwardAnimationTime = min(
lerpDouble(
_kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)
.floor(),
_kMaxDroppedSwipePageForwardAnimationTime,
0,
controller.value,
).floor(),
_kMaxPageBackAnimationTime,
);
controller.animateTo(1.0,
... ... @@ -582,15 +597,20 @@ class _CupertinoBackGestureController<T> {
// This route is destined to pop at this point. Reuse navigator's pop.
navigator.pop();
// The popping may have finished inline if already at the target destination.
// The popping may have finished inline if already at the target
// destination.
if (controller.isAnimating) {
// Otherwise, use a custom popping animation duration and curve.
final int droppedPageBackAnimationTime = lerpDouble(
0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)
.floor();
controller.animateBack(0.0,
final droppedPageBackAnimationTime = lerpDouble(
0,
_kMaxDroppedSwipePageForwardAnimationTime,
controller.value,
).floor();
controller.animateBack(
0.0,
duration: Duration(milliseconds: droppedPageBackAnimationTime),
curve: animationCurve);
curve: animationCurve,
);
}
}
... ... @@ -599,7 +619,7 @@ class _CupertinoBackGestureController<T> {
// curve of the page transition mid-flight since CupertinoPageTransition
// depends on userGestureInProgress.
AnimationStatusListener animationStatusCallback;
animationStatusCallback = (AnimationStatus status) {
animationStatusCallback = (status) {
navigator.didStopUserGesture();
controller.removeStatusListener(animationStatusCallback);
};
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/navigation/routes/bindings_interface.dart';
import 'bindings_interface.dart';
import 'custom_transition.dart';
import 'transitions_type.dart';
... ...
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';
import '../../../../route_manager.dart';
import '../../../instance/get_instance.dart';
import '../../dialog/dialog_route.dart';
import '../../snackbar/snack_route.dart';
import '../default_route.dart';
class Routing {
String current;
... ... @@ -15,6 +16,7 @@ class Routing {
bool isSnackbar;
bool isBottomSheet;
bool isDialog;
Routing({
this.current = '',
this.previous = '',
... ... @@ -36,6 +38,7 @@ class GetObserver extends NavigatorObserver {
final Function(Routing) routing;
GetObserver([this.routing, this._routeSend]);
final Routing _routeSend;
Route<dynamic> route;
... ... @@ -46,6 +49,7 @@ class GetObserver extends NavigatorObserver {
String current;
String previous;
Object args;
// String previousArgs;
String removed;
... ... @@ -65,11 +69,11 @@ class GetObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
bool isGetPageRoute = route is GetPageRoute;
bool isSnackbar = route is SnackRoute;
bool isDialog = route is GetDialogRoute;
bool isBottomSheet = route is GetModalBottomSheetRoute;
String routeName = name(route);
var isGetPageRoute = route is GetPageRoute;
var isSnackbar = route is SnackRoute;
var isDialog = route is GetDialogRoute;
var isBottomSheet = route is GetModalBottomSheetRoute;
var routeName = name(route);
if (isSnackbar) {
GetConfig.log("OPEN SNACKBAR $routeName");
... ... @@ -100,11 +104,11 @@ class GetObserver extends NavigatorObserver {
void didPop(Route route, Route previousRoute) {
super.didPop(route, previousRoute);
bool isGetPageRoute = route is GetPageRoute;
bool isSnackbar = route is SnackRoute;
bool isDialog = route is GetDialogRoute;
bool isBottomSheet = route is GetModalBottomSheetRoute;
String routeName = name(route);
var isGetPageRoute = route is GetPageRoute;
var isSnackbar = route is SnackRoute;
var isDialog = route is GetDialogRoute;
var isBottomSheet = route is GetModalBottomSheetRoute;
var routeName = name(route);
if (isSnackbar) {
GetConfig.log("CLOSE SNACKBAR $routeName");
... ... @@ -118,8 +122,9 @@ class GetObserver extends NavigatorObserver {
GetConfig.currentRoute = routeName;
_routeSend.update((value) {
if (previousRoute is PageRoute)
if (previousRoute is PageRoute) {
value.current = previousRoute?.settings?.name ?? '';
}
value.args = route?.settings?.arguments;
value.route = previousRoute;
value.isBack = true;
... ...
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import '../../../get.dart';
import 'snack_route.dart';
typedef void SnackbarStatusCallback(SnackbarStatus status);
typedef void OnTap(GetBar snack);
typedef SnackbarStatusCallback = void Function(SnackbarStatus status);
typedef OnTap = void Function(GetBar snack);
// ignore: must_be_immutable
class GetBar<T extends Object> extends StatefulWidget {
GetBar(
{Key key,
String title,
String message,
Widget titleText,
Widget messageText,
Widget icon,
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,
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),
GetBar({
Key key,
this.title,
this.message,
this.titleText,
this.messageText,
this.icon,
this.shouldIconPulse = true,
this.maxWidth,
this.margin = const EdgeInsets.all(0.0),
this.padding = const EdgeInsets.all(16),
this.borderRadius = 0.0,
this.borderColor,
this.borderWidth = 1.0,
this.backgroundColor = const Color(0xFF303030),
this.leftBarIndicatorColor,
this.boxShadows,
this.backgroundGradient,
this.mainButton,
this.onTap,
this.duration,
this.isDismissible = true,
this.dismissDirection = SnackDismissDirection.VERTICAL,
this.showProgressIndicator = false,
this.progressIndicatorController,
this.progressIndicatorBackgroundColor,
this.progressIndicatorValueColor,
this.snackPosition = SnackPosition.BOTTOM,
this.snackStyle = SnackStyle.FLOATING,
this.forwardAnimationCurve = Curves.easeOutCirc,
this.reverseAnimationCurve = Curves.easeOutCirc,
this.animationDuration = const Duration(seconds: 1),
this.barBlur = 0.0,
this.overlayBlur = 0.0,
this.overlayColor = Colors.transparent,
this.userInputForm,
SnackbarStatusCallback snackbarStatus,
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor = Colors.transparent,
Form userInputForm})
: this.title = title,
this.message = message,
this.titleText = titleText,
this.messageText = messageText,
this.icon = icon,
this.shouldIconPulse = shouldIconPulse,
this.maxWidth = maxWidth,
this.margin = margin,
this.padding = padding,
this.borderRadius = borderRadius,
this.borderColor = borderColor,
this.borderWidth = borderWidth,
this.backgroundColor = backgroundColor,
this.leftBarIndicatorColor = leftBarIndicatorColor,
this.boxShadows = boxShadows,
this.backgroundGradient = backgroundGradient,
this.mainButton = mainButton,
this.onTap = onTap,
this.duration = duration,
this.isDismissible = isDismissible,
this.dismissDirection = dismissDirection,
this.showProgressIndicator = showProgressIndicator,
this.progressIndicatorController = progressIndicatorController,
this.progressIndicatorBackgroundColor =
progressIndicatorBackgroundColor,
this.progressIndicatorValueColor = progressIndicatorValueColor,
this.snackPosition = snackPosition,
this.snackStyle = snackStyle,
this.forwardAnimationCurve = forwardAnimationCurve,
this.reverseAnimationCurve = reverseAnimationCurve,
this.animationDuration = animationDuration,
this.barBlur = barBlur,
this.overlayBlur = overlayBlur,
this.overlayColor = overlayColor,
this.userInputForm = userInputForm,
super(key: key) {
}) : super(key: key) {
this.snackbarStatus = snackbarStatus ?? (status) {};
}
... ... @@ -95,20 +62,24 @@ class GetBar<T extends Object> extends StatefulWidget {
/// The message displayed to the user.
final String message;
/// Replaces [title]. Although this accepts a [Widget], it is meant to receive [Text] or [RichText]
/// Replaces [title]. Although this accepts a [Widget], it is meant
/// to receive [Text] or [RichText]
final Widget titleText;
/// Replaces [message]. Although this accepts a [Widget], it is meant to receive [Text] or [RichText]
/// Replaces [message]. Although this accepts a [Widget], it is meant
/// to receive [Text] or [RichText]
final Widget messageText;
/// Will be ignored if [backgroundGradient] is not null
final Color backgroundColor;
/// If not null, shows a left vertical colored bar on notification.
/// It is not possible to use it with a [Form] and I do not recommend using it with [LinearProgressIndicator]
/// It is not possible to use it with a [Form] and I do not recommend
/// using it with [LinearProgressIndicator]
final Color leftBarIndicatorColor;
/// [boxShadows] The shadows generated by Snack. Leave it null if you don't want a shadow.
/// [boxShadows] The shadows generated by Snack. Leave it null
/// if you don't want a shadow.
/// You can use more than one if you feel the need.
/// Check (this example)[https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/shadows.dart]
final List<BoxShadow> boxShadows;
... ... @@ -116,7 +87,8 @@ class GetBar<T extends Object> extends StatefulWidget {
/// Makes [backgroundColor] be ignored.
final Gradient backgroundGradient;
/// You can use any widget here, but I recommend [Icon] or [Image] as indication of what kind
/// You can use any widget here, but I recommend [Icon] or [Image] as
/// indication of what kind
/// of message you are displaying. Other widgets may break the layout
final Widget icon;
... ... @@ -126,16 +98,19 @@ class GetBar<T extends Object> extends StatefulWidget {
/// A [FlatButton] widget if you need an action from the user.
final FlatButton mainButton;
/// A callback that registers the user's click anywhere. An alternative to [mainButton]
/// A callback that registers the user's click anywhere.
/// An alternative to [mainButton]
final OnTap onTap;
/// How long until Snack will hide itself (be dismissed). To make it indefinite, leave it null.
/// How long until Snack will hide itself (be dismissed).
/// To make it indefinite, leave it null.
final Duration duration;
/// True if you want to show a [LinearProgressIndicator].
final bool showProgressIndicator;
/// An optional [AnimationController] when you want to control the progress of your [LinearProgressIndicator].
/// An optional [AnimationController] when you want to control the
/// progress of your [LinearProgressIndicator].
final AnimationController progressIndicatorController;
/// A [LinearProgressIndicator] configuration parameter.
... ... @@ -144,9 +119,11 @@ class GetBar<T extends Object> extends StatefulWidget {
/// A [LinearProgressIndicator] configuration parameter.
final Animation<Color> progressIndicatorValueColor;
/// Determines if the user can swipe or click the overlay (if [overlayBlur] > 0) to dismiss.
/// Determines if the user can swipe or click the overlay
/// (if [overlayBlur] > 0) to dismiss.
/// It is recommended that you set [duration] != null if this is false.
/// If the user swipes to dismiss or clicks the overlay, no value will be returned.
/// If the user swipes to dismiss or clicks the overlay, no value
/// will be returned.
final bool isDismissible;
/// Used to limit Snack width (usually on large screens)
... ... @@ -160,33 +137,41 @@ class GetBar<T extends Object> extends StatefulWidget {
final EdgeInsets padding;
/// Adds a radius to all corners of Snack. Best combined with [margin].
/// I do not recommend using it with [showProgressIndicator] or [leftBarIndicatorColor].
/// I do not recommend using it with [showProgressIndicator]
/// or [leftBarIndicatorColor].
final double borderRadius;
/// Adds a border to every side of Snack
/// I do not recommend using it with [showProgressIndicator] or [leftBarIndicatorColor].
/// I do not recommend using it with [showProgressIndicator]
/// or [leftBarIndicatorColor].
final Color borderColor;
/// Changes the width of the border if [borderColor] is specified
final double borderWidth;
/// Snack can be based on [SnackPosition.TOP] or on [SnackPosition.BOTTOM] of your screen.
/// Snack can be based on [SnackPosition.TOP] or on [SnackPosition.BOTTOM]
/// of your screen.
/// [SnackPosition.BOTTOM] is the default.
final SnackPosition snackPosition;
/// [SnackDismissDirection.VERTICAL] by default.
/// Can also be [SnackDismissDirection.HORIZONTAL] in which case both left and right dismiss are allowed.
/// Can also be [SnackDismissDirection.HORIZONTAL] in which case both left
/// and right dismiss are allowed.
final SnackDismissDirection dismissDirection;
/// Snack can be floating or be grounded to the edge of the screen.
/// If grounded, I do not recommend using [margin] or [borderRadius]. [SnackStyle.FLOATING] is the default
/// If grounded, I do not recommend using a [backgroundColor] with transparency or [barBlur]
/// If grounded, I do not recommend using [margin] or [borderRadius].
/// [SnackStyle.FLOATING] is the default
/// If grounded, I do not recommend using a [backgroundColor] with
/// transparency or [barBlur]
final SnackStyle snackStyle;
/// The [Curve] animation used when show() is called. [Curves.easeOut] is default
/// The [Curve] animation used when show() is called.
/// [Curves.easeOut] is default
final Curve forwardAnimationCurve;
/// The [Curve] animation used when dismiss() is called. [Curves.fastOutSlowIn] is default
/// The [Curve] animation used when dismiss() is called.
/// [Curves.fastOutSlowIn] is default
final Curve reverseAnimationCurve;
/// Use it to speed up or slow down the animation duration
... ... @@ -203,15 +188,18 @@ class GetBar<T extends Object> extends StatefulWidget {
final double overlayBlur;
/// Default is [Colors.transparent]. Only takes effect if [overlayBlur] > 0.0.
/// Make sure you use a color with transparency here e.g. Colors.grey[600].withOpacity(0.2).
/// Make sure you use a color with transparency here e.g.
/// Colors.grey[600].withOpacity(0.2).
final Color overlayColor;
/// A [TextFormField] in case you want a simple user input. Every other widget is ignored if this is not null.
/// A [TextFormField] in case you want a simple user input.
/// Every other widget is ignored if this is not null.
final Form userInputForm;
SnackRoute<T> _snackRoute;
/// Show the snack. Kicks in [SnackbarStatus.OPENING] state followed by [SnackbarStatus.OPEN]
/// Show the snack. Kicks in [SnackbarStatus.OPENING] state
/// followed by [SnackbarStatus.OPEN]
Future<T> show() async {
_snackRoute = showSnack<T>(
snack: this,
... ... @@ -231,9 +219,12 @@ class GetBar<T extends Object> extends StatefulWidget {
_snackRoute.navigator.pop(result);
return _snackRoute.completed;
} else if (_snackRoute.isActive) {
// removeRoute is called every time you dismiss a Snack that is not the top route.
// It will not animate back and listeners will not detect SnackbarStatus.CLOSING or SnackbarStatus.CLOSED
// To avoid this, always make sure that Snack is the top route when it is being dismissed
// removeRoute is called every time you dismiss a Snack that is not
// the top route.
// It will not animate back and listeners will not detect
// SnackbarStatus.CLOSING or SnackbarStatus.CLOSED
// To avoid this, always make sure that Snack is the top
// route when it is being dismissed
_snackRoute.navigator.removeRoute(_snackRoute);
}
... ... @@ -283,6 +274,7 @@ class _GetBarState<K extends Object> extends State<GetBar>
((widget.userInputForm != null ||
((widget.message != null && widget.message.isNotEmpty) ||
widget.messageText != null))),
// ignore: lines_longer_than_80_chars
"A message is mandatory if you are not using userInputForm. Set either a message or messageText");
_isTitlePresent = (widget.title != null || widget.titleText != null);
... ... @@ -320,7 +312,7 @@ class _GetBarState<K extends Object> extends State<GetBar>
final keyContext = backgroundBoxKey.currentContext;
if (keyContext != null) {
final RenderBox box = keyContext.findRenderObject();
final box = keyContext.findRenderObject() as RenderBox;
_boxHeightCompleter.complete(box.size);
}
},
... ... @@ -349,7 +341,7 @@ class _GetBarState<K extends Object> extends State<GetBar>
_fadeController.forward();
}
Function _progressListener;
VoidCallback _progressListener;
void _configureProgressIndicatorAnimation() {
if (widget.showProgressIndicator &&
... ... @@ -403,9 +395,9 @@ class _GetBarState<K extends Object> extends State<GetBar>
return Stack(
children: [
FutureBuilder(
FutureBuilder<Size>(
future: _boxHeightCompleter.future,
builder: (context, AsyncSnapshot<Size> snapshot) {
builder: (context, snapshot) {
if (snapshot.hasData) {
return ClipRRect(
borderRadius: BorderRadius.circular(widget.borderRadius),
... ... @@ -500,7 +492,7 @@ class _GetBarState<K extends Object> extends State<GetBar>
List<Widget> _getAppropriateRowLayout() {
double buttonRightPadding;
double iconPadding = 0;
var iconPadding = 0.0;
if (widget.padding.right - 12 < 0) {
buttonRightPadding = 4;
} else {
... ... @@ -661,9 +653,9 @@ class _GetBarState<K extends Object> extends State<GetBar>
Widget _buildLeftBarIndicator() {
if (widget.leftBarIndicatorColor != null) {
return FutureBuilder(
return FutureBuilder<Size>(
future: _boxHeightCompleter.future,
builder: (BuildContext buildContext, AsyncSnapshot<Size> snapshot) {
builder: (buildContext, snapshot) {
if (snapshot.hasData) {
return Container(
color: widget.leftBarIndicatorColor,
... ... @@ -733,8 +725,11 @@ enum SnackStyle { FLOATING, GROUNDED }
enum SnackDismissDirection { HORIZONTAL, VERTICAL }
/// Indicates Status of snackbar
/// [SnackbarStatus.OPEN] Snack is fully open, [SnackbarStatus.CLOSED] Snackbar has closed,
/// [SnackbarStatus.OPENING] Starts with the opening animation and ends with the full
/// snackbar display, [SnackbarStatus.CLOSING] Starts with the closing animation and ends
/// [SnackbarStatus.OPEN] Snack is fully open, [SnackbarStatus.CLOSED] Snackbar
/// has closed,
/// [SnackbarStatus.OPENING] Starts with the opening animation and ends
/// with the full
/// snackbar display, [SnackbarStatus.CLOSING] Starts with the closing animation
/// and ends
/// with the full snackbar dispose
enum SnackbarStatus { OPEN, CLOSED, OPENING, CLOSING }
... ...
import 'dart:async';
import 'dart:ui';
import 'package:flutter/widgets.dart';
import 'snack.dart';
class SnackRoute<T> extends OverlayRoute<T> {
... ... @@ -11,14 +13,14 @@ class SnackRoute<T> extends OverlayRoute<T> {
@required this.snack,
RouteSettings settings,
}) : super(settings: settings) {
this._builder = Builder(builder: (BuildContext innerContext) {
_builder = Builder(builder: (innerContext) {
return GestureDetector(
child: snack,
onTap: snack.onTap != null ? () => snack.onTap(snack) : null,
);
});
_configureAlignment(this.snack.snackPosition);
_configureAlignment(snack.snackPosition);
_snackbarStatus = snack.snackbarStatus;
}
... ... @@ -56,12 +58,12 @@ class SnackRoute<T> extends OverlayRoute<T> {
@override
Iterable<OverlayEntry> createOverlayEntries() {
List<OverlayEntry> overlays = [];
var overlays = <OverlayEntry>[];
if (snack.overlayBlur > 0.0) {
overlays.add(
OverlayEntry(
builder: (BuildContext context) {
builder: (context) {
return GestureDetector(
onTap: snack.isDismissible ? () => snack.dismiss() : null,
child: AnimatedBuilder(
... ... @@ -81,13 +83,14 @@ class SnackRoute<T> extends OverlayRoute<T> {
);
},
maintainState: false,
opaque: opaque),
opaque: opaque,
),
);
}
overlays.add(
OverlayEntry(
builder: (BuildContext context) {
builder: (context) {
final Widget annotatedChild = Semantics(
child: AlignTransition(
alignment: _animation,
... ... @@ -102,7 +105,8 @@ class SnackRoute<T> extends OverlayRoute<T> {
return annotatedChild;
},
maintainState: false,
opaque: opaque),
opaque: opaque,
),
);
return overlays;
... ... @@ -172,9 +176,9 @@ class SnackRoute<T> extends OverlayRoute<T> {
AnimationController get controller => _controller;
AnimationController _controller;
/// Called to create the animation controller that will drive the transitions to
/// this route from the previous one, and back to the previous route from this
/// one.
/// Called to create the animation controller that will drive the transitions
/// to this route from the previous one, and back to the previous route
/// from this one.
AnimationController createAnimationController() {
assert(!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.');
... ... @@ -286,10 +290,15 @@ class SnackRoute<T> extends OverlayRoute<T> {
@override
TickerFuture didPush() {
super.didPush();
assert(_controller != null,
'$runtimeType.didPush called before calling install() or after calling dispose().');
assert(!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.');
assert(
_controller != null,
// ignore: lines_longer_than_80_chars
'$runtimeType.didPush called before calling install() or after calling dispose().',
);
assert(
!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.',
);
_animation.addStatusListener(_handleStatusChanged);
_configureTimer();
return _controller.forward();
... ... @@ -297,21 +306,34 @@ class SnackRoute<T> extends OverlayRoute<T> {
@override
void didReplace(Route<dynamic> oldRoute) {
assert(_controller != null,
'$runtimeType.didReplace called before calling install() or after calling dispose().');
assert(!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.');
if (oldRoute is SnackRoute) _controller.value = oldRoute._controller.value;
assert(
_controller != null,
// ignore: lines_longer_than_80_chars
'$runtimeType.didReplace called before calling install() or after calling dispose().',
);
assert(
!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.',
);
if (oldRoute is SnackRoute) {
_controller.value = oldRoute._controller.value;
}
_animation.addStatusListener(_handleStatusChanged);
super.didReplace(oldRoute);
}
@override
bool didPop(T result) {
assert(_controller != null,
'$runtimeType.didPop called before calling install() or after calling dispose().');
assert(!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.');
assert(
_controller != null,
// ignore: lines_longer_than_80_chars
'$runtimeType.didPop called before calling install() or after calling dispose().',
);
assert(
!_transitionCompleter.isCompleted,
'Cannot reuse a $runtimeType after disposing it.',
);
_result = result;
_cancelTimer();
... ... @@ -335,9 +357,9 @@ class SnackRoute<T> extends OverlayRoute<T> {
_timer.cancel();
}
_timer = Timer(snack.duration, () {
if (this.isCurrent) {
if (isCurrent) {
navigator.pop();
} else if (this.isActive) {
} else if (isActive) {
navigator.removeRoute(this);
}
});
... ...
... ... @@ -7,8 +7,7 @@ RxInterface getObs;
class _RxImpl<T> implements RxInterface<T> {
StreamController<T> subject = StreamController<T>.broadcast();
HashMap<Stream<T>, StreamSubscription> _subscriptions =
HashMap<Stream<T>, StreamSubscription>();
final _subscriptions = HashMap<Stream<T>, StreamSubscription>();
T _value;
... ... @@ -47,8 +46,10 @@ class _RxImpl<T> implements RxInterface<T> {
// ),
///```
T call([T v]) {
if (v != null) this.value = v;
return this.value;
if (v != null) {
value = v;
}
return value;
}
/// Makes a direct update of [value] adding it to the Stream
... ... @@ -73,8 +74,8 @@ class _RxImpl<T> implements RxInterface<T> {
subject.add(value);
}
/// Uses a callback to update [value] internally, similar to [refresh], but provides
/// the current value as the argument.
/// Uses a callback to update [value] internally, similar to [refresh],
/// but provides the current value as the argument.
/// Makes sense for custom Rx types (like Models).
///
/// Sample:
... ... @@ -105,8 +106,10 @@ class _RxImpl<T> implements RxInterface<T> {
dynamic toJson() => value;
/// This equality override works for _RxImpl instances and the internal values.
/// This equality override works for _RxImpl instances and the internal
/// values.
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
bool operator ==(dynamic o) {
// Todo, find a common implementation for the hashCode of different Types.
if (o is T) return _value == o;
... ... @@ -115,6 +118,7 @@ class _RxImpl<T> implements RxInterface<T> {
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => _value.hashCode;
void close() {
... ...
... ... @@ -23,6 +23,7 @@ abstract class RxInterface<T> {
T get value;
/// Closes the stream
// FIXME: shouldn't we expose the returned future?
void close() => subject?.close();
/// Calls [callback] with current value, when the value changes.
... ... @@ -30,26 +31,31 @@ abstract class RxInterface<T> {
}
/// Unlike GetxController, which serves to control events on each of its pages,
/// GetxService is not automatically disposed (nor can be removed with Get.delete()).
/// It is ideal for situations where, once started, that service will remain in memory,
/// such as Auth control for example. Only way to remove it is Get.reset().
/// GetxService is not automatically disposed (nor can be removed with
/// Get.delete()).
/// It is ideal for situations where, once started, that service will
/// remain in memory, such as Auth control for example. Only way to remove
/// it is Get.reset().
abstract class GetxService extends DisposableInterface {}
/// 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.
/// 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 DisposableInterface {
/// 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.
/// This method should be internal and is required to define the
/// lifetime cycle of the subclass.
final onStart = _InternalFinalCallback<void>();
bool _initialized = false;
... ... @@ -72,16 +78,18 @@ abstract class DisposableInterface {
/// 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.
/// 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() async {}
/// 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.
/// 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() async {}
FutureOr onClose() async {}
}
/// Used like [SingleTickerProviderMixin] but only with Get Controllers.
... ... @@ -89,7 +97,8 @@ abstract class DisposableInterface {
///
/// Example:
///```
///class SplashController extends GetxController with SingleGetTickerProviderMixin {
///class SplashController extends GetxController with
/// SingleGetTickerProviderMixin {
/// AnimationController _ac;
///
/// @override
... ...
import 'dart:async';
import 'dart:math';
import 'package:flutter/foundation.dart';
import '../rx_core/rx_impl.dart';
... ... @@ -27,10 +28,12 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
@override
bool get isNotEmpty => value.isNotEmpty;
StreamController<List<E>> subject = StreamController<List<E>>.broadcast();
Map<Stream<List<E>>, StreamSubscription> _subscriptions = Map();
@override
StreamController<List<E>> subject = StreamController.broadcast();
final Map<Stream<List<E>>, StreamSubscription> _subscriptions = {};
operator []=(int index, E val) {
void operator []=(int index, E val) {
_list[index] = val;
subject.add(_list);
}
... ... @@ -102,7 +105,7 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
/// Returns whether the item was present in the list.
@override
bool remove(Object item) {
bool hasRemoved = _list.remove(item);
final hasRemoved = _list.remove(item);
if (hasRemoved) {
subject.add(_list);
}
... ... @@ -111,14 +114,14 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
@override
E removeAt(int index) {
E item = _list.removeAt(index);
final item = _list.removeAt(index);
subject.add(_list);
return item;
}
@override
E removeLast() {
E item = _list.removeLast();
final item = _list.removeLast();
subject.add(_list);
return item;
}
... ... @@ -148,7 +151,7 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
}
@override
close() {
void close() {
_subscriptions.forEach((observable, subscription) {
subscription.cancel();
});
... ... @@ -183,16 +186,14 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
String get string => value.toString();
addListener(Stream<List<E>> rxGetx) {
if (_subscriptions.containsKey(rxGetx)) {
void addListener(Stream<List<E>> rxGetX) {
if (_subscriptions.containsKey(rxGetX)) {
return;
}
_subscriptions[rxGetx] = rxGetx.listen((data) {
subject.add(data);
});
_subscriptions[rxGetX] = rxGetX.listen(subject.add);
}
set value(Iterable<E> val) {
set value(List<E> val) {
if (_list == val) return;
_list = val;
subject.add(_list);
... ... @@ -200,12 +201,15 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
Stream<List<E>> get stream => subject.stream;
StreamSubscription<List<E>> listen(void Function(List<E>) onData,
{Function onError, void Function() onDone, bool cancelOnError}) =>
StreamSubscription<List<E>> listen(
void Function(List<E>) onData, {
Function onError,
void Function() onDone,
bool cancelOnError,
}) =>
stream.listen(onData, onError: onError, onDone: onDone);
void bindStream(Stream<Iterable<E>> stream) =>
stream.listen((va) => value = va);
void bindStream(Stream<List<E>> stream) => stream.listen((va) => value = va);
@override
E get first => value.first;
... ... @@ -426,9 +430,10 @@ class RxList<E> implements List<E>, RxInterface<List<E>> {
extension ListExtension<E> on List<E> {
RxList<E> get obs {
if (this != null)
if (this != null) {
return RxList<E>(<E>[])..addAllNonNull(this);
else
} else {
return RxList<E>(null);
}
}
}
... ...
import 'dart:async';
import 'package:flutter/foundation.dart';
import '../../../../get.dart';
import '../rx_core/rx_interface.dart';
import '../rx_typedefs/rx_typedefs.dart';
... ... @@ -39,11 +41,11 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> {
}
@override
void addListener(Stream rxGetx) {
if (_subscriptions.containsKey(rxGetx)) {
void addListener(Stream<Map<K, V>> rxGetX) {
if (_subscriptions.containsKey(rxGetX)) {
return;
}
_subscriptions[rxGetx] = rxGetx.listen((data) {
_subscriptions[rxGetX] = rxGetX.listen((data) {
subject.add(data);
});
}
... ... @@ -68,7 +70,7 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> {
subject.add(_value);
}
void addIf(condition, K key, V value) {
void addIf(dynamic condition, K key, V value) {
if (condition is Condition) condition = condition();
if (condition is bool && condition) {
_value[key] = value;
... ... @@ -76,7 +78,7 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> {
}
}
void addAllIf(condition, Map<K, V> values) {
void addAllIf(dynamic condition, Map<K, V> values) {
if (condition is Condition) condition = condition();
if (condition is bool && condition) addAll(values);
}
... ... @@ -185,9 +187,10 @@ class RxMap<K, V> implements RxInterface<Map<K, V>>, Map<K, V> {
extension MapExtension<K, V> on Map<K, V> {
RxMap<K, V> get obs {
if (this != null)
if (this != null) {
return RxMap<K, V>(<K, V>{})..addAll(this);
else
} else {
return RxMap<K, V>(null);
}
}
}
... ...
... ... @@ -11,7 +11,7 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
_set = initial;
}
RxSet<E> _set = Set<E>();
Set<E> _set = <E>{};
@override
Iterator<E> get iterator => value.iterator;
... ... @@ -27,28 +27,23 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
bool get isNotEmpty => value.isNotEmpty;
StreamController<Set<E>> subject = StreamController<Set<E>>.broadcast();
Map<Stream<Set<E>>, StreamSubscription> _subscriptions = Map();
final Map<Stream<Set<E>>, StreamSubscription> _subscriptions = {};
/// Adds [item] only if [condition] resolves to true.
void addIf(condition, E item) {
void addIf(dynamic condition, E item) {
if (condition is Condition) condition = condition();
if (condition is bool && condition) add(item);
}
/// Adds all [items] only if [condition] resolves to true.
void addAllIf(condition, Iterable<E> items) {
void addAllIf(dynamic condition, Iterable<E> items) {
if (condition is Condition) condition = condition();
if (condition is bool && condition) addAll(items);
}
operator []=(int index, E val) {
_set[index] = val;
subject.add(_set);
}
/// Special override to push() element(s) in a reactive way
/// inside the List,
RxSet<E> operator +(Iterable<E> val) {
RxSet<E> operator +(Set<E> val) {
addAll(val);
subject.add(_set);
return this;
... ... @@ -61,6 +56,7 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
return val;
}
@override
void addAll(Iterable<E> item) {
_set.addAll(item);
subject.add(_set);
... ... @@ -76,16 +72,6 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
if (item != null) addAll(item);
}
void insert(int index, E item) {
_set.insert(index, item);
subject.add(_set);
}
void insertAll(int index, Iterable<E> iterable) {
_set.insertAll(index, iterable);
subject.add(_set);
}
int get length => value.length;
/// Removes an item from the list.
... ... @@ -94,30 +80,13 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
///
/// Returns whether the item was present in the list.
bool remove(Object item) {
bool hasRemoved = _set.remove(item);
var hasRemoved = _set.remove(item);
if (hasRemoved) {
subject.add(_set);
}
return hasRemoved;
}
E removeAt(int index) {
E item = _set.removeAt(index);
subject.add(_set);
return item;
}
E removeLast() {
E item = _set.removeLast();
subject.add(_set);
return item;
}
void removeRange(int start, int end) {
_set.removeRange(start, end);
subject.add(_set);
}
void removeWhere(bool Function(E) test) {
_set.removeWhere(test);
subject.add(_set);
... ... @@ -128,12 +97,7 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
subject.add(_set);
}
void sort([int compare(E a, E b)]) {
_set.sort();
subject.add(_set);
}
close() {
void close() {
_subscriptions.forEach((observable, subscription) {
subscription.cancel();
});
... ... @@ -168,16 +132,16 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
String get string => value.toString();
addListener(Stream<Set<E>> rxGetx) {
if (_subscriptions.containsKey(rxGetx)) {
void addListener(Stream<Set<E>> rxGetX) {
if (_subscriptions.containsKey(rxGetX)) {
return;
}
_subscriptions[rxGetx] = rxGetx.listen((data) {
_subscriptions[rxGetX] = rxGetX.listen((data) {
subject.add(data);
});
}
set value(Iterable<E> val) {
set value(Set<E> val) {
if (_set == val) return;
_set = val;
subject.add(_set);
... ... @@ -189,8 +153,7 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
{Function onError, void Function() onDone, bool cancelOnError}) =>
stream.listen(onData, onError: onError, onDone: onDone);
void bindStream(Stream<Iterable<E>> stream) =>
stream.listen((va) => value = va);
void bindStream(Stream<Set<E>> stream) => stream.listen((va) => value = va);
@override
E get first => value.first;
... ... @@ -362,9 +325,10 @@ class RxSet<E> implements Set<E>, RxInterface<Set<E>> {
extension SetExtension<E> on Set<E> {
RxSet<E> get obs {
if (this != null)
if (this != null) {
return RxSet<E>(<E>{})..addAllNonNull(this);
else
} else {
return RxSet<E>(null);
}
}
}
... ...
typedef bool Condition();
typedef Condition = bool Function();
typedef ValueCallback<T> = Function(T v);
... ...
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import '../../../instance/get_instance.dart';
import '../../../navigation/root/smart_management.dart';
import '../rx_core/rx_impl.dart';
import '../rx_core/rx_interface.dart';
class GetX<T extends DisposableInterface> extends StatefulWidget {
final Widget Function(T) builder;
final bool global;
// final Stream Function(T) stream;
// final StreamController Function(T) streamController;
final bool autoRemove;
... ... @@ -16,6 +18,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
final void Function(State state) initState, dispose, didChangeDependencies;
final void Function(GetX oldWidget, State state) didUpdateWidget;
final T init;
const GetX({
this.builder,
this.global = true,
... ... @@ -29,6 +32,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
this.init,
// this.streamController
});
GetImplXState<T> createState() => GetImplXState<T>();
}
... ... @@ -41,8 +45,9 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
@override
void initState() {
_observer = Rx();
bool isPrepared = GetInstance().isPrepared<T>();
bool isRegistered = GetInstance().isRegistered<T>();
var isPrepared = GetInstance().isPrepared<T>();
var isRegistered = GetInstance().isRegistered<T>();
if (widget.global) {
if (isPrepared) {
if (GetConfig.smartManagement != SmartManagement.keepFactory) {
... ...
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/src/state_manager/rx/rx_core/rx_interface.dart';
import '../rx_core/rx_impl.dart';
import '../rx_core/rx_interface.dart';
typedef WidgetCallback = Widget Function();
... ... @@ -16,6 +18,7 @@ class Obx extends StatefulWidget {
final WidgetCallback builder;
const Obx(this.builder);
_ObxState createState() => _ObxState();
}
... ... @@ -74,7 +77,8 @@ class _ObxState extends State<Obx> {
/// false.obs,
/// ),
// TODO: change T to a proper Rx interface, that includes the accessor for ::value
// TODO: change T to a proper Rx interface, that includes the accessor
// for ::value
class ObxValue<T extends RxInterface> extends StatefulWidget {
final Widget Function(T) builder;
final T data;
... ...
import 'dart:async';
import 'package:get/get.dart';
import '../../../../get.dart';
import '../rx_core/rx_interface.dart';
import 'utils/debouncer.dart';
... ... @@ -16,13 +17,15 @@ Worker ever<T>(RxInterface<T> listener, Function(T) callback,
return Worker(cancel, '[ever]');
}
Worker everAll(List<RxInterface> listener, Function(dynamic) callback,
Worker everAll(List<RxInterface> listeners, Function(dynamic) callback,
{bool condition = true}) {
List<StreamSubscription> evers = <StreamSubscription>[];
var evers = <StreamSubscription>[];
for (var i in listener) {
StreamSubscription sub = i.subject.stream.listen((event) {
if (condition) callback(event);
for (final listener in listeners) {
final sub = listener.subject.stream.listen((event) {
if (condition) {
callback(event);
}
});
evers.add(sub);
}
... ... @@ -37,23 +40,26 @@ Worker everAll(List<RxInterface> listener, Function(dynamic) callback,
return Worker(cancel, '[everAll]');
}
Worker once<T>(RxInterface<T> listener, Function(T) callback,
{bool condition = true}) {
StreamSubscription sub;
int times = 0;
Worker once<T>(
RxInterface<T> listener,
Function(T) callback, {
bool condition = true,
}) {
StreamSubscription subscription;
var times = 0;
sub = listener.subject.stream.listen((event) {
subscription = listener.subject.stream.listen((event) {
if (!condition) return null;
times++;
if (times < 2) {
callback(event);
} else {
sub.cancel();
subscription.cancel();
}
});
Future<void> cancel() {
return sub.cancel();
return subscription.cancel();
}
return Worker(cancel, '[once]');
... ... @@ -61,7 +67,7 @@ Worker once<T>(RxInterface<T> listener, Function(T) callback,
Worker interval<T>(RxInterface<T> listener, Function(T) callback,
{Duration time, bool condition = true}) {
bool debounceActive = false;
var debounceActive = false;
StreamSubscription sub = listener.subject.stream.listen((event) async {
if (debounceActive || !condition) return null;
debounceActive = true;
... ...
import 'dart:collection';
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_core/rx_interface.dart';
import 'package:get/state_manager.dart';
import '../../../state_manager.dart';
import '../../instance/get_instance.dart';
import '../../navigation/root/smart_management.dart';
import '../rx/rx_core/rx_interface.dart';
import 'simple_builder.dart';
typedef Disposer = void Function();
... ... @@ -18,12 +18,19 @@ class GetxController extends DisposableInterface {
/// Update GetBuilder with update();
void update([List<String> ids, bool condition = true]) {
if (!condition) return;
(ids == null)
? _updaters.forEach((rs) => rs(() {}))
: ids.forEach((element) {
_updatersIds[element]?.call(() {});
});
if (!condition) {
return;
}
if (ids == null) {
for (final updater in _updaters) {
updater(() {});
}
} else {
for (final id in ids) {
_updatersIds[id]?.call(() {});
}
}
}
Disposer addListener(StateSetter listener) {
... ... @@ -53,6 +60,7 @@ class GetBuilder<T extends GetxController> extends StatefulWidget {
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,
... ... @@ -68,12 +76,13 @@ class GetBuilder<T extends GetxController> extends StatefulWidget {
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;
T controller;
bool isCreator = false;
final HashSet<Disposer> disposers = HashSet<Disposer>();
Disposer remove;
... ... @@ -129,9 +138,9 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
if (remove != null) remove();
}
disposers.forEach((element) {
element();
});
for (final disposer in disposers) {
disposer();
}
}
@override
... ... @@ -157,6 +166,7 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
/// like Rx() does with Obx().
class Value<T> extends GetxController {
Value([this._value]);
T _value;
T get value {
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import '../../instance/get_instance.dart';
/// GetView is a great way of quickly access your Controller
/// without having to call Get.find<AwesomeController>() yourself.
... ... @@ -22,6 +23,7 @@ import 'package:get/src/instance/get_instance.dart';
///``
abstract class GetView<T> extends StatelessWidget {
const GetView({Key key}) : super(key: key);
T get controller => GetInstance().find<T>();
@override
... ... @@ -31,7 +33,7 @@ abstract class GetView<T> extends StatelessWidget {
abstract class GetWidget<T> extends StatelessWidget {
GetWidget({Key key}) : super(key: key);
final Set<T> _value = Set<T>();
final Set<T> _value = <T>{};
T get controller {
if (_value.isEmpty) _value.add(GetInstance().find<T>());
... ...
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:get/src/instance/get_instance.dart';
// import 'package:get/state_manager.dart';
// abstract class GetState<T> extends DisposableInterface {
//import 'package:flutter/foundation.dart';
//import 'package:flutter/material.dart';
//import 'package:get/state_manager.dart';
//
//import '../../instance/get_instance.dart';
//
//abstract class GetState<T> extends DisposableInterface {
// GetState(this.initialValue) {
// _state = initialValue;
// }
// final Set<StateSetter> _updaters = Set<StateSetter>();
//
// final Set<StateSetter> _updaters = <StateSetter>{};
//
// @protected
// void update(T value, [bool condition = true]) {
// if (!condition) return;
// _state = value;
// _updaters.forEach((rs) => rs(() {}));
// }
//
// T _state;
//
// final T initialValue;
//
// void addListener(StateSetter value) {
// _updaters.add(value);
// }
//
// void removeListener(StateSetter value) {
// _updaters.add(value);
// }
//
// // @protected
// T get state => _state;
//
// @protected
// void updater(void fn(T value)) {
// fn(_state);
// update(_state);
// }
// }
// class StateBuilder<T extends GetState> extends StatefulWidget {
//}
//
//class StateBuilder<T extends GetState> extends StatefulWidget {
// final Widget Function(dynamic) builder;
// final bool global;
// final String tag;
... ... @@ -48,6 +49,7 @@
// final void Function(State state) initState, dispose, didChangeDependencies;
// final void Function(StateBuilder oldWidget, State state) didUpdateWidget;
// final T Function() state;
//
// const StateBuilder({
// Key key,
// this.state,
... ... @@ -62,14 +64,16 @@
// this.didUpdateWidget,
// }) : assert(builder != null),
// super(key: key);
//
// @override
// _StateBuilderState<T> createState() => _StateBuilderState<T>();
// }
// class _StateBuilderState<T extends GetState> extends State<StateBuilder<T>> {
//}
//
//class _StateBuilderState<T extends GetState> extends State<StateBuilder<T>> {
// T controller;
//
// bool isCreator = false;
//
// @override
// void initState() {
// super.initState();
... ... @@ -77,7 +81,7 @@
// if (widget.global) {
// final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
// final isRegistred = GetInstance().isRegistred<T>(tag: widget.tag);
//
// if (isPrepared) {
// isCreator = true;
// } else if (isRegistred) {
... ... @@ -85,12 +89,15 @@
// } else {
// isCreator = true;
// }
//
// if (isCreator) {
// controller?.onStart();
// }
// final instance = GetInstance().putOrFind(widget.state, tag: widget.tag);
//
// final instance = GetInstance().putOrFind(
// widget.state,
// tag: widget.tag,
// );
// controller = instance;
// controller._updaters.add(setState);
// } else {
... ... @@ -100,13 +107,16 @@
// controller?.onStart();
// }
// }
//
// @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)) {
// if (widget.autoRemove &&
// GetInstance().isRegistred<T>(
// tag: widget.tag,
// )) {
// controller._updaters.remove(setState);
// GetInstance().delete<T>(tag: widget.tag);
// }
... ... @@ -114,7 +124,7 @@
// controller._updaters.remove(setState);
// }
// }
//
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
... ... @@ -122,15 +132,17 @@
// widget.didChangeDependencies(this);
// }
// }
//
// @override
// void didUpdateWidget(StateBuilder oldWidget) {
// super.didUpdateWidget(oldWidget as StateBuilder<T>);
// if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
// if (widget.didUpdateWidget != null) {
// widget.didUpdateWidget(oldWidget, this);
// }
// }
//
// @override
// Widget build(BuildContext context) {
// return widget.builder(controller.state);
// }
// }
//}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/state_manager/rx/rx_widgets/rx_obx_widget.dart';
import '../rx/rx_widgets/rx_obx_widget.dart';
import 'get_state.dart';
class MixinBuilder<T extends GetxController> extends StatelessWidget {
... ... @@ -11,6 +12,7 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget {
final void Function(State state) initState, dispose, didChangeDependencies;
final void Function(GetBuilder oldWidget, State state) didUpdateWidget;
final T init;
const MixinBuilder({
Key key,
this.init,
... ...
... ... @@ -9,7 +9,8 @@ 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.
/// Manages a local state like ObxValue, but uses a callback instead of
/// a Rx value.
///
/// Example:
/// ```
... ... @@ -25,7 +26,7 @@ typedef ValueBuilderBuilder<T> = Widget Function(
/// ```
class ValueBuilder<T> extends StatefulWidget {
final T initialValue;
final ValueBuilderBuilder builder;
final ValueBuilderBuilder<T> builder;
final void Function() onDispose;
final void Function(T) onUpdate;
... ... @@ -78,9 +79,11 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T>> {
// 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();
}
... ... @@ -91,25 +94,33 @@ class _SimpleBuilderState extends State<SimpleBuilder> {
@override
void dispose() {
super.dispose();
disposers.forEach((element) => element());
for (final disposer in disposers) {
disposer();
}
}
@override
Widget build(BuildContext context) {
return TaskManager.instance
.exchange(disposers, setState, widget.builder, 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) {
void notify(HashSet<StateSetter> _updaters) {
if (_setter != null) {
if (!_updaters.contains(_setter)) {
_updaters.add(_setter);
... ...
import 'package:flutter/foundation.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]
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)
/// 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)
/// 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
/// [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%.
... ... @@ -32,9 +34,9 @@ extension ContextExtensionss on BuildContext {
/// 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
/// [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%.
... ... @@ -105,7 +107,8 @@ extension ContextExtensionss on BuildContext {
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 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.
... ... @@ -116,7 +119,7 @@ extension ContextExtensionss on BuildContext {
T desktop,
T watch,
}) {
double deviceWidth = mediaQuerySize.shortestSide;
var deviceWidth = mediaQuerySize.shortestSide;
if (kIsWeb) {
deviceWidth = mediaQuerySize.width;
... ...
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import '../../../get.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)
/// 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)
/// 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
/// [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%.
... ... @@ -32,9 +35,9 @@ extension ContextExtensionss on BuildContext {
/// 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
/// [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%.
... ... @@ -105,9 +108,9 @@ extension ContextExtensionss on BuildContext {
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 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>({
... ... @@ -116,7 +119,7 @@ extension ContextExtensionss on BuildContext {
T desktop,
T watch,
}) {
double deviceWidth = mediaQuerySize.shortestSide;
var deviceWidth = mediaQuerySize.shortestSide;
if (GetPlatform.isDesktop) {
deviceWidth = mediaQuerySize.width;
}
... ...
... ... @@ -2,7 +2,7 @@ import 'dart:math';
extension Precision on double {
double toPrecision(int fractionDigits) {
double mod = pow(10, fractionDigits.toDouble());
var mod = pow(10, fractionDigits.toDouble()).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.
/// 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);
}
... ...
... ... @@ -4,7 +4,9 @@ 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);
/// Utility to delay some callback (or code execution).
... ... @@ -34,11 +36,15 @@ extension GetNumUtils on num {
/// print(1.5.hours);
///```
Duration get milliseconds => Duration(microseconds: (this * 1000).round());
Duration get seconds => Duration(milliseconds: (this * 1000).round());
Duration get minutes =>
Duration(seconds: (this * Duration.secondsPerMinute).round());
Duration get hours =>
Duration(minutes: (this * Duration.minutesPerHour).round());
Duration get days => Duration(hours: (this * Duration.hoursPerDay).round());
//final _delayMaps = <Function, Future>{};
... ...
... ... @@ -2,45 +2,82 @@ 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.isWord(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 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 'platform_web.dart' if (dart.library.io) 'platform_io.dart';
// ignore: avoid_classes_with_only_static_members
class GetPlatform {
static bool get isWeb => GeneralPlatform.isWeb;
static bool get isMacOS => GeneralPlatform.isMacOS;
static bool get isWindows => GeneralPlatform.isWindows;
static bool get isLinux => GeneralPlatform.isLinux;
static bool get isAndroid => GeneralPlatform.isAndroid;
static bool get isIOS => GeneralPlatform.isIOS;
static bool get isFuchsia => GeneralPlatform.isFuchsia;
static bool get isMobile => GetPlatform.isIOS || GetPlatform.isAndroid;
static bool get isDesktop =>
GetPlatform.isMacOS || GetPlatform.isWindows || GetPlatform.isLinux;
}
... ...
import 'dart:io';
// ignore: avoid_classes_with_only_static_members
class GeneralPlatform {
static bool get isWeb => false;
static bool get isMacOS => Platform.isMacOS;
static bool get isWindows => Platform.isWindows;
static bool get isLinux => Platform.isLinux;
static bool get isAndroid => Platform.isAndroid;
static bool get isIOS => Platform.isIOS;
static bool get isFuchsia => Platform.isFuchsia;
static bool get isDesktop =>
Platform.isMacOS || Platform.isWindows || Platform.isLinux;
}
... ...
... ... @@ -2,10 +2,11 @@
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
import 'package:get/utils.dart';
import '../../../utils.dart';
html.Navigator _navigator = html.window.navigator;
// ignore: avoid_classes_with_only_static_members
class GeneralPlatform {
static bool get isWeb => true;
... ... @@ -29,5 +30,6 @@ class GeneralPlatform {
}
static bool get isFuchsia => false;
static bool get isDesktop => isMacOS || isWindows || isLinux;
}
... ...
... ... @@ -10,7 +10,7 @@ class GetQueue {
var item = _queue.removeAt(0);
try {
item.completer.complete(await item.job());
} catch (e) {
} on Exception catch (e) {
item.completer.completeError(e);
}
_active = false;
... ... @@ -27,7 +27,8 @@ class GetQueue {
}
class _Item {
final completer;
final job;
final dynamic completer;
final dynamic job;
_Item(this.completer, this.job);
}
... ...
... ... @@ -4,22 +4,23 @@ class GetUtils {
/// In dart2js (in flutter v1.17) a var by default is undefined.
/// *Use this only if you are in version <- 1.17*.
/// So we assure the null type in json convertions to avoid the "value":value==null?null:value;
/// someVar.nil will force the null type if the var is null or undefined.
/// So we assure the null type in json convertions to avoid the
/// "value":value==null?null:value; someVar.nil will force the null type
/// if the var is null or undefined.
/// `nil` taken from ObjC just to have a shorter sintax.
static dynamic nil(dynamic s) => s == null ? null : s;
/// Checks if data is null or blank (empty or only contains whitespace).
static bool isNullOrBlank(dynamic s) {
if (isNull(s)) return true;
switch (s.runtimeType) {
switch (s.runtimeType as Type) {
case String:
case List:
case Map:
case Set:
case Iterable:
return s.isEmpty;
break;
return s.isEmpty as bool;
default:
return s.toString() == 'null' || s.toString().trim().isEmpty;
}
... ... @@ -46,48 +47,54 @@ class GetUtils {
/// Checks if string is an video file.
static bool isVideo(String filePath) {
String ext = filePath.toLowerCase();
return (((((ext.endsWith(".mp4") || ext.endsWith(".avi")) ||
ext.endsWith(".wmv")) ||
ext.endsWith(".rmvb")) ||
ext.endsWith(".mpg")) ||
ext.endsWith(".mpeg")) ||
var ext = filePath.toLowerCase();
return ext.endsWith(".mp4") ||
ext.endsWith(".avi") ||
ext.endsWith(".wmv") ||
ext.endsWith(".rmvb") ||
ext.endsWith(".mpg") ||
ext.endsWith(".mpeg") ||
ext.endsWith(".3gp");
}
/// Checks if string is an image file.
static bool isImage(String filePath) {
String ext = filePath.toLowerCase();
return (((ext.endsWith(".jpg") || ext.endsWith(".jpeg")) ||
ext.endsWith(".png")) ||
ext.endsWith(".gif")) ||
final ext = filePath.toLowerCase();
return ext.endsWith(".jpg") ||
ext.endsWith(".jpeg") ||
ext.endsWith(".png") ||
ext.endsWith(".gif") ||
ext.endsWith(".bmp");
}
/// Checks if string is an audio file.
static bool isAudio(String filePath) {
String ext = filePath.toLowerCase();
return (((ext.endsWith(".mp3") || ext.endsWith(".wav")) ||
ext.endsWith(".wma")) ||
ext.endsWith(".amr")) ||
final ext = filePath.toLowerCase();
return ext.endsWith(".mp3") ||
ext.endsWith(".wav") ||
ext.endsWith(".wma") ||
ext.endsWith(".amr") ||
ext.endsWith(".ogg");
}
/// Checks if string is an powerpoint file.
static bool isPPT(String filePath) {
String ext = filePath.toLowerCase();
final ext = filePath.toLowerCase();
return ext.endsWith(".ppt") || ext.endsWith(".pptx");
}
/// Checks if string is an word file.
static bool isWord(String filePath) {
String ext = filePath.toLowerCase();
final ext = filePath.toLowerCase();
return ext.endsWith(".doc") || ext.endsWith(".docx");
}
/// Checks if string is an excel file.
static bool isExcel(String filePath) {
String ext = filePath.toLowerCase();
final ext = filePath.toLowerCase();
return ext.endsWith(".xls") || ext.endsWith(".xlsx");
}
... ... @@ -174,9 +181,11 @@ class GetUtils {
/// Checks if string is Palindrom.
static bool isPalindrom(String s) {
bool isPalindrom = true;
var isPalindrom = true;
for (var i = 0; i < s.length; i++) {
if (s[i] != s[s.length - i - 1]) isPalindrom = false;
if (s[i] != s[s.length - i - 1]) {
isPalindrom = false;
}
}
return isPalindrom;
}
... ... @@ -187,13 +196,15 @@ class GetUtils {
if ((s is String || s is List) && !isNullOrBlank(s)) {
var first = s[0];
var isOneAKind = true;
for (var i = 0; i < s.length; i++) {
var len = s.length as num;
for (var i = 0; i < len; i++) {
if (s[i] != first) isOneAKind = false;
}
return isOneAKind;
}
if (s is int) {
String value = s.toString();
var value = s.toString();
var first = value[0];
var isOneAKind = true;
for (var i = 0; i < value.length; i++) {
... ... @@ -215,20 +226,17 @@ class GetUtils {
/// Checks if length of data is LOWER than maxLength.
static bool isLengthLowerThan(dynamic s, int maxLength) {
if (isNull(s)) return (maxLength <= 0) ? true : false;
switch (s.runtimeType) {
switch (s.runtimeType as Type) {
case String:
case List:
case Map:
case Set:
case Iterable:
return s.length < maxLength;
break;
return (s.length as num) < maxLength;
case int:
return s.toString().length < maxLength;
break;
case double:
return s.toString().replaceAll('.', '').length < maxLength;
break;
default:
return false;
}
... ... @@ -237,20 +245,17 @@ class GetUtils {
/// Checks if length of data is GREATER than maxLength.
static bool isLengthGreaterThan(dynamic s, int maxLength) {
if (isNull(s)) return false;
switch (s.runtimeType) {
switch (s.runtimeType as Type) {
case String:
case List:
case Map:
case Set:
case Iterable:
return s.length > maxLength;
break;
return (s.length as num) > maxLength;
case int:
return s.toString().length > maxLength;
break;
case double:
return s.toString().replaceAll('.', '').length > maxLength;
break;
default:
return false;
}
... ... @@ -259,13 +264,13 @@ class GetUtils {
/// Checks if length of data is GREATER OR EQUAL to maxLength.
static bool isLengthGreaterOrEqual(dynamic s, int maxLength) {
if (isNull(s)) return false;
switch (s.runtimeType) {
switch (s.runtimeType as Type) {
case String:
case List:
case Map:
case Set:
case Iterable:
return s.length >= maxLength;
return (s.length as num) >= maxLength;
break;
case int:
return s.toString().length >= maxLength;
... ... @@ -281,17 +286,15 @@ class GetUtils {
/// Checks if length of data is LOWER OR EQUAL to maxLength.
static bool isLengthLowerOrEqual(dynamic s, int maxLength) {
if (isNull(s)) return false;
switch (s.runtimeType) {
switch (s.runtimeType as Type) {
case String:
case List:
case Map:
case Set:
case Iterable:
return s.length <= maxLength;
break;
return (s.length as num) <= maxLength;
case int:
return s.toString().length <= maxLength;
break;
case double:
return s.toString().replaceAll('.', '').length <= maxLength;
default:
... ... @@ -302,7 +305,7 @@ class GetUtils {
/// Checks if length of data is EQUAL to maxLength.
static bool isLengthEqualTo(dynamic s, int maxLength) {
if (isNull(s)) return false;
switch (s.runtimeType) {
switch (s.runtimeType as Type) {
case String:
case List:
case Map:
... ... @@ -328,14 +331,16 @@ class GetUtils {
isLengthLowerOrEqual(s, maxLength);
}
/// Checks if a contains b (Treating or interpreting upper- and lowercase letters as being the same).
/// Checks if a contains b (Treating or interpreting upper- and lowercase
/// letters as being the same).
static bool isCaseInsensitiveContains(String a, String b) =>
a.toLowerCase().contains(b.toLowerCase());
/// Checks if a contains b or b contains a (Treating or interpreting upper- and lowercase letters as being the same).
/// Checks if a contains b or b contains a (Treating or
/// interpreting upper- and lowercase letters as being the same).
static bool isCaseInsensitiveContainsAny(String a, String b) {
String lowA = a.toLowerCase();
String lowB = b.toLowerCase();
final lowA = a.toLowerCase();
final lowB = b.toLowerCase();
return lowA.contains(lowB) || lowB.contains(lowA);
}
... ... @@ -362,8 +367,7 @@ class GetUtils {
if (RegExp(r'^(\d)\1*$').hasMatch(numbers)) return false;
// Dividir dígitos
List<int> digits =
numbers.split('').map((String d) => int.parse(d)).toList();
var digits = numbers.split('').map(int.parse).toList();
// Calcular o primeiro dígito verificador
var calcDv1 = 0;
... ... @@ -404,8 +408,7 @@ class GetUtils {
if (RegExp(r'^(\d)\1*$').hasMatch(numbers)) return false;
// split the digits
List<int> digits =
numbers.split('').map((String d) => int.parse(d)).toList();
var digits = numbers.split('').map(int.parse).toList();
// Calculate the first verifier digit
var calcDv1 = 0;
... ... @@ -441,9 +444,11 @@ class GetUtils {
if (isNullOrBlank(s)) return null;
if (firstOnly) return capitalizeFirst(s);
List lst = s.split(' ');
String newStr = '';
for (var s in lst) newStr += capitalizeFirst(s);
var lst = s.split(' ');
var newStr = '';
for (var s in lst) {
newStr += capitalizeFirst(s);
}
return newStr;
}
... ... @@ -470,9 +475,10 @@ class GetUtils {
/// Extract numeric value of string
/// Example: OTP 12312 27/04/2020 => 1231227042020ß
/// If firstword only is true, then the example return is "12312" (first found numeric word)
/// If firstword only is true, then the example return is "12312"
/// (first found numeric word)
static String numericOnly(String s, {bool firstWordOnly = false}) {
String numericOnlyStr = '';
var numericOnlyStr = '';
for (var i = 0; i < s.length; i++) {
if (isNumericOnly(s[i])) numericOnlyStr += s[i];
if (firstWordOnly && numericOnlyStr.isNotEmpty && s[i] == " ") break;
... ... @@ -480,6 +486,7 @@ class GetUtils {
return numericOnlyStr;
}
static bool hasMatch(String s, Pattern p) =>
(s == null) ? false : RegExp(p).hasMatch(s);
static bool hasMatch(String value, String pattern) {
return (value == null) ? false : RegExp(pattern).hasMatch(value);
}
}
... ...
... ... @@ -2,56 +2,96 @@ import '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.isWord(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 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);
}
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);
}
extension GetDynamicUtils on dynamic {
bool get isNull => GetUtils.isNull(this);
bool get isNullOrBlank => GetUtils.isNullOrBlank(this);
}
... ...
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_core/rx_interface.dart';
export 'src/state_manager/rx/rx_core/rx_impl.dart';
export 'src/state_manager/rx/rx_core/rx_interface.dart';
export 'src/state_manager/rx/rx_iterables/rx_list.dart';
export 'src/state_manager/rx/rx_iterables/rx_map.dart';
export 'src/state_manager/rx/rx_iterables/rx_set.dart';
export 'src/state_manager/rx/rx_workers/rx_workers.dart';
export 'src/state_manager/rx/rx_widgets/rx_obx_widget.dart';
export 'src/state_manager/rx/rx_widgets/rx_getx_widget.dart';
export 'src/state_manager/rx/rx_widgets/rx_obx_widget.dart';
export 'src/state_manager/rx/rx_workers/rx_workers.dart';
export 'src/state_manager/simple/get_state.dart';
export 'src/state_manager/simple/get_view.dart';
export 'src/state_manager/simple/immutable_state.dart';
export 'src/state_manager/simple/mixin_state.dart';
export 'src/state_manager/simple/simple_builder.dart';
... ...
export 'src/utils/extensions/export.dart';
export 'src/utils/queue/get_queue.dart';
export 'src/utils/platform/platform.dart';
export 'src/utils/queue/get_queue.dart';
export 'src/utils/regex/get_utils.dart';
... ...
... ... @@ -43,6 +43,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0-nullsafety.2"
effective_dart:
dependency: "direct dev"
description:
name: effective_dart
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.4"
fake_async:
dependency: transitive
description:
... ...
... ... @@ -13,6 +13,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
effective_dart: ^1.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
... ...
... ... @@ -61,12 +61,13 @@ void main() {
testWidgets(
"GetMaterialApp with debugShowMaterialGrid null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
debugShowMaterialGrid: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
}
... ...
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'util/matcher.dart';
class Mock {
... ... @@ -19,6 +20,7 @@ class DisposableController extends DisposableInterface {
}
}
// ignore: one_member_abstracts
abstract class Service {
String post();
}
... ... @@ -32,7 +34,7 @@ class Api implements Service {
void main() {
test('Get.putAsync test', () async {
await Get.putAsync<String>(() => Mock.test());
await Get.putAsync<String>(Mock.test);
expect('test', Get.find<String>());
Get.reset();
});
... ... @@ -70,9 +72,7 @@ void main() {
});
group('test put, delete and check onInit execution', () {
tearDownAll(() {
Get.reset();
});
tearDownAll(Get.reset);
test('Get.put test with init check', () async {
final instance = Get.put<DisposableController>(DisposableController());
... ...
... ... @@ -202,8 +202,9 @@ void main() {
expect(find.byType(FirstScreen), findsOneWidget);
Get.offUntil(
MaterialPageRoute(builder: (BuildContext context) => SecondScreen()),
ModalRoute.withName('/'));
MaterialPageRoute(builder: (context) => SecondScreen()),
ModalRoute.withName('/'),
);
await tester.pumpAndSettle();
... ...
... ... @@ -66,13 +66,14 @@ void main() {
testWidgets(
"MixinBuilder with build null",
(WidgetTester tester) async {
(tester) async {
expect(
() => MixinBuilder<Controller>(
init: Controller(),
builder: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
}
... ... @@ -80,12 +81,12 @@ void main() {
class Controller extends GetxController {
static Controller get to => Get.find();
int count = 0;
var counter = 0.obs;
var doubleNum = 0.0.obs;
var string = "string".obs;
var list = [].obs;
var map = {}.obs;
var boolean = true.obs;
RxInt counter = 0.obs;
RxDouble doubleNum = 0.0.obs;
RxString string = "string".obs;
RxList list = [].obs;
RxMap map = {}.obs;
RxBool boolean = true.obs;
void increment() {
counter.value++;
... ...
... ... @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
void main() {
Controller controller = Get.put<Controller>(Controller());
final controller = Get.put(Controller());
testWidgets("GetxController smoke test", (tester) async {
await tester.pumpWidget(
MaterialApp(
... ... @@ -11,31 +11,17 @@ void main() {
children: [
Obx(
() => Column(children: [
Text(
'Count: ${controller.counter.value}',
),
Text(
'Double: ${controller.doubleNum.value}',
),
Text(
'String: ${controller.string.value}',
),
Text(
'List: ${controller.list.length}',
),
Text(
'Bool: ${controller.boolean.value}',
),
Text(
'Map: ${controller.map.length}',
),
Text('Count: ${controller.counter.value}'),
Text('Double: ${controller.doubleNum.value}'),
Text('String: ${controller.string.value}'),
Text('List: ${controller.list.length}'),
Text('Bool: ${controller.boolean.value}'),
Text('Map: ${controller.map.length}'),
FlatButton(
child: Text("increment"),
onPressed: () => controller.increment(),
onPressed: controller.increment,
),
Obx(() => Text(
'Obx: ${controller.map.length}',
))
Obx(() => Text('Obx: ${controller.map.length}'))
]),
),
],
... ... @@ -68,12 +54,12 @@ void main() {
class Controller extends GetxController {
static Controller get to => Get.find();
var counter = 0.obs;
var doubleNum = 0.0.obs;
var string = "string".obs;
var list = [].obs;
var map = {}.obs;
var boolean = true.obs;
RxInt counter = 0.obs;
RxDouble doubleNum = 0.0.obs;
RxString string = "string".obs;
RxList list = [].obs;
RxMap map = {}.obs;
RxBool boolean = true.obs;
void increment() {
counter.value++;
... ...
... ... @@ -74,22 +74,22 @@ void main() {
}
class Controller2 extends GetxController {
var lazy = 0.obs;
RxInt lazy = 0.obs;
}
class ControllerNonGlobal extends GetxController {
var nonGlobal = 0.obs;
RxInt nonGlobal = 0.obs;
}
class Controller extends GetxController {
static Controller get to => Get.find();
var counter = 0.obs;
var doubleNum = 0.0.obs;
var string = "string".obs;
var list = [].obs;
var map = {}.obs;
var boolean = true.obs;
RxInt counter = 0.obs;
RxDouble doubleNum = 0.0.obs;
RxString string = "string".obs;
RxList list = [].obs;
RxMap map = {}.obs;
RxBool boolean = true.obs;
void increment() {
counter.value++;
... ...
... ... @@ -70,13 +70,14 @@ void main() {
testWidgets(
"MixinBuilder with build null",
(WidgetTester test) async {
(test) async {
expect(
() => GetBuilder<Controller>(
init: Controller(),
builder: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
}
... ... @@ -85,6 +86,7 @@ class Controller extends GetxController {
static Controller get to => Get.find();
int counter = 0;
void increment() {
counter++;
update();
... ...
... ... @@ -4,7 +4,7 @@ import 'package:get/get.dart';
void main() {
testWidgets(
"GetMaterialApp with routes null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
routes: null,
... ... @@ -15,7 +15,7 @@ void main() {
testWidgets(
"GetMaterialApp with navigatorObservers null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
navigatorObservers: null,
... ... @@ -25,7 +25,7 @@ void main() {
);
testWidgets(
"GetMaterialApp with title null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
title: null,
... ... @@ -35,37 +35,40 @@ void main() {
);
testWidgets(
"GetMaterialApp with debugShowMaterialGrid null",
(WidgetTester testr) async {
(test) async {
expect(
() => GetMaterialApp(
debugShowMaterialGrid: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
testWidgets(
"GetMaterialApp with showPerformanceOverlay null",
(WidgetTester testr) async {
(test) async {
expect(
() => GetMaterialApp(
showPerformanceOverlay: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
testWidgets(
"GetMaterialApp with showSemanticsDebugger null",
(WidgetTester testr) async {
(test) async {
expect(
() => GetMaterialApp(
showSemanticsDebugger: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
testWidgets(
"GetMaterialApp with debugShowCheckedModeBanner null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
debugShowCheckedModeBanner: null,
... ... @@ -76,7 +79,7 @@ void main() {
testWidgets(
"GetMaterialApp with checkerboardRasterCacheImages null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
checkerboardRasterCacheImages: null,
... ... @@ -87,12 +90,13 @@ void main() {
testWidgets(
"GetMaterialApp with checkerboardOffscreenLayers null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetMaterialApp(
checkerboardOffscreenLayers: null,
),
throwsAssertionError);
throwsAssertionError,
);
},
);
}
... ...
... ... @@ -5,37 +5,39 @@ import 'package:get/src/navigation/routes/get_route.dart';
void main() {
testWidgets(
'GetPage page null',
(WidgetTester testr) async {
(tester) async {
expect(() => GetPage(page: null, name: null), throwsAssertionError);
},
);
testWidgets(
"GetPage maintainState null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetPage(page: () => Scaffold(), maintainState: null, name: '/'),
throwsAssertionError);
throwsAssertionError,
);
},
);
testWidgets(
"GetPage name null",
(WidgetTester testr) async {
(tester) async {
expect(
() =>
GetPage(page: () => Scaffold(), maintainState: null, name: null),
throwsAssertionError);
() => GetPage(page: () => Scaffold(), maintainState: null, name: null),
throwsAssertionError,
);
},
);
testWidgets(
"GetPage fullscreenDialog null",
(WidgetTester testr) async {
(tester) async {
expect(
() => GetPage(
page: () => Scaffold(), fullscreenDialog: null, name: '/'),
throwsAssertionError);
() =>
GetPage(page: () => Scaffold(), fullscreenDialog: null, name: '/'),
throwsAssertionError,
);
},
);
}
... ...
... ... @@ -3,7 +3,7 @@ import 'package:get/utils.dart';
void main() {
test('Test for toPrecision on Double', () {
double testVar = 5.4545454;
var testVar = 5.4545454;
expect(testVar.toPrecision(2), equals(5.45));
});
}
... ...
... ... @@ -4,7 +4,7 @@ import 'package:get/utils.dart';
void main() {
group('Group test for PaddingX Extension', () {
testWidgets('Test of paddingAll', (WidgetTester tester) async {
testWidgets('Test of paddingAll', (tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
... ... @@ -14,7 +14,7 @@ void main() {
expect(find.byType(Padding), findsOneWidget);
});
testWidgets('Test of paddingOnly', (WidgetTester tester) async {
testWidgets('Test of paddingOnly', (tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
... ... @@ -24,7 +24,7 @@ void main() {
expect(find.byType(Padding), findsOneWidget);
});
testWidgets('Test of paddingSymmetric', (WidgetTester tester) async {
testWidgets('Test of paddingSymmetric', (tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
... ... @@ -34,7 +34,7 @@ void main() {
expect(find.byType(Padding), findsOneWidget);
});
testWidgets('Test of paddingZero', (WidgetTester tester) async {
testWidgets('Test of paddingZero', (tester) async {
Widget containerTest;
expect(find.byType(Padding), findsNothing);
... ... @@ -46,7 +46,7 @@ void main() {
});
group('Group test for MarginX Extension', () {
testWidgets('Test of marginAll', (WidgetTester tester) async {
testWidgets('Test of marginAll', (tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginAll(16));
... ... @@ -54,7 +54,7 @@ void main() {
expect(find.byType(Container), findsOneWidget);
});
testWidgets('Test of marginOnly', (WidgetTester tester) async {
testWidgets('Test of marginOnly', (tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginOnly(top: 16));
... ... @@ -62,7 +62,7 @@ void main() {
expect(find.byType(Container), findsOneWidget);
});
testWidgets('Test of marginSymmetric', (WidgetTester tester) async {
testWidgets('Test of marginSymmetric', (tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginSymmetric(vertical: 16));
... ... @@ -70,7 +70,7 @@ void main() {
expect(find.byType(Container), findsOneWidget);
});
testWidgets('Test of marginZero', (WidgetTester tester) async {
testWidgets('Test of marginZero', (tester) async {
Widget containerTest;
await tester.pumpWidget(containerTest.marginZero);
... ...
... ... @@ -56,7 +56,7 @@ class HavingMatcher<T> implements TypeMatcher<T> {
HavingMatcher(_parent, description, feature, matcher, _functionMatchers);
@override
bool matches(item, Map matchState) {
bool matches(dynamic item, Map matchState) {
for (var matcher in <Matcher>[_parent].followedBy(_functionMatchers)) {
if (!matcher.matches(item, matchState)) {
addStateInfo(matchState, {'matcher': matcher});
... ... @@ -68,7 +68,11 @@ class HavingMatcher<T> implements TypeMatcher<T> {
@override
Description describeMismatch(
item, Description mismatchDescription, Map matchState, bool verbose) {
dynamic item,
Description mismatchDescription,
Map matchState,
bool verbose,
) {
var matcher = matchState['matcher'] as Matcher;
matcher.describeMismatch(
item, mismatchDescription, matchState['state'] as Map, verbose);
... ... @@ -101,7 +105,11 @@ class TypeMatcher<T> extends Matcher {
@override
Description describeMismatch(
item, Description mismatchDescription, Map matchState, bool verbose) {
dynamic item,
Description mismatchDescription,
Map matchState,
bool verbose,
) {
var name = _stripDynamic(T);
return mismatchDescription.add("is not an instance of '$name'");
}
... ...