Jonny Borges
Committed by GitHub

Merge pull request #2115 from jonataslaw/update-code

improve code
... ... @@ -20,6 +20,10 @@ version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependency_overrides:
get:
path: ../
dependencies:
flutter:
sdk: flutter
... ... @@ -33,6 +37,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
get_test: 4.0.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
... ...
import 'dart:async';
import 'package:get/get.dart';
import 'package:async/async.dart';
import 'package:get/get.dart';
class SplashService extends GetxService {
final welcomeStr = ['GetX', 'Rules!'];
... ...
import 'package:example_nav2/app/modules/splash/controllers/splash_service.dart';
import 'package:example_nav2/app/modules/splash/views/splash_view.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'app/modules/splash/controllers/splash_service.dart';
import 'app/modules/splash/views/splash_view.dart';
import 'app/routes/app_pages.dart';
import 'services/auth_service.dart';
... ...
... ... @@ -76,3 +76,11 @@ mixin GetLifeCycleMixin {
/// Allow track difference between GetxServices and GetxControllers
mixin GetxServiceMixin {}
/// 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().
abstract class GetxService with GetLifeCycleMixin, GetxServiceMixin {}
... ...
... ... @@ -2,9 +2,9 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../../../get.dart';
import '../../../get_state_manager/src/simple/list_notifier.dart';
import 'get_navigator.dart';
/// Enables the user to customize the intended pop behavior
///
... ...
... ... @@ -4,6 +4,21 @@ import '../../../get.dart';
import '../router_report.dart';
import 'get_transition_mixin.dart';
@optionalTypeArgs
mixin RouteReportMixin<T extends StatefulWidget> on State<T> {
@override
void initState() {
super.initState();
RouterReportManager.instance.reportCurrentRoute(this);
}
@override
void dispose() {
super.dispose();
RouterReportManager.instance.reportRouteDispose(this);
}
}
mixin PageRouteReportMixin<T> on Route<T> {
@override
void install() {
... ...
import 'package:flutter/material.dart';
import '../router_report.dart';
import 'default_route.dart';
class RouteReport extends StatefulWidget {
RouteReport({Key? key, required this.builder}) : super(key: key);
final WidgetBuilder builder;
@override
_RouteReportState createState() => _RouteReportState();
}
class _RouteReportState extends State<RouteReport> with RouteReportMixin {
@override
void initState() {
RouterReportManager.instance.reportCurrentRoute(this);
super.initState();
}
@override
void dispose() {
RouterReportManager.instance.reportRouteDispose(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.builder(context);
}
}
... ...
... ... @@ -102,9 +102,7 @@ mixin RxObjectMixin<T> on GetListenable<T> {
sentToStream = false;
if (value == val && !firstRebuild) return;
firstRebuild = false;
// _value = val;
sentToStream = true;
//TODO: Check this
super.value = val;
}
... ... @@ -121,7 +119,6 @@ mixin RxObjectMixin<T> on GetListenable<T> {
cancelOnError: cancelOnError,
);
//TODO: Change to refresh????
subject.add(value);
return subscription;
... ... @@ -140,53 +137,6 @@ mixin RxObjectMixin<T> on GetListenable<T> {
}
}
//class RxNotifier<T> = RxInterface<T> with NotifyManager<T>;
// mixin NotifyManager<T> {
// GetStream<T> subject = GetStream<T>();
// final _subscriptions = <GetStream, List<StreamSubscription>>{};
// bool get canUpdate => _subscriptions.isNotEmpty;
// /// This is an internal method.
// /// Subscribe to changes on the inner stream.
// void addListener(GetStream<T> rxGetx) {
// if (!_subscriptions.containsKey(rxGetx)) {
// final subs = rxGetx.listen((data) {
// if (!subject.isClosed) subject.add(data);
// });
// final listSubscriptions =
// _subscriptions[rxGetx] ??= <StreamSubscription>[];
// listSubscriptions.add(subs);
// }
// }
// StreamSubscription<T> listen(
// void Function(T) onData, {
// Function? onError,
// void Function()? onDone,
// bool? cancelOnError,
// }) =>
// subject.listen(
// onData,
// onError: onError,
// onDone: onDone,
// cancelOnError: cancelOnError ?? false,
// );
// /// Closes the subscriptions for this Rx, releasing the resources.
// void close() {
// _subscriptions.forEach((getStream, _subscriptions) {
// for (final subscription in _subscriptions) {
// subscription.cancel();
// }
// });
// _subscriptions.clear();
// subject.close();
// }
// }
/// Base Rx class that manages all the stream logic for any Type.
abstract class _RxImpl<T> extends GetListenable<T> with RxObjectMixin<T> {
_RxImpl(T initial) : super(initial);
... ...
... ... @@ -2,33 +2,15 @@ part of rx_types;
/// This class is the foundation for all reactive (Rx) classes that makes Get
/// so powerful.
/// This interface is the contract that _RxImpl]<T> uses in all it's
/// This interface is the contract that [_RxImpl]<T> uses in all it's
/// subclass.
abstract class RxInterface<T> {
//bool get canUpdate;
/// Adds a listener to stream
void addListener(VoidCallback listener);
abstract class RxInterface<T> implements ValueListenable<T> {
/// Close the Rx Variable
void close();
/// Calls `callback` with current value, when the value changes.
StreamSubscription<T> listen(void Function(T event) onData,
{Function? onError, void Function()? onDone, bool? cancelOnError});
/// Avoids an unsafe usage of the `proxy`
// static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) {
// final _observer = RxInterface.proxy;
// RxInterface.proxy = observer;
// final result = builder();
// if (!observer.canUpdate) {
// RxInterface.proxy = _observer;
// throw ObxError();
// }
// RxInterface.proxy = _observer;
// return result;
// }
}
class ObxError {
... ...
library get_state_manager;
export 'src/rx_flutter/rx_disposable.dart';
export 'src/rx_flutter/rx_getx_widget.dart';
export 'src/rx_flutter/rx_notifier.dart';
export 'src/rx_flutter/rx_obx_widget.dart';
... ... @@ -9,5 +8,4 @@ export 'src/simple/get_controllers.dart';
export 'src/simple/get_responsive.dart';
export 'src/simple/get_state.dart';
export 'src/simple/get_view.dart';
export 'src/simple/mixin_state.dart';
export 'src/simple/simple_builder.dart';
... ...
import '../../../get_instance/src/lifecycle.dart';
/// 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().
abstract class GetxService with GetLifeCycleMixin, GetxServiceMixin {}
// abstract class DisposableInterface with GetLifeCycleMixin {}
... ... @@ -113,20 +113,25 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> {
disposer();
}
disposers.clear();
controller = null;
_isCreator = null;
super.dispose();
}
void _update() {
if (mounted) {
setState(() {});
}
}
final disposers = <Disposer>[];
@override
Widget build(BuildContext context) => NotifierManager.instance
.exchange(disposers, _update, () => widget.builder(controller!));
Widget build(BuildContext context) => Notifier.instance.append(
NotifyData(disposers: disposers, updater: _update),
() => widget.builder(controller!));
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
... ...
... ... @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../../../get_rx/src/rx_types/rx_types.dart';
import '../../../instance_manager.dart';
import '../../get_state_manager.dart';
import '../simple/list_notifier.dart';
... ... @@ -78,8 +79,7 @@ mixin StateMixin<T> on ListNotifier {
}
}
class GetListenable<T> extends ListNotifierSingle
implements ValueListenable<T> {
class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> {
GetListenable(T val) : _value = val;
StreamController<T>? _controller;
... ... @@ -96,6 +96,7 @@ class GetListenable<T> extends ListNotifierSingle
_controller?.add(_value);
}
@override
@mustCallSuper
void close() {
removeListener(_streamListener);
... ... @@ -132,6 +133,7 @@ class GetListenable<T> extends ListNotifierSingle
return value;
}
@override
StreamSubscription<T> listen(
void Function(T)? onData, {
Function? onError,
... ... @@ -188,6 +190,8 @@ class Value<T> extends ListNotifier
dynamic toJson() => (value as dynamic)?.toJson();
}
/// GetNotifier has a native status and state implementation, with the
/// Get Lifecycle
abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin {
GetNotifier(T initial) : super(initial);
}
... ... @@ -198,6 +202,7 @@ extension StateExt<T> on StateMixin<T> {
Widget Function(String? error)? onError,
Widget? onLoading,
Widget? onEmpty,
WidgetBuilder? onCustom,
}) {
return Observer(builder: (_) {
if (status.isLoading) {
... ... @@ -210,6 +215,11 @@ extension StateExt<T> on StateMixin<T> {
return onEmpty != null
? onEmpty
: SizedBox.shrink(); // Also can be widget(null); but is risky
} else if (status.isSuccess) {
return widget(value);
} else if (status.isCustom) {
return onCustom?.call(_) ??
SizedBox.shrink(); // Also can be widget(null); but is risky
}
return widget(value);
});
... ... @@ -246,6 +256,7 @@ extension StatusDataExt<T> on GetState<T> {
bool get isSuccess => this is SuccessState;
bool get isError => this is ErrorState;
bool get isEmpty => this is EmptyState;
bool get isCustom => !isLoading && !isSuccess && !isError && !isEmpty;
String get errorMessage {
final isError = this is ErrorState;
if (isError) {
... ...
... ... @@ -26,6 +26,8 @@ abstract class GetxController extends ListNotifier with GetLifeCycleMixin {
}
}
/// this mixin allow to fetch data when the scroll is at the bottom or on the
/// top
mixin ScrollMixin on GetLifeCycleMixin {
final ScrollController scroll = ScrollController();
... ... @@ -59,8 +61,10 @@ mixin ScrollMixin on GetLifeCycleMixin {
}
}
/// this method is called when the scroll is at the bottom
Future<void> onEndScroll();
/// this method is called when the scroll is at the top
Future<void> onTopScroll();
@override
... ... @@ -70,13 +74,17 @@ mixin ScrollMixin on GetLifeCycleMixin {
}
}
/// A clean controller to be used with only Rx variables
abstract class RxController with GetLifeCycleMixin {}
/// A recommended way to use Getx with Future fetching
abstract class StateController<T> extends GetxController with StateMixin<T> {}
/// A controller with super lifecycles (including native lifecycles) and StateMixins
abstract class SuperController<T> extends FullLifeCycleController
with FullLifeCycleMixin, StateMixin<T> {}
/// A controller with super lifecycles (including native lifecycles)
abstract class FullLifeCycleController extends GetxController
with
// ignore: prefer_mixin
... ... @@ -116,8 +124,8 @@ mixin FullLifeCycleMixin on FullLifeCycleController {
}
}
void onResumed();
void onPaused();
void onInactive();
void onDetached();
void onResumed() {}
void onPaused() {}
void onInactive() {}
void onDetached() {}
}
... ...
... ... @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import '../../../instance_manager.dart';
import '../../get_state_manager.dart';
import 'list_notifier.dart';
typedef InitBuilder<T> = T Function();
... ... @@ -37,7 +38,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
final void Function(Binder<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
final T? init;
... ... @@ -59,7 +60,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BindWrapper(
return Binder(
init: init == null ? null : () => init!,
global: global,
autoRemove: autoRemove,
... ... @@ -108,7 +109,7 @@ abstract class Bind<T> extends StatelessWidget {
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
final void Function(Binder<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
final Widget? child;
... ... @@ -193,8 +194,7 @@ abstract class Bind<T> extends StatelessWidget {
void Function(BindElement<T> state)? initState,
void Function(BindElement<T> state)? dispose,
void Function(BindElement<T> state)? didChangeDependencies,
void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget,
void Function(Binder<T> oldWidget, BindElement<T> state)? didUpdateWidget,
}) =>
_FactoryBind<T>(
// key: key,
... ... @@ -218,7 +218,7 @@ abstract class Bind<T> extends StatelessWidget {
// Object Function(T value)? filter,
}) {
final inheritedElement =
context.getElementForInheritedWidgetOfExactType<BindWrapper<T>>()
context.getElementForInheritedWidgetOfExactType<Binder<T>>()
as BindElement<T>?;
if (inheritedElement == null) {
... ... @@ -265,7 +265,7 @@ class _FactoryBind<T> extends Bind<T> {
dispose,
didChangeDependencies;
@override
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
final void Function(Binder<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
@override
... ... @@ -307,7 +307,7 @@ class _FactoryBind<T> extends Bind<T> {
@override
Widget build(BuildContext context) {
return BindWrapper<T>(
return Binder<T>(
init: init,
global: global,
autoRemove: autoRemove,
... ... @@ -340,12 +340,12 @@ class Binds extends StatelessWidget {
binds.reversed.fold(child, (acc, e) => e._copyWithChild(acc));
}
class BindWrapper<T> extends InheritedWidget {
class Binder<T> extends InheritedWidget {
/// Create an inherited widget that updates its dependents when [controller]
/// sends notifications.
///
/// The [child] argument is required
const BindWrapper({
const Binder({
Key? key,
required Widget child,
this.init,
... ... @@ -371,11 +371,11 @@ class BindWrapper<T> extends InheritedWidget {
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
final void Function(Binder<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
@override
bool updateShouldNotify(BindWrapper<T> oldWidget) {
bool updateShouldNotify(Binder<T> oldWidget) {
return oldWidget.id != id ||
oldWidget.global != global ||
oldWidget.autoRemove != autoRemove ||
... ... @@ -389,10 +389,12 @@ class BindWrapper<T> extends InheritedWidget {
/// The BindElement is responsible for injecting dependencies into the widget
/// tree so that they can be observed
class BindElement<T> extends InheritedElement {
BindElement(BindWrapper<T> widget) : super(widget) {
BindElement(Binder<T> widget) : super(widget) {
initState();
}
final disposers = <Disposer>[];
InitBuilder<T>? _controllerBuilder;
T? _controller;
... ... @@ -486,6 +488,12 @@ class BindElement<T> extends InheritedElement {
}
}
for (final disposer in disposers) {
disposer();
}
disposers.clear();
_remove?.call();
_controller = null;
_isCreator = null;
... ... @@ -497,12 +505,12 @@ class BindElement<T> extends InheritedElement {
}
@override
BindWrapper<T> get widget => super.widget as BindWrapper<T>;
Binder<T> get widget => super.widget as Binder<T>;
var _dirty = false;
@override
void update(BindWrapper<T> newWidget) {
void update(Binder<T> newWidget) {
final oldNotifier = widget.id;
final newNotifier = newWidget.id;
if (oldNotifier != newNotifier && _wasStarted) {
... ... @@ -523,7 +531,11 @@ class BindElement<T> extends InheritedElement {
if (_dirty) {
notifyClients(widget);
}
// return Notifier.instance.notifyAppend(
// NotifyData(
// disposers: disposers, updater: getUpdate, throwException: false),
return super.build();
//);
}
void getUpdate() {
... ... @@ -532,7 +544,7 @@ class BindElement<T> extends InheritedElement {
}
@override
void notifyClients(BindWrapper<T> oldWidget) {
void notifyClients(Binder<T> oldWidget) {
super.notifyClients(oldWidget);
_dirty = false;
}
... ...
... ... @@ -12,10 +12,14 @@ typedef GetStateUpdate = void Function();
class ListNotifier extends Listenable
with ListNotifierSingleMixin, ListNotifierGroupMixin {}
/// A Notifier with single listeners
class ListNotifierSingle = ListNotifier with ListNotifierSingleMixin;
/// A notifier with group of listeners identified by id
class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin;
/// This mixin add to Listenable the addListener, removerListener and
/// containsListener implementation
mixin ListNotifierSingleMixin on Listenable {
List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[];
... ... @@ -44,12 +48,12 @@ mixin ListNotifierSingleMixin on Listenable {
@protected
void reportRead() {
NotifierManager.instance.notify(this);
Notifier.instance.read(this);
}
@protected
void reportAdd(VoidCallback disposer) {
NotifierManager.instance.reportAdd(disposer);
Notifier.instance.add(disposer);
}
void _notifyUpdate() {
... ... @@ -96,7 +100,7 @@ mixin ListNotifierGroupMixin on Listenable {
@protected
void notifyGroupChildrens(Object id) {
assert(_debugAssertNotDisposed());
NotifierManager.instance.notify(_updatersGroupIds![id]!);
Notifier.instance.read(_updatersGroupIds![id]!);
}
bool containsId(Object id) {
... ... @@ -148,44 +152,47 @@ mixin ListNotifierGroupMixin on Listenable {
}
}
class NotifierManager {
NotifierManager._();
class Notifier {
Notifier._();
static NotifierManager? _instance;
static Notifier? _instance;
static Notifier get instance => _instance ??= Notifier._();
static NotifierManager get instance => _instance ??= NotifierManager._();
NotifyData? _notifyData;
GetStateUpdate? _setter;
List<VoidCallback>? _remove;
void reportAdd(VoidCallback listener) {
_remove?.add(listener);
void add(VoidCallback listener) {
_notifyData?.disposers.add(listener);
}
void notify(ListNotifierSingleMixin _updaters) {
final listener = _setter;
if (listener != null) {
if (!_updaters.containsListener(listener)) {
void read(ListNotifierSingleMixin _updaters) {
final listener = _notifyData?.updater;
if (listener != null && !_updaters.containsListener(listener)) {
_updaters.addListener(listener);
reportAdd(() => _updaters.removeListener(listener));
}
add(() => _updaters.removeListener(listener));
}
}
T exchange<T>(List<VoidCallback> disposers, GetStateUpdate setState,
T Function() builder) {
_remove = disposers;
_setter = setState;
T append<T>(NotifyData data, T Function() builder) {
_notifyData = data;
final result = builder();
if (disposers.isEmpty) {
if (data.disposers.isEmpty && data.throwException) {
throw ObxError();
}
_remove = null;
_setter = null;
_notifyData = data;
return result;
}
}
class NotifyData {
const NotifyData(
{required this.updater,
required this.disposers,
this.throwException = true});
final GetStateUpdate updater;
final List<VoidCallback> disposers;
final bool throwException;
}
class ObxError {
const ObxError();
@override
... ...
import 'package:flutter/material.dart';
import '../../get_state_manager.dart';
import '../rx_flutter/rx_obx_widget.dart';
import 'get_controllers.dart';
import 'get_state.dart';
class MixinBuilder<T extends GetxController> extends StatelessWidget {
@required
... ... @@ -11,7 +13,7 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget {
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
final void Function(Binder<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
final T? init;
... ...
... ... @@ -45,7 +45,6 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T>> {
T value;
_ValueBuilderState(this.value);
@override
Widget build(BuildContext context) => widget.builder(value, updater);
... ... @@ -92,17 +91,27 @@ abstract class ObxStatelessWidget extends StatelessWidget {
/// a Component that can track changes in a reactive variable
mixin ObserverComponent on ComponentElement {
final disposers = <Disposer>[];
List<Disposer>? disposers = <Disposer>[];
void getUpdate() {
if (disposers != null) {
markNeedsBuild();
}
}
@override
Widget build() =>
NotifierManager.instance.exchange(disposers, markNeedsBuild, super.build);
Widget build() {
return Notifier.instance.append(
NotifyData(disposers: disposers!, updater: getUpdate), super.build);
}
@override
void unmount() {
super.unmount();
for (final disposer in disposers) {
for (final disposer in disposers!) {
disposer();
}
disposers!.clear();
disposers = null;
}
}
... ...
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
extension ContextExtensionss on BuildContext {
extension ContextExt on BuildContext {
/// The same of [MediaQuery.of(context).size]
Size get mediaQuerySize => MediaQuery.of(this).size;
... ... @@ -105,8 +105,8 @@ extension ContextExtensionss on BuildContext {
/// True if the width is higher than 600p
bool get isPhoneOrWider => width >= 600;
/// same as [isPhoneOrLess]
bool get isPhone => isPhoneOrLess;
/// True if the shortestSide is smaller than 600p
bool get isPhone => (mediaQueryShortestSide < 600);
/// True if the width is smaller than 600p
bool get isSmallTabletOrLess => width <= 600;
... ... @@ -114,8 +114,11 @@ extension ContextExtensionss on BuildContext {
/// True if the width is higher than 600p
bool get isSmallTabletOrWider => width >= 600;
/// same as [isSmallTabletOrLess]
bool get isSmallTablet => isSmallTabletOrLess;
/// True if the shortestSide is largest than 600p
bool get isSmallTablet => (mediaQueryShortestSide >= 600);
/// True if the shortestSide is largest than 720p
bool get isLargeTablet => (mediaQueryShortestSide >= 720);
/// True if the width is smaller than 720p
bool get isLargeTabletOrLess => width <= 720;
... ... @@ -123,11 +126,8 @@ extension ContextExtensionss on BuildContext {
/// True if the width is higher than 720p
bool get isLargeTabletOrWider => width >= 720;
/// same as [isLargeTabletOrLess]
bool get isLargeTablet => isLargeTabletOrLess;
/// True if the current device is Tablet
bool get isTablet => isSmallTablet;
bool get isTablet => isSmallTablet || isLargeTablet;
/// True if the width is smaller than 1200p
bool get isDesktopOrLess => width <= 1200;
... ...
import '../get_utils/get_utils.dart';
extension GetDynamicUtils on dynamic {
@Deprecated('isNull is deprecated and cannot be used, use "==" operator')
bool get isNull => GetUtils.isNull(this);
bool? get isBlank => GetUtils.isBlank(this);
@Deprecated(
... ...
import '../get_utils/get_utils.dart';
extension GetStringUtils on String {
/// Discover if the String is a valid number
bool get isNum => GetUtils.isNum(this);
/// Discover if the String is numeric only
bool get isNumericOnly => GetUtils.isNumericOnly(this);
String numericOnly({bool firstWordOnly = false}) =>
GetUtils.numericOnly(this, firstWordOnly: firstWordOnly);
/// Discover if the String is alphanumeric only
bool get isAlphabetOnly => GetUtils.isAlphabetOnly(this);
/// Discover if the String is a boolean
bool get isBool => GetUtils.isBool(this);
/// Discover if the String is a vector
bool get isVectorFileName => GetUtils.isVector(this);
/// Discover if the String is a ImageFileName
bool get isImageFileName => GetUtils.isImage(this);
/// Discover if the String is a AudioFileName
bool get isAudioFileName => GetUtils.isAudio(this);
/// Discover if the String is a VideoFileName
bool get isVideoFileName => GetUtils.isVideo(this);
/// Discover if the String is a TxtFileName
bool get isTxtFileName => GetUtils.isTxt(this);
/// Discover if the String is a Document Word
bool get isDocumentFileName => GetUtils.isWord(this);
/// Discover if the String is a Document Excel
bool get isExcelFileName => GetUtils.isExcel(this);
/// Discover if the String is a Document Powerpoint
bool get isPPTFileName => GetUtils.isPPT(this);
/// Discover if the String is a APK File
bool get isAPKFileName => GetUtils.isAPK(this);
/// Discover if the String is a PDF file
bool get isPDFFileName => GetUtils.isPDF(this);
/// Discover if the String is a HTML file
bool get isHTMLFileName => GetUtils.isHTML(this);
/// Discover if the String is a URL file
bool get isURL => GetUtils.isURL(this);
/// Discover if the String is a Email
bool get isEmail => GetUtils.isEmail(this);
/// Discover if the String is a Phone Number
bool get isPhoneNumber => GetUtils.isPhoneNumber(this);
/// Discover if the String is a DateTime
bool get isDateTime => GetUtils.isDateTime(this);
/// Discover if the String is a MD5 Hash
bool get isMD5 => GetUtils.isMD5(this);
/// Discover if the String is a SHA1 Hash
bool get isSHA1 => GetUtils.isSHA1(this);
/// Discover if the String is a SHA256 Hash
bool get isSHA256 => GetUtils.isSHA256(this);
/// Discover if the String is a bynary value
bool get isBinary => GetUtils.isBinary(this);
/// Discover if the String is a ipv4
bool get isIPv4 => GetUtils.isIPv4(this);
bool get isIPv6 => GetUtils.isIPv6(this);
/// Discover if the String is a Hexadecimal
bool get isHexadecimal => GetUtils.isHexadecimal(this);
/// Discover if the String is a palindrom
bool get isPalindrom => GetUtils.isPalindrom(this);
/// Discover if the String is a passport number
bool get isPassport => GetUtils.isPassport(this);
/// Discover if the String is a currency
bool get isCurrency => GetUtils.isCurrency(this);
/// Discover if the String is a CPF number
bool get isCpf => GetUtils.isCpf(this);
/// Discover if the String is a CNPJ number
bool get isCnpj => GetUtils.isCnpj(this);
/// Discover if the String is a case insensitive
bool isCaseInsensitiveContains(String b) =>
GetUtils.isCaseInsensitiveContains(this, b);
/// Discover if the String is a case sensitive and contains any value
bool isCaseInsensitiveContainsAny(String b) =>
GetUtils.isCaseInsensitiveContainsAny(this, b);
/// capitalize the String
String? get capitalize => GetUtils.capitalize(this);
/// Capitalize the first letter of the String
String? get capitalizeFirst => GetUtils.capitalizeFirst(this);
/// remove all whitespace from the String
String get removeAllWhitespace => GetUtils.removeAllWhitespace(this);
/// converter the String
String? get camelCase => GetUtils.camelCase(this);
/// Discover if the String is a valid URL
String? get paramCase => GetUtils.paramCase(this);
String numericOnly({bool firstWordOnly = false}) =>
GetUtils.numericOnly(this, firstWordOnly: firstWordOnly);
/// add segments to the String
String createPath([Iterable? segments]) {
final path = startsWith('/') ? this : '/$this';
return GetUtils.createPath(path, segments);
... ...
import 'package:flutter/material.dart';
class OtimizedListView<T> extends StatelessWidget {
final List<T> list;
final Axis scrollDirection;
final bool reverse;
final ScrollController? controller;
final bool? primary;
final ScrollPhysics? physics;
final bool shrinkWrap;
final Widget onEmpty;
final int lenght;
final Widget Function(BuildContext context, ValueKey key, T item) builder;
const OtimizedListView({
Key? key,
required this.list,
required this.builder,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.controller,
this.primary,
this.physics,
this.onEmpty = const SizedBox.shrink(),
this.shrinkWrap = false,
}) : lenght = list.length,
super(key: key);
@override
Widget build(BuildContext context) {
if (list.isEmpty) return onEmpty;
return CustomScrollView(
controller: controller,
reverse: reverse,
scrollDirection: scrollDirection,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) {
final item = list[i];
final key = ValueKey(item);
return builder(context, key, item);
},
childCount: list.length,
addAutomaticKeepAlives: true,
findChildIndexCallback: (key) {
return list.indexWhere((m) => m == (key as ValueKey<T>).value);
},
),
),
],
);
}
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:get/get_state_manager/src/simple/mixin_builder.dart';
void main() {
testWidgets("MixinBuilder smoke test", (tester) async {
testWidgets("MixinBuilder with reactive and not reactive", (tester) async {
await tester.pumpWidget(
MaterialApp(
home: MixinBuilder<Controller>(
... ... @@ -35,6 +36,10 @@ void main() {
TextButton(
child: Text("increment"),
onPressed: () => controller.increment(),
),
TextButton(
child: Text("increment2"),
onPressed: () => controller.increment2(),
)
],
);
... ... @@ -62,6 +67,12 @@ void main() {
await tester.pump();
expect(find.text("Count: 2"), findsOneWidget);
await tester.tap(find.text('increment2'));
await tester.pump();
expect(find.text("Count2: 1"), findsOneWidget);
});
// testWidgets(
... ...