Showing
7 changed files
with
57 additions
and
171 deletions
| @@ -3,7 +3,7 @@ import 'package:get/get.dart'; | @@ -3,7 +3,7 @@ import 'package:get/get.dart'; | ||
| 3 | import '../../domain/adapters/repository_adapter.dart'; | 3 | import '../../domain/adapters/repository_adapter.dart'; | 
| 4 | import '../../domain/entity/cases_model.dart'; | 4 | import '../../domain/entity/cases_model.dart'; | 
| 5 | 5 | ||
| 6 | -class HomeController extends SuperController<CasesModel> { | 6 | +class HomeController extends StateController<CasesModel> { | 
| 7 | HomeController({required this.homeRepository}); | 7 | HomeController({required this.homeRepository}); | 
| 8 | 8 | ||
| 9 | final IHomeRepository homeRepository; | 9 | final IHomeRepository homeRepository; | 
| @@ -13,7 +13,7 @@ class HomeController extends SuperController<CasesModel> { | @@ -13,7 +13,7 @@ class HomeController extends SuperController<CasesModel> { | ||
| 13 | super.onInit(); | 13 | super.onInit(); | 
| 14 | 14 | ||
| 15 | //Loading, Success, Error handle with 1 line of code | 15 | //Loading, Success, Error handle with 1 line of code | 
| 16 | - append(() => homeRepository.getCases); | 16 | + listenFuture(() => homeRepository.getCases); | 
| 17 | } | 17 | } | 
| 18 | 18 | ||
| 19 | Country getCountryById(String id) { | 19 | Country getCountryById(String id) { | 
| @@ -24,61 +24,4 @@ class HomeController extends SuperController<CasesModel> { | @@ -24,61 +24,4 @@ class HomeController extends SuperController<CasesModel> { | ||
| 24 | 24 | ||
| 25 | return state.countries.first; | 25 | return state.countries.first; | 
| 26 | } | 26 | } | 
| 27 | - | ||
| 28 | - @override | ||
| 29 | - void onReady() { | ||
| 30 | - print('The build method is done. ' | ||
| 31 | - 'Your controller is ready to call dialogs and snackbars'); | ||
| 32 | - super.onReady(); | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | - @override | ||
| 36 | - void onClose() { | ||
| 37 | - print('onClose called'); | ||
| 38 | - super.onClose(); | ||
| 39 | - } | ||
| 40 | - | ||
| 41 | - @override | ||
| 42 | - void didChangeMetrics() { | ||
| 43 | - print('the window size did change'); | ||
| 44 | - super.didChangeMetrics(); | ||
| 45 | - } | ||
| 46 | - | ||
| 47 | - @override | ||
| 48 | - void didChangePlatformBrightness() { | ||
| 49 | - print('platform change ThemeMode'); | ||
| 50 | - super.didChangePlatformBrightness(); | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - @override | ||
| 54 | - Future<bool> didPushRoute(String route) { | ||
| 55 | - print('the route $route will be open'); | ||
| 56 | - return super.didPushRoute(route); | ||
| 57 | - } | ||
| 58 | - | ||
| 59 | - @override | ||
| 60 | - Future<bool> didPopRoute() { | ||
| 61 | - print('the current route will be closed'); | ||
| 62 | - return super.didPopRoute(); | ||
| 63 | - } | ||
| 64 | - | ||
| 65 | - @override | ||
| 66 | - void onDetached() { | ||
| 67 | - print('onDetached called'); | ||
| 68 | - } | ||
| 69 | - | ||
| 70 | - @override | ||
| 71 | - void onInactive() { | ||
| 72 | - print('onInative called'); | ||
| 73 | - } | ||
| 74 | - | ||
| 75 | - @override | ||
| 76 | - void onPaused() { | ||
| 77 | - print('onPaused called'); | ||
| 78 | - } | ||
| 79 | - | ||
| 80 | - @override | ||
| 81 | - void onResumed() { | ||
| 82 | - print('onResumed called'); | ||
| 83 | - } | ||
| 84 | } | 27 | } | 
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; | 
| 3 | 3 | ||
| 4 | +import 'app/routes/app_pages.dart'; | ||
| 5 | +import 'services/auth_service.dart'; | ||
| 6 | + | ||
| 4 | void main() { | 7 | void main() { | 
| 5 | runApp( | 8 | runApp( | 
| 6 | - GetMaterialApp( | ||
| 7 | - home: Home(), | 9 | + GetMaterialApp.router( | 
| 10 | + title: "Application", | ||
| 11 | + initialBinding: BindingsBuilder( | ||
| 12 | + () { | ||
| 13 | + Get.put(AuthService()); | ||
| 14 | + }, | ||
| 15 | + ), | ||
| 16 | + getPages: AppPages.routes, | ||
| 17 | + // routeInformationParser: GetInformationParser( | ||
| 18 | + // // initialRoute: Routes.HOME, | ||
| 19 | + // ), | ||
| 20 | + // routerDelegate: GetDelegate( | ||
| 21 | + // backButtonPopMode: PopMode.History, | ||
| 22 | + // preventDuplicateHandlingMode: | ||
| 23 | + // PreventDuplicateHandlingMode.ReorderRoutes, | ||
| 24 | + // ), | ||
| 8 | ), | 25 | ), | 
| 9 | ); | 26 | ); | 
| 10 | } | 27 | } | 
| 11 | - | ||
| 12 | -class Controller extends GetxController { | ||
| 13 | - final count = 0.reactive; | ||
| 14 | - void increment() { | ||
| 15 | - count.value++; | ||
| 16 | - update(); | ||
| 17 | - } | ||
| 18 | -} | ||
| 19 | - | ||
| 20 | -class Home extends ObxStatelessWidget { | ||
| 21 | - const Home({Key? key}) : super(key: key); | ||
| 22 | - @override | ||
| 23 | - Widget build(BuildContext context) { | ||
| 24 | - final controller = Get.put(Controller()); | ||
| 25 | - return Scaffold( | ||
| 26 | - appBar: AppBar(title: Text("counter")), | ||
| 27 | - body: Center( | ||
| 28 | - child: Column( | ||
| 29 | - mainAxisAlignment: MainAxisAlignment.center, | ||
| 30 | - children: [ | ||
| 31 | - Observer(builder: (context) { | ||
| 32 | - print('builder'); | ||
| 33 | - return Text( | ||
| 34 | - '${controller.count.value}', | ||
| 35 | - style: TextStyle(fontSize: 30), | ||
| 36 | - ); | ||
| 37 | - }), | ||
| 38 | - // ElevatedButton( | ||
| 39 | - // child: Text('Next Route'), | ||
| 40 | - // onPressed: () { | ||
| 41 | - // Get.to(() => Second()); | ||
| 42 | - // }, | ||
| 43 | - // ), | ||
| 44 | - ], | ||
| 45 | - ), | ||
| 46 | - ), | ||
| 47 | - floatingActionButton: FloatingActionButton( | ||
| 48 | - child: Icon(Icons.add), | ||
| 49 | - onPressed: controller.increment, | ||
| 50 | - ), | ||
| 51 | - ); | ||
| 52 | - } | ||
| 53 | -} | 
| @@ -96,6 +96,7 @@ extension MapExtension<K, V> on Map<K, V> { | @@ -96,6 +96,7 @@ extension MapExtension<K, V> on Map<K, V> { | ||
| 96 | final map = (this as RxMap); | 96 | final map = (this as RxMap); | 
| 97 | if (map.value == val) return; | 97 | if (map.value == val) return; | 
| 98 | map.value = val; | 98 | map.value = val; | 
| 99 | + // ignore: invalid_use_of_protected_member | ||
| 99 | map.refresh(); | 100 | map.refresh(); | 
| 100 | } else { | 101 | } else { | 
| 101 | if (this == val) return; | 102 | if (this == val) return; | 
| @@ -4,10 +4,8 @@ import 'dart:async'; | @@ -4,10 +4,8 @@ import 'dart:async'; | ||
| 4 | import 'dart:collection'; | 4 | import 'dart:collection'; | 
| 5 | 5 | ||
| 6 | import 'package:flutter/foundation.dart'; | 6 | import 'package:flutter/foundation.dart'; | 
| 7 | -import 'package:get/get_state_manager/src/rx_flutter/rx_notifier.dart'; | ||
| 8 | -import 'package:get/get_state_manager/src/simple/list_notifier.dart'; | ||
| 9 | 7 | ||
| 10 | -import '../rx_stream/rx_stream.dart'; | 8 | +import '../../../get_state_manager/src/rx_flutter/rx_notifier.dart'; | 
| 11 | import '../rx_typedefs/rx_typedefs.dart'; | 9 | import '../rx_typedefs/rx_typedefs.dart'; | 
| 12 | 10 | ||
| 13 | part 'rx_core/rx_impl.dart'; | 11 | part 'rx_core/rx_impl.dart'; | 
| @@ -8,13 +8,14 @@ import '../../get_state_manager.dart'; | @@ -8,13 +8,14 @@ import '../../get_state_manager.dart'; | ||
| 8 | import '../simple/list_notifier.dart'; | 8 | import '../simple/list_notifier.dart'; | 
| 9 | 9 | ||
| 10 | extension _NullOrEmpty on Object { | 10 | extension _NullOrEmpty on Object { | 
| 11 | - bool _isNullOrEmpty(dynamic val) { | ||
| 12 | - if (val == null) return true; | 11 | + bool _isEmpty() { | 
| 12 | + final val = this; | ||
| 13 | + // if (val == null) return true; | ||
| 13 | var result = false; | 14 | var result = false; | 
| 14 | if (val is Iterable) { | 15 | if (val is Iterable) { | 
| 15 | result = val.isEmpty; | 16 | result = val.isEmpty; | 
| 16 | } else if (val is String) { | 17 | } else if (val is String) { | 
| 17 | - result = val.isEmpty; | 18 | + result = val.trim().isEmpty; | 
| 18 | } else if (val is Map) { | 19 | } else if (val is Map) { | 
| 19 | result = val.isEmpty; | 20 | result = val.isEmpty; | 
| 20 | } | 21 | } | 
| @@ -24,15 +25,17 @@ extension _NullOrEmpty on Object { | @@ -24,15 +25,17 @@ extension _NullOrEmpty on Object { | ||
| 24 | 25 | ||
| 25 | mixin StateMixin<T> on ListNotifier { | 26 | mixin StateMixin<T> on ListNotifier { | 
| 26 | late T _value; | 27 | late T _value; | 
| 27 | - RxStatus? _status; | 28 | + GetState? _status; | 
| 28 | 29 | ||
| 29 | void _fillEmptyStatus() { | 30 | void _fillEmptyStatus() { | 
| 30 | - _status = _isNullOrEmpty(_value) ? RxStatus.loading() : RxStatus.success(); | 31 | + _status = (value == null || value!._isEmpty()) | 
| 32 | + ? GetState.loading() | ||
| 33 | + : GetState.success(_status); | ||
| 31 | } | 34 | } | 
| 32 | 35 | ||
| 33 | - RxStatus get status { | 36 | + GetState get status { | 
| 34 | reportRead(); | 37 | reportRead(); | 
| 35 | - return _status ??= _status = RxStatus.loading(); | 38 | + return _status ??= _status = GetState.loading(); | 
| 36 | } | 39 | } | 
| 37 | 40 | ||
| 38 | T get state => value; | 41 | T get state => value; | 
| @@ -51,7 +54,7 @@ mixin StateMixin<T> on ListNotifier { | @@ -51,7 +54,7 @@ mixin StateMixin<T> on ListNotifier { | ||
| 51 | } | 54 | } | 
| 52 | 55 | ||
| 53 | @protected | 56 | @protected | 
| 54 | - void change(T newState, {RxStatus? status}) { | 57 | + void change(T newState, {GetState? status}) { | 
| 55 | var _canUpdate = false; | 58 | var _canUpdate = false; | 
| 56 | if (status != null) { | 59 | if (status != null) { | 
| 57 | _status = status; | 60 | _status = status; | 
| @@ -66,12 +69,17 @@ mixin StateMixin<T> on ListNotifier { | @@ -66,12 +69,17 @@ mixin StateMixin<T> on ListNotifier { | ||
| 66 | } | 69 | } | 
| 67 | } | 70 | } | 
| 68 | 71 | ||
| 69 | - void append(Future<T> Function() body(), {String? errorMessage}) { | 72 | + void listenFuture(Future<T> Function() body(), | 
| 73 | + {String? errorMessage, bool useEmpty = true}) { | ||
| 70 | final compute = body(); | 74 | final compute = body(); | 
| 71 | compute().then((newValue) { | 75 | compute().then((newValue) { | 
| 72 | - change(newValue, status: RxStatus.success()); | 76 | + if ((newValue == null || newValue._isEmpty()) && useEmpty) { | 
| 77 | + change(newValue, status: GetState.loading()); | ||
| 78 | + } else { | ||
| 79 | + change(newValue, status: GetState.success(newValue)); | ||
| 80 | + } | ||
| 73 | }, onError: (err) { | 81 | }, onError: (err) { | 
| 74 | - change(state, status: RxStatus.error(errorMessage ?? err.toString())); | 82 | + change(state, status: GetState.error(errorMessage ?? err.toString())); | 
| 75 | }); | 83 | }); | 
| 76 | } | 84 | } | 
| 77 | } | 85 | } | 
| @@ -186,10 +194,6 @@ class Value<T> extends ListNotifier | @@ -186,10 +194,6 @@ class Value<T> extends ListNotifier | ||
| 186 | dynamic toJson() => (value as dynamic)?.toJson(); | 194 | dynamic toJson() => (value as dynamic)?.toJson(); | 
| 187 | } | 195 | } | 
| 188 | 196 | ||
| 189 | -extension ReactiveT<T> on T { | ||
| 190 | - Value<T> get reactive => Value<T>(this); | ||
| 191 | -} | ||
| 192 | - | ||
| 193 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin { | 197 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin { | 
| 194 | GetNotifier(T initial) : super(initial); | 198 | GetNotifier(T initial) : super(initial); | 
| 195 | } | 199 | } | 
| @@ -218,70 +222,32 @@ extension StateExt<T> on StateMixin<T> { | @@ -218,70 +222,32 @@ extension StateExt<T> on StateMixin<T> { | ||
| 218 | } | 222 | } | 
| 219 | } | 223 | } | 
| 220 | 224 | ||
| 221 | -class RxStatus { | ||
| 222 | - final bool isLoading; | ||
| 223 | - final bool isError; | ||
| 224 | - final bool isSuccess; | ||
| 225 | - final bool isEmpty; | ||
| 226 | - final bool isLoadingMore; | ||
| 227 | - final String? errorMessage; | ||
| 228 | - | ||
| 229 | - RxStatus._({ | ||
| 230 | - this.isEmpty = false, | ||
| 231 | - this.isLoading = false, | ||
| 232 | - this.isError = false, | ||
| 233 | - this.isSuccess = false, | ||
| 234 | - this.errorMessage, | ||
| 235 | - this.isLoadingMore = false, | ||
| 236 | - }); | ||
| 237 | - | ||
| 238 | - factory RxStatus.loading() { | ||
| 239 | - return RxStatus._(isLoading: true); | ||
| 240 | - } | ||
| 241 | - | ||
| 242 | - factory RxStatus.loadingMore() { | ||
| 243 | - return RxStatus._(isSuccess: true, isLoadingMore: true); | ||
| 244 | - } | ||
| 245 | - | ||
| 246 | - factory RxStatus.success() { | ||
| 247 | - return RxStatus._(isSuccess: true); | ||
| 248 | - } | ||
| 249 | - | ||
| 250 | - factory RxStatus.error([String? message]) { | ||
| 251 | - return RxStatus._(isError: true, errorMessage: message); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | - factory RxStatus.empty() { | ||
| 255 | - return RxStatus._(isEmpty: true); | ||
| 256 | - } | ||
| 257 | -} | ||
| 258 | - | ||
| 259 | typedef NotifierBuilder<T> = Widget Function(T state); | 225 | typedef NotifierBuilder<T> = Widget Function(T state); | 
| 260 | 226 | ||
| 261 | -abstract class GState<T> { | ||
| 262 | - const GState(); | ||
| 263 | - factory GState.loading() => GLoading(); | ||
| 264 | - factory GState.error(String message) => GError(message); | ||
| 265 | - factory GState.empty() => GEmpty(); | ||
| 266 | - factory GState.success(T data) => GSuccess(data); | 227 | +abstract class GetState<T> { | 
| 228 | + const GetState(); | ||
| 229 | + factory GetState.loading() => GLoading(); | ||
| 230 | + factory GetState.error(String message) => GError(message); | ||
| 231 | + factory GetState.empty() => GEmpty(); | ||
| 232 | + factory GetState.success(T data) => GSuccess(data); | ||
| 267 | } | 233 | } | 
| 268 | 234 | ||
| 269 | -class GLoading<T> extends GState<T> {} | 235 | +class GLoading<T> extends GetState<T> {} | 
| 270 | 236 | ||
| 271 | -class GSuccess<T> extends GState<T> { | 237 | +class GSuccess<T> extends GetState<T> { | 
| 272 | final T data; | 238 | final T data; | 
| 273 | 239 | ||
| 274 | GSuccess(this.data); | 240 | GSuccess(this.data); | 
| 275 | } | 241 | } | 
| 276 | 242 | ||
| 277 | -class GError<T, S> extends GState<T> { | 243 | +class GError<T, S> extends GetState<T> { | 
| 278 | final S? error; | 244 | final S? error; | 
| 279 | GError([this.error]); | 245 | GError([this.error]); | 
| 280 | } | 246 | } | 
| 281 | 247 | ||
| 282 | -class GEmpty<T> extends GState<T> {} | 248 | +class GEmpty<T> extends GetState<T> {} | 
| 283 | 249 | ||
| 284 | -extension StatusDataExt<T> on GState<T> { | 250 | +extension StatusDataExt<T> on GetState<T> { | 
| 285 | bool get isLoading => this is GLoading; | 251 | bool get isLoading => this is GLoading; | 
| 286 | bool get isSuccess => this is GSuccess; | 252 | bool get isSuccess => this is GSuccess; | 
| 287 | bool get isError => this is GError; | 253 | bool get isError => this is GError; | 
| @@ -72,6 +72,8 @@ mixin ScrollMixin on GetLifeCycleMixin { | @@ -72,6 +72,8 @@ mixin ScrollMixin on GetLifeCycleMixin { | ||
| 72 | 72 | ||
| 73 | abstract class RxController with GetLifeCycleMixin {} | 73 | abstract class RxController with GetLifeCycleMixin {} | 
| 74 | 74 | ||
| 75 | +abstract class StateController<T> extends GetxController with StateMixin<T> {} | ||
| 76 | + | ||
| 75 | abstract class SuperController<T> extends FullLifeCycleController | 77 | abstract class SuperController<T> extends FullLifeCycleController | 
| 76 | with FullLifeCycleMixin, StateMixin<T> {} | 78 | with FullLifeCycleMixin, StateMixin<T> {} | 
| 77 | 79 | 
| @@ -176,7 +176,9 @@ class TaskManager { | @@ -176,7 +176,9 @@ class TaskManager { | ||
| 176 | T Function() builder) { | 176 | T Function() builder) { | 
| 177 | _remove = disposers; | 177 | _remove = disposers; | 
| 178 | _setter = setState; | 178 | _setter = setState; | 
| 179 | + | ||
| 179 | final result = builder(); | 180 | final result = builder(); | 
| 181 | + print(disposers.isEmpty); | ||
| 180 | if (disposers.isEmpty) { | 182 | if (disposers.isEmpty) { | 
| 181 | throw ObxError(); | 183 | throw ObxError(); | 
| 182 | } | 184 | } | 
- 
Please register or login to post a comment