Merge branch 'master' of git://github.com/jonataslaw/getx
Showing
35 changed files
with
529 additions
and
281 deletions
No preview for this file type
| 1 | import 'package:get/get.dart'; | 1 | import 'package:get/get.dart'; | 
| 2 | + | ||
| 2 | import '../domain/entity/cases_model.dart'; | 3 | import '../domain/entity/cases_model.dart'; | 
| 3 | 4 | ||
| 4 | // ignore: one_member_abstracts | 5 | // ignore: one_member_abstracts | 
| @@ -12,6 +13,7 @@ class HomeProvider extends GetConnect implements IHomeProvider { | @@ -12,6 +13,7 @@ class HomeProvider extends GetConnect implements IHomeProvider { | ||
| 12 | httpClient.defaultDecoder = | 13 | httpClient.defaultDecoder = | 
| 13 | (val) => CasesModel.fromJson(val as Map<String, dynamic>); | 14 | (val) => CasesModel.fromJson(val as Map<String, dynamic>); | 
| 14 | httpClient.baseUrl = 'https://api.covid19api.com'; | 15 | httpClient.baseUrl = 'https://api.covid19api.com'; | 
| 16 | + super.onInit(); | ||
| 15 | } | 17 | } | 
| 16 | 18 | ||
| 17 | @override | 19 | @override | 
| @@ -19,10 +19,10 @@ class HomeController extends SuperController<CasesModel> { | @@ -19,10 +19,10 @@ class HomeController extends SuperController<CasesModel> { | ||
| 19 | Country getCountryById(String id) { | 19 | Country getCountryById(String id) { | 
| 20 | final index = int.tryParse(id); | 20 | final index = int.tryParse(id); | 
| 21 | if (index != null) { | 21 | if (index != null) { | 
| 22 | - return state!.countries[index]; | 22 | + return state.countries[index]; | 
| 23 | } | 23 | } | 
| 24 | 24 | ||
| 25 | - return state!.countries.first; | 25 | + return state.countries.first; | 
| 26 | } | 26 | } | 
| 27 | 27 | ||
| 28 | @override | 28 | @override | 
| @@ -28,9 +28,9 @@ class CountryView extends GetView<HomeController> { | @@ -28,9 +28,9 @@ class CountryView extends GetView<HomeController> { | ||
| 28 | ), | 28 | ), | 
| 29 | body: Center( | 29 | body: Center( | 
| 30 | child: ListView.builder( | 30 | child: ListView.builder( | 
| 31 | - itemCount: controller.state!.countries.length, | 31 | + itemCount: controller.state.countries.length, | 
| 32 | itemBuilder: (context, index) { | 32 | itemBuilder: (context, index) { | 
| 33 | - final country = controller.state!.countries[index]; | 33 | + final country = controller.state.countries[index]; | 
| 34 | return ListTile( | 34 | return ListTile( | 
| 35 | onTap: () { | 35 | onTap: () { | 
| 36 | //Get.rootDelegate.toNamed('/home/country'); | 36 | //Get.rootDelegate.toNamed('/home/country'); | 
| 1 | import 'dart:io'; | 1 | import 'dart:io'; | 
| 2 | import 'dart:math'; | 2 | import 'dart:math'; | 
| 3 | + | ||
| 3 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; | 
| 4 | import 'package:flutter_test/flutter_test.dart'; | 5 | import 'package:flutter_test/flutter_test.dart'; | 
| 5 | import 'package:get/get.dart'; | 6 | import 'package:get/get.dart'; | 
| @@ -81,8 +82,8 @@ void main() { | @@ -81,8 +82,8 @@ void main() { | ||
| 81 | } | 82 | } | 
| 82 | 83 | ||
| 83 | if (controller.status.isSuccess) { | 84 | if (controller.status.isSuccess) { | 
| 84 | - expect(controller.state!.global.totalDeaths, 100); | ||
| 85 | - expect(controller.state!.global.totalConfirmed, 200); | 85 | + expect(controller.state.global.totalDeaths, 100); | 
| 86 | + expect(controller.state.global.totalConfirmed, 200); | ||
| 86 | } | 87 | } | 
| 87 | }); | 88 | }); | 
| 88 | 89 | 
| @@ -100,9 +100,7 @@ class GetConnect extends GetConnectInterface { | @@ -100,9 +100,7 @@ class GetConnect extends GetConnectInterface { | ||
| 100 | this.maxAuthRetries = 1, | 100 | this.maxAuthRetries = 1, | 
| 101 | this.allowAutoSignedCert = false, | 101 | this.allowAutoSignedCert = false, | 
| 102 | this.withCredentials = false, | 102 | this.withCredentials = false, | 
| 103 | - }) { | ||
| 104 | - $configureLifeCycle(); | ||
| 105 | - } | 103 | + }); | 
| 106 | 104 | ||
| 107 | bool allowAutoSignedCert; | 105 | bool allowAutoSignedCert; | 
| 108 | String userAgent; | 106 | String userAgent; | 
| @@ -28,6 +28,7 @@ class GetHttpClient { | @@ -28,6 +28,7 @@ class GetHttpClient { | ||
| 28 | int maxAuthRetries; | 28 | int maxAuthRetries; | 
| 29 | 29 | ||
| 30 | bool sendUserAgent; | 30 | bool sendUserAgent; | 
| 31 | + bool sendContentLength; | ||
| 31 | 32 | ||
| 32 | Decoder? defaultDecoder; | 33 | Decoder? defaultDecoder; | 
| 33 | 34 | ||
| @@ -47,6 +48,7 @@ class GetHttpClient { | @@ -47,6 +48,7 @@ class GetHttpClient { | ||
| 47 | this.followRedirects = true, | 48 | this.followRedirects = true, | 
| 48 | this.maxRedirects = 5, | 49 | this.maxRedirects = 5, | 
| 49 | this.sendUserAgent = false, | 50 | this.sendUserAgent = false, | 
| 51 | + this.sendContentLength = true, | ||
| 50 | this.maxAuthRetries = 1, | 52 | this.maxAuthRetries = 1, | 
| 51 | bool allowAutoSignedCert = false, | 53 | bool allowAutoSignedCert = false, | 
| 52 | this.baseUrl, | 54 | this.baseUrl, | 
| @@ -111,7 +113,7 @@ class GetHttpClient { | @@ -111,7 +113,7 @@ class GetHttpClient { | ||
| 111 | 113 | ||
| 112 | if (body is FormData) { | 114 | if (body is FormData) { | 
| 113 | bodyBytes = await body.toBytes(); | 115 | bodyBytes = await body.toBytes(); | 
| 114 | - headers['content-length'] = bodyBytes.length.toString(); | 116 | + _setContentLenght(headers, bodyBytes.length); | 
| 115 | headers['content-type'] = | 117 | headers['content-type'] = | 
| 116 | 'multipart/form-data; boundary=${body.boundary}'; | 118 | 'multipart/form-data; boundary=${body.boundary}'; | 
| 117 | } else if (contentType != null && | 119 | } else if (contentType != null && | 
| @@ -124,21 +126,21 @@ class GetHttpClient { | @@ -124,21 +126,21 @@ class GetHttpClient { | ||
| 124 | }); | 126 | }); | 
| 125 | var formData = parts.join('&'); | 127 | var formData = parts.join('&'); | 
| 126 | bodyBytes = utf8.encode(formData); | 128 | bodyBytes = utf8.encode(formData); | 
| 127 | - headers['content-length'] = bodyBytes.length.toString(); | 129 | + _setContentLenght(headers, bodyBytes.length); | 
| 128 | headers['content-type'] = contentType; | 130 | headers['content-type'] = contentType; | 
| 129 | } else if (body is Map || body is List) { | 131 | } else if (body is Map || body is List) { | 
| 130 | var jsonString = json.encode(body); | 132 | var jsonString = json.encode(body); | 
| 131 | - | ||
| 132 | bodyBytes = utf8.encode(jsonString); | 133 | bodyBytes = utf8.encode(jsonString); | 
| 133 | - headers['content-length'] = bodyBytes.length.toString(); | 134 | + _setContentLenght(headers, bodyBytes.length); | 
| 134 | headers['content-type'] = contentType ?? defaultContentType; | 135 | headers['content-type'] = contentType ?? defaultContentType; | 
| 135 | } else if (body is String) { | 136 | } else if (body is String) { | 
| 136 | bodyBytes = utf8.encode(body); | 137 | bodyBytes = utf8.encode(body); | 
| 137 | - headers['content-length'] = bodyBytes.length.toString(); | 138 | + _setContentLenght(headers, bodyBytes.length); | 
| 139 | + | ||
| 138 | headers['content-type'] = contentType ?? defaultContentType; | 140 | headers['content-type'] = contentType ?? defaultContentType; | 
| 139 | } else if (body == null) { | 141 | } else if (body == null) { | 
| 142 | + _setContentLenght(headers, 0); | ||
| 140 | headers['content-type'] = contentType ?? defaultContentType; | 143 | headers['content-type'] = contentType ?? defaultContentType; | 
| 141 | - headers['content-length'] = '0'; | ||
| 142 | } else { | 144 | } else { | 
| 143 | if (!errorSafety) { | 145 | if (!errorSafety) { | 
| 144 | throw UnexpectedFormat('body cannot be ${body.runtimeType}'); | 146 | throw UnexpectedFormat('body cannot be ${body.runtimeType}'); | 
| @@ -162,6 +164,12 @@ class GetHttpClient { | @@ -162,6 +164,12 @@ class GetHttpClient { | ||
| 162 | ); | 164 | ); | 
| 163 | } | 165 | } | 
| 164 | 166 | ||
| 167 | + void _setContentLenght(Map<String, String> headers, int contentLength) { | ||
| 168 | + if (sendContentLength) { | ||
| 169 | + headers['content-length'] = '$contentLength'; | ||
| 170 | + } | ||
| 171 | + } | ||
| 172 | + | ||
| 165 | Stream<List<int>> _trackProgress( | 173 | Stream<List<int>> _trackProgress( | 
| 166 | List<int> bodyBytes, | 174 | List<int> bodyBytes, | 
| 167 | Progress? uploadProgress, | 175 | Progress? uploadProgress, | 
| @@ -110,11 +110,12 @@ class BaseWebSocket { | @@ -110,11 +110,12 @@ class BaseWebSocket { | ||
| 110 | return true; | 110 | return true; | 
| 111 | }; | 111 | }; | 
| 112 | 112 | ||
| 113 | - var request = await client.getUrl(Uri.parse(url)); | ||
| 114 | - request.headers.add('Connection', 'Upgrade'); | ||
| 115 | - request.headers.add('Upgrade', 'websocket'); | ||
| 116 | - request.headers.add('Sec-WebSocket-Version', '13'); | ||
| 117 | - request.headers.add('Sec-WebSocket-Key', key.toLowerCase()); | 113 | + var request = await client.getUrl(Uri.parse(url)) | 
| 114 | + ..headers.add('Connection', 'Upgrade') | ||
| 115 | + ..headers.add('Upgrade', 'websocket') | ||
| 116 | + ..headers.add('Cache-Control', 'no-cache') | ||
| 117 | + ..headers.add('Sec-WebSocket-Version', '13') | ||
| 118 | + ..headers.add('Sec-WebSocket-Key', key.toLowerCase()); | ||
| 118 | 119 | ||
| 119 | var response = await request.close(); | 120 | var response = await request.close(); | 
| 120 | // ignore: close_sinks | 121 | // ignore: close_sinks | 
| @@ -200,7 +200,8 @@ class GetInstance { | @@ -200,7 +200,8 @@ class GetInstance { | ||
| 200 | if (_singl[key]!.isSingleton!) { | 200 | if (_singl[key]!.isSingleton!) { | 
| 201 | _singl[key]!.isInit = true; | 201 | _singl[key]!.isInit = true; | 
| 202 | if (Get.smartManagement != SmartManagement.onlyBuilder) { | 202 | if (Get.smartManagement != SmartManagement.onlyBuilder) { | 
| 203 | - RouterReportManager.reportDependencyLinkedToRoute(_getKey(S, name)); | 203 | + RouterReportManager.instance | 
| 204 | + .reportDependencyLinkedToRoute(_getKey(S, name)); | ||
| 204 | } | 205 | } | 
| 205 | } | 206 | } | 
| 206 | } | 207 | } | 
| @@ -252,7 +253,7 @@ class GetInstance { | @@ -252,7 +253,7 @@ class GetInstance { | ||
| 252 | Get.log('Instance "$S" with tag "$tag" has been initialized'); | 253 | Get.log('Instance "$S" with tag "$tag" has been initialized'); | 
| 253 | } | 254 | } | 
| 254 | if (!_singl[key]!.isSingleton!) { | 255 | if (!_singl[key]!.isSingleton!) { | 
| 255 | - RouterReportManager.appendRouteByCreate(i); | 256 | + RouterReportManager.instance.appendRouteByCreate(i); | 
| 256 | } | 257 | } | 
| 257 | } | 258 | } | 
| 258 | return i; | 259 | return i; | 
| @@ -318,7 +319,7 @@ class GetInstance { | @@ -318,7 +319,7 @@ class GetInstance { | ||
| 318 | {@deprecated bool clearFactory = true, bool clearRouteBindings = true}) { | 319 | {@deprecated bool clearFactory = true, bool clearRouteBindings = true}) { | 
| 319 | // if (clearFactory) _factory.clear(); | 320 | // if (clearFactory) _factory.clear(); | 
| 320 | // deleteAll(force: true); | 321 | // deleteAll(force: true); | 
| 321 | - if (clearRouteBindings) RouterReportManager.clearRouteKeys(); | 322 | + if (clearRouteBindings) RouterReportManager.instance.clearRouteKeys(); | 
| 322 | _singl.clear(); | 323 | _singl.clear(); | 
| 323 | 324 | ||
| 324 | return true; | 325 | return true; | 
| 1 | -import '../../get_core/get_core.dart'; | ||
| 2 | - | ||
| 3 | -/// Special callable class to keep the contract of a regular method, and avoid | ||
| 4 | -/// overrides if you extend the class that uses it, as Dart has no final | ||
| 5 | -/// methods. | ||
| 6 | -/// Used in `DisposableInterface` to avoid the danger of overriding onStart. | ||
| 7 | -class InternalFinalCallback<T> { | ||
| 8 | - ValueUpdater<T>? _callback; | ||
| 9 | - | ||
| 10 | - InternalFinalCallback({ValueUpdater<T>? callback}) : _callback = callback; | ||
| 11 | - | ||
| 12 | - T call() => _callback!.call(); | ||
| 13 | -} | 1 | +import 'package:flutter/foundation.dart'; | 
| 2 | +import 'package:flutter/scheduler.dart'; | ||
| 14 | 3 | ||
| 15 | /// The [GetLifeCycle] | 4 | /// The [GetLifeCycle] | 
| 16 | /// | 5 | /// | 
| @@ -22,24 +11,10 @@ class InternalFinalCallback<T> { | @@ -22,24 +11,10 @@ class InternalFinalCallback<T> { | ||
| 22 | /// } | 11 | /// } | 
| 23 | /// ``` | 12 | /// ``` | 
| 24 | mixin GetLifeCycleBase { | 13 | mixin GetLifeCycleBase { | 
| 25 | - /// Called at the exact moment the widget is allocated in memory. | ||
| 26 | - /// It uses an internal "callable" type, to avoid any @overrides in subclases. | ||
| 27 | - /// This method should be internal and is required to define the | ||
| 28 | - /// lifetime cycle of the subclass. | ||
| 29 | - final onStart = InternalFinalCallback<void>(); | ||
| 30 | - | ||
| 31 | - // /// The `configureLifeCycle` works as a constructor for the [GetLifeCycle] | ||
| 32 | - // /// | ||
| 33 | - // /// This method must be invoked in the constructor of the implementation | ||
| 34 | - // void configureLifeCycle() { | ||
| 35 | - // if (_initialized) return; | ||
| 36 | - // } | ||
| 37 | - | ||
| 38 | - /// Internal callback that starts the cycle of this controller. | ||
| 39 | - final onDelete = InternalFinalCallback<void>(); | ||
| 40 | - | ||
| 41 | /// Called immediately after the widget is allocated in memory. | 14 | /// Called immediately after the widget is allocated in memory. | 
| 42 | /// You might use this to initialize something for the controller. | 15 | /// You might use this to initialize something for the controller. | 
| 16 | + @protected | ||
| 17 | + @mustCallSuper | ||
| 43 | void onInit() {} | 18 | void onInit() {} | 
| 44 | 19 | ||
| 45 | /// Called 1 frame after onInit(). It is the perfect place to enter | 20 | /// Called 1 frame after onInit(). It is the perfect place to enter | 
| @@ -60,8 +35,14 @@ mixin GetLifeCycleBase { | @@ -60,8 +35,14 @@ mixin GetLifeCycleBase { | ||
| 60 | /// Checks whether the controller has already been initialized. | 35 | /// Checks whether the controller has already been initialized. | 
| 61 | bool get initialized => _initialized; | 36 | bool get initialized => _initialized; | 
| 62 | 37 | ||
| 63 | - // Internal callback that starts the cycle of this controller. | ||
| 64 | - void _onStart() { | 38 | + /// Called at the exact moment the widget is allocated in memory. | 
| 39 | + /// It uses an internal "callable" type, to avoid any @overrides in subclases. | ||
| 40 | + /// This method should be internal and is required to define the | ||
| 41 | + /// lifetime cycle of the subclass. | ||
| 42 | + // @protected | ||
| 43 | + @mustCallSuper | ||
| 44 | + void onStart() { | ||
| 45 | + // _checkIfAlreadyConfigured(); | ||
| 65 | if (_initialized) return; | 46 | if (_initialized) return; | 
| 66 | onInit(); | 47 | onInit(); | 
| 67 | _initialized = true; | 48 | _initialized = true; | 
| @@ -72,31 +53,28 @@ mixin GetLifeCycleBase { | @@ -72,31 +53,28 @@ mixin GetLifeCycleBase { | ||
| 72 | /// Checks whether the controller has already been closed. | 53 | /// Checks whether the controller has already been closed. | 
| 73 | bool get isClosed => _isClosed; | 54 | bool get isClosed => _isClosed; | 
| 74 | 55 | ||
| 75 | - // Internal callback that starts the cycle of this controller. | ||
| 76 | - void _onDelete() { | 56 | + // Called when the controller is removed from memory. | 
| 57 | + @mustCallSuper | ||
| 58 | + void onDelete() { | ||
| 77 | if (_isClosed) return; | 59 | if (_isClosed) return; | 
| 78 | _isClosed = true; | 60 | _isClosed = true; | 
| 79 | onClose(); | 61 | onClose(); | 
| 80 | } | 62 | } | 
| 81 | 63 | ||
| 82 | - void $configureLifeCycle() { | ||
| 83 | - _checkIfAlreadyConfigured(); | ||
| 84 | - onStart._callback = _onStart; | ||
| 85 | - onDelete._callback = _onDelete; | ||
| 86 | - } | ||
| 87 | - | ||
| 88 | - void _checkIfAlreadyConfigured() { | ||
| 89 | - if (_initialized) { | ||
| 90 | - throw """You can only call configureLifeCycle once. | ||
| 91 | -The proper place to insert it is in your class's constructor | ||
| 92 | -that inherits GetLifeCycle."""; | ||
| 93 | - } | ||
| 94 | - } | 64 | +// void _checkIfAlreadyConfigured() { | 
| 65 | +// if (_initialized) { | ||
| 66 | +// throw """You can only call configureLifeCycle once. | ||
| 67 | +// The proper place to insert it is in your class's constructor | ||
| 68 | +// that inherits GetLifeCycle."""; | ||
| 69 | +// } | ||
| 70 | +// } | ||
| 95 | } | 71 | } | 
| 96 | 72 | ||
| 97 | abstract class GetLifeCycle with GetLifeCycleBase { | 73 | abstract class GetLifeCycle with GetLifeCycleBase { | 
| 98 | - GetLifeCycle() { | ||
| 99 | - $configureLifeCycle(); | 74 | + @override | 
| 75 | + void onInit() { | ||
| 76 | + SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); | ||
| 77 | + super.onInit(); | ||
| 100 | } | 78 | } | 
| 101 | } | 79 | } | 
| 102 | 80 | 
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | + | ||
| 2 | import '../../../get.dart'; | 3 | import '../../../get.dart'; | 
| 3 | import '../router_report.dart'; | 4 | import '../router_report.dart'; | 
| 4 | 5 | ||
| @@ -21,7 +22,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | @@ -21,7 +22,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | ||
| 21 | this.enterBottomSheetDuration = const Duration(milliseconds: 250), | 22 | this.enterBottomSheetDuration = const Duration(milliseconds: 250), | 
| 22 | this.exitBottomSheetDuration = const Duration(milliseconds: 200), | 23 | this.exitBottomSheetDuration = const Duration(milliseconds: 200), | 
| 23 | }) : super(settings: settings) { | 24 | }) : super(settings: settings) { | 
| 24 | - RouterReportManager.reportCurrentRoute(this); | 25 | + RouterReportManager.instance.reportCurrentRoute(this); | 
| 25 | } | 26 | } | 
| 26 | final bool? isPersistent; | 27 | final bool? isPersistent; | 
| 27 | final WidgetBuilder? builder; | 28 | final WidgetBuilder? builder; | 
| @@ -56,7 +57,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | @@ -56,7 +57,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> { | ||
| 56 | 57 | ||
| 57 | @override | 58 | @override | 
| 58 | void dispose() { | 59 | void dispose() { | 
| 59 | - RouterReportManager.reportRouteDispose(this); | 60 | + RouterReportManager.instance.reportRouteDispose(this); | 
| 60 | super.dispose(); | 61 | super.dispose(); | 
| 61 | } | 62 | } | 
| 62 | 63 | 
| 1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; | 
| 2 | + | ||
| 2 | import '../router_report.dart'; | 3 | import '../router_report.dart'; | 
| 3 | 4 | ||
| 4 | class GetDialogRoute<T> extends PopupRoute<T> { | 5 | class GetDialogRoute<T> extends PopupRoute<T> { | 
| @@ -17,7 +18,7 @@ class GetDialogRoute<T> extends PopupRoute<T> { | @@ -17,7 +18,7 @@ class GetDialogRoute<T> extends PopupRoute<T> { | ||
| 17 | _transitionDuration = transitionDuration, | 18 | _transitionDuration = transitionDuration, | 
| 18 | _transitionBuilder = transitionBuilder, | 19 | _transitionBuilder = transitionBuilder, | 
| 19 | super(settings: settings) { | 20 | super(settings: settings) { | 
| 20 | - RouterReportManager.reportCurrentRoute(this); | 21 | + RouterReportManager.instance.reportCurrentRoute(this); | 
| 21 | } | 22 | } | 
| 22 | 23 | ||
| 23 | final RoutePageBuilder widget; | 24 | final RoutePageBuilder widget; | 
| @@ -28,7 +29,7 @@ class GetDialogRoute<T> extends PopupRoute<T> { | @@ -28,7 +29,7 @@ class GetDialogRoute<T> extends PopupRoute<T> { | ||
| 28 | 29 | ||
| 29 | @override | 30 | @override | 
| 30 | void dispose() { | 31 | void dispose() { | 
| 31 | - RouterReportManager.reportRouteDispose(this); | 32 | + RouterReportManager.instance.reportRouteDispose(this); | 
| 32 | super.dispose(); | 33 | super.dispose(); | 
| 33 | } | 34 | } | 
| 34 | 35 | 
| @@ -511,6 +511,7 @@ extension GetNavigation on GetInterface { | @@ -511,6 +511,7 @@ extension GetNavigation on GetInterface { | ||
| 511 | Bindings? binding, | 511 | Bindings? binding, | 
| 512 | bool preventDuplicates = true, | 512 | bool preventDuplicates = true, | 
| 513 | bool? popGesture, | 513 | bool? popGesture, | 
| 514 | + bool showCupertinoParallax = true, | ||
| 514 | double Function(BuildContext context)? gestureWidth, | 515 | double Function(BuildContext context)? gestureWidth, | 
| 515 | }) { | 516 | }) { | 
| 516 | // var routeName = "/${page.runtimeType}"; | 517 | // var routeName = "/${page.runtimeType}"; | 
| @@ -525,6 +526,7 @@ extension GetNavigation on GetInterface { | @@ -525,6 +526,7 @@ extension GetNavigation on GetInterface { | ||
| 525 | page: _resolvePage(page, 'to'), | 526 | page: _resolvePage(page, 'to'), | 
| 526 | routeName: routeName, | 527 | routeName: routeName, | 
| 527 | gestureWidth: gestureWidth, | 528 | gestureWidth: gestureWidth, | 
| 529 | + showCupertinoParallax: showCupertinoParallax, | ||
| 528 | settings: RouteSettings( | 530 | settings: RouteSettings( | 
| 529 | name: routeName, | 531 | name: routeName, | 
| 530 | arguments: arguments, | 532 | arguments: arguments, | 
| @@ -7,28 +7,30 @@ import '../../get.dart'; | @@ -7,28 +7,30 @@ import '../../get.dart'; | ||
| 7 | class RouterReportManager<T> { | 7 | class RouterReportManager<T> { | 
| 8 | /// Holds a reference to `Get.reference` when the Instance was | 8 | /// Holds a reference to `Get.reference` when the Instance was | 
| 9 | /// created to manage the memory. | 9 | /// created to manage the memory. | 
| 10 | - static final Map<Route?, List<String>> _routesKey = {}; | 10 | + final Map<T?, List<String>> _routesKey = {}; | 
| 11 | 11 | ||
| 12 | /// Stores the onClose() references of instances created with `Get.create()` | 12 | /// Stores the onClose() references of instances created with `Get.create()` | 
| 13 | /// using the `Get.reference`. | 13 | /// using the `Get.reference`. | 
| 14 | /// Experimental feature to keep the lifecycle and memory management with | 14 | /// Experimental feature to keep the lifecycle and memory management with | 
| 15 | /// non-singleton instances. | 15 | /// non-singleton instances. | 
| 16 | - static final Map<Route?, HashSet<Function>> _routesByCreate = {}; | 16 | + final Map<T?, HashSet<Function>> _routesByCreate = {}; | 
| 17 | + | ||
| 18 | + static late final RouterReportManager instance = RouterReportManager(); | ||
| 17 | 19 | ||
| 18 | void printInstanceStack() { | 20 | void printInstanceStack() { | 
| 19 | Get.log(_routesKey.toString()); | 21 | Get.log(_routesKey.toString()); | 
| 20 | } | 22 | } | 
| 21 | 23 | ||
| 22 | - static Route? _current; | 24 | + T? _current; | 
| 23 | 25 | ||
| 24 | // ignore: use_setters_to_change_properties | 26 | // ignore: use_setters_to_change_properties | 
| 25 | - static void reportCurrentRoute(Route newRoute) { | 27 | + void reportCurrentRoute(T newRoute) { | 
| 26 | _current = newRoute; | 28 | _current = newRoute; | 
| 27 | } | 29 | } | 
| 28 | 30 | ||
| 29 | /// Links a Class instance [S] (or [tag]) to the current route. | 31 | /// Links a Class instance [S] (or [tag]) to the current route. | 
| 30 | /// Requires usage of `GetMaterialApp`. | 32 | /// Requires usage of `GetMaterialApp`. | 
| 31 | - static void reportDependencyLinkedToRoute(String depedencyKey) { | 33 | + void reportDependencyLinkedToRoute(String depedencyKey) { | 
| 32 | if (_current == null) return; | 34 | if (_current == null) return; | 
| 33 | if (_routesKey.containsKey(_current)) { | 35 | if (_routesKey.containsKey(_current)) { | 
| 34 | _routesKey[_current!]!.add(depedencyKey); | 36 | _routesKey[_current!]!.add(depedencyKey); | 
| @@ -37,18 +39,18 @@ class RouterReportManager<T> { | @@ -37,18 +39,18 @@ class RouterReportManager<T> { | ||
| 37 | } | 39 | } | 
| 38 | } | 40 | } | 
| 39 | 41 | ||
| 40 | - static void clearRouteKeys() { | 42 | + void clearRouteKeys() { | 
| 41 | _routesKey.clear(); | 43 | _routesKey.clear(); | 
| 42 | _routesByCreate.clear(); | 44 | _routesByCreate.clear(); | 
| 43 | } | 45 | } | 
| 44 | 46 | ||
| 45 | - static void appendRouteByCreate(GetLifeCycleBase i) { | 47 | + void appendRouteByCreate(GetLifeCycleBase i) { | 
| 46 | _routesByCreate[_current] ??= HashSet<Function>(); | 48 | _routesByCreate[_current] ??= HashSet<Function>(); | 
| 47 | // _routesByCreate[Get.reference]!.add(i.onDelete as Function); | 49 | // _routesByCreate[Get.reference]!.add(i.onDelete as Function); | 
| 48 | _routesByCreate[_current]!.add(i.onDelete); | 50 | _routesByCreate[_current]!.add(i.onDelete); | 
| 49 | } | 51 | } | 
| 50 | 52 | ||
| 51 | - static void reportRouteDispose(Route disposed) { | 53 | + void reportRouteDispose(T disposed) { | 
| 52 | if (Get.smartManagement != SmartManagement.onlyBuilder) { | 54 | if (Get.smartManagement != SmartManagement.onlyBuilder) { | 
| 53 | WidgetsBinding.instance!.addPostFrameCallback((_) { | 55 | WidgetsBinding.instance!.addPostFrameCallback((_) { | 
| 54 | _removeDependencyByRoute(disposed); | 56 | _removeDependencyByRoute(disposed); | 
| @@ -56,7 +58,7 @@ class RouterReportManager<T> { | @@ -56,7 +58,7 @@ class RouterReportManager<T> { | ||
| 56 | } | 58 | } | 
| 57 | } | 59 | } | 
| 58 | 60 | ||
| 59 | - static void reportRouteWillDispose(Route disposed) { | 61 | + void reportRouteWillDispose(T disposed) { | 
| 60 | final keysToRemove = <String>[]; | 62 | final keysToRemove = <String>[]; | 
| 61 | 63 | ||
| 62 | _routesKey[disposed]?.forEach(keysToRemove.add); | 64 | _routesKey[disposed]?.forEach(keysToRemove.add); | 
| @@ -85,7 +87,7 @@ class RouterReportManager<T> { | @@ -85,7 +87,7 @@ class RouterReportManager<T> { | ||
| 85 | /// using `Get.smartManagement` as [SmartManagement.full] or | 87 | /// using `Get.smartManagement` as [SmartManagement.full] or | 
| 86 | /// [SmartManagement.keepFactory] | 88 | /// [SmartManagement.keepFactory] | 
| 87 | /// Meant for internal usage of `GetPageRoute` and `GetDialogRoute` | 89 | /// Meant for internal usage of `GetPageRoute` and `GetDialogRoute` | 
| 88 | - static void _removeDependencyByRoute(Route routeName) { | 90 | + void _removeDependencyByRoute(T routeName) { | 
| 89 | final keysToRemove = <String>[]; | 91 | final keysToRemove = <String>[]; | 
| 90 | 92 | ||
| 91 | _routesKey[routeName]?.forEach(keysToRemove.add); | 93 | _routesKey[routeName]?.forEach(keysToRemove.add); | 
| @@ -8,18 +8,20 @@ mixin PageRouteReportMixin<T> on Route<T> { | @@ -8,18 +8,20 @@ mixin PageRouteReportMixin<T> on Route<T> { | ||
| 8 | @override | 8 | @override | 
| 9 | void install() { | 9 | void install() { | 
| 10 | super.install(); | 10 | super.install(); | 
| 11 | - RouterReportManager.reportCurrentRoute(this); | 11 | + RouterReportManager.instance.reportCurrentRoute(this); | 
| 12 | } | 12 | } | 
| 13 | 13 | ||
| 14 | @override | 14 | @override | 
| 15 | void dispose() { | 15 | void dispose() { | 
| 16 | super.dispose(); | 16 | super.dispose(); | 
| 17 | - RouterReportManager.reportRouteDispose(this); | 17 | + RouterReportManager.instance.reportRouteDispose(this); | 
| 18 | } | 18 | } | 
| 19 | } | 19 | } | 
| 20 | 20 | ||
| 21 | -class GetPageRoute<T> extends PageRoute<T> | ||
| 22 | - with GetPageRouteTransitionMixin<T>, PageRouteReportMixin { | 21 | +class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T> | 
| 22 | + with | ||
| 23 | + GetPageRouteTransitionMixin<T>, | ||
| 24 | + PageRouteReportMixin { | ||
| 23 | /// Creates a page route for use in an iOS designed app. | 25 | /// Creates a page route for use in an iOS designed app. | 
| 24 | /// | 26 | /// | 
| 25 | /// The [builder], [maintainState], and [fullscreenDialog] arguments must not | 27 | /// The [builder], [maintainState], and [fullscreenDialog] arguments must not | 
| @@ -47,7 +49,11 @@ class GetPageRoute<T> extends PageRoute<T> | @@ -47,7 +49,11 @@ class GetPageRoute<T> extends PageRoute<T> | ||
| 47 | this.maintainState = true, | 49 | this.maintainState = true, | 
| 48 | bool fullscreenDialog = false, | 50 | bool fullscreenDialog = false, | 
| 49 | this.middlewares, | 51 | this.middlewares, | 
| 50 | - }) : super(settings: settings, fullscreenDialog: fullscreenDialog); | 52 | + }) : super( | 
| 53 | + settings: settings, | ||
| 54 | + fullscreenDialog: fullscreenDialog, | ||
| 55 | + // builder: (context) => Container(), | ||
| 56 | + ); | ||
| 51 | 57 | ||
| 52 | @override | 58 | @override | 
| 53 | final Duration transitionDuration; | 59 | final Duration transitionDuration; | 
| @@ -322,7 +322,6 @@ Cannot read the previousTitle for a route that has not yet been installed''', | @@ -322,7 +322,6 @@ Cannot read the previousTitle for a route that has not yet been installed''', | ||
| 322 | bool canTransitionTo(TransitionRoute<dynamic> nextRoute) { | 322 | bool canTransitionTo(TransitionRoute<dynamic> nextRoute) { | 
| 323 | // Don't perform outgoing animation if the next route is a | 323 | // Don't perform outgoing animation if the next route is a | 
| 324 | // fullscreen dialog. | 324 | // fullscreen dialog. | 
| 325 | - | ||
| 326 | return (nextRoute is GetPageRouteTransitionMixin && | 325 | return (nextRoute is GetPageRouteTransitionMixin && | 
| 327 | !nextRoute.fullscreenDialog && | 326 | !nextRoute.fullscreenDialog && | 
| 328 | nextRoute.showCupertinoParallax) || | 327 | nextRoute.showCupertinoParallax) || | 
lib/get_navigation/src/routes/modules.dart
0 → 100644
| 1 | +// import 'package:flutter/material.dart'; | ||
| 2 | +// import 'package:get/get_navigation/src/router_report.dart'; | ||
| 3 | +// import 'package:get/instance_manager.dart'; | ||
| 4 | + | ||
| 5 | +// class Dependencies { | ||
| 6 | +// void lazyPut<S>(InstanceBuilderCallback<S> builder, | ||
| 7 | +// {String? tag, bool fenix = false}) { | ||
| 8 | +// GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix); | ||
| 9 | +// } | ||
| 10 | + | ||
| 11 | +// S call<S>() { | ||
| 12 | +// return find<S>(); | ||
| 13 | +// } | ||
| 14 | + | ||
| 15 | +// Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder, | ||
| 16 | +// {String? tag, bool permanent = false}) async => | ||
| 17 | +// GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent); | ||
| 18 | + | ||
| 19 | +// void create<S>(InstanceBuilderCallback<S> builder, | ||
| 20 | +// {String? tag, bool permanent = true}) => | ||
| 21 | +// GetInstance().create<S>(builder, tag: tag, permanent: permanent); | ||
| 22 | + | ||
| 23 | +// S find<S>({String? tag}) => GetInstance().find<S>(tag: tag); | ||
| 24 | + | ||
| 25 | +// S put<S>(S dependency, | ||
| 26 | +// {String? tag, | ||
| 27 | +// bool permanent = false, | ||
| 28 | +// InstanceBuilderCallback<S>? builder}) => | ||
| 29 | +// GetInstance().put<S>(dependency, tag: tag, permanent: permanent); | ||
| 30 | + | ||
| 31 | +// Future<bool> delete<S>({String? tag, bool force = false}) async => | ||
| 32 | +// GetInstance().delete<S>(tag: tag, force: force); | ||
| 33 | + | ||
| 34 | +// Future<void> deleteAll({bool force = false}) async => | ||
| 35 | +// GetInstance().deleteAll(force: force); | ||
| 36 | + | ||
| 37 | +// void reloadAll({bool force = false}) => GetInstance().reloadAll(force: force); | ||
| 38 | + | ||
| 39 | +// void reload<S>({String? tag, String? key, bool force = false}) => | ||
| 40 | +// GetInstance().reload<S>(tag: tag, key: key, force: force); | ||
| 41 | + | ||
| 42 | +// bool isRegistered<S>({String? tag}) => | ||
| 43 | +// GetInstance().isRegistered<S>(tag: tag); | ||
| 44 | + | ||
| 45 | +// bool isPrepared<S>({String? tag}) => GetInstance().isPrepared<S>(tag: tag); | ||
| 46 | + | ||
| 47 | +// void replace<P>(P child, {String? tag}) { | ||
| 48 | +// final info = GetInstance().getInstanceInfo<P>(tag: tag); | ||
| 49 | +// final permanent = (info.isPermanent ?? false); | ||
| 50 | +// delete<P>(tag: tag, force: permanent); | ||
| 51 | +// put(child, tag: tag, permanent: permanent); | ||
| 52 | +// } | ||
| 53 | + | ||
| 54 | +// void lazyReplace<P>(InstanceBuilderCallback<P> builder, | ||
| 55 | +// {String? tag, bool? fenix}) { | ||
| 56 | +// final info = GetInstance().getInstanceInfo<P>(tag: tag); | ||
| 57 | +// final permanent = (info.isPermanent ?? false); | ||
| 58 | +// delete<P>(tag: tag, force: permanent); | ||
| 59 | +// lazyPut(builder, tag: tag, fenix: fenix ?? permanent); | ||
| 60 | +// } | ||
| 61 | +// } | ||
| 62 | + | ||
| 63 | +// abstract class Module extends StatefulWidget { | ||
| 64 | +// Module({Key? key}) : super(key: key); | ||
| 65 | + | ||
| 66 | +// Widget view(BuildContext context); | ||
| 67 | + | ||
| 68 | +// void dependencies(Dependencies i); | ||
| 69 | + | ||
| 70 | +// @override | ||
| 71 | +// _ModuleState createState() => _ModuleState(); | ||
| 72 | +// } | ||
| 73 | + | ||
| 74 | +// class _ModuleState extends State<Module> { | ||
| 75 | +// @override | ||
| 76 | +// void initState() { | ||
| 77 | +// RouterReportManager.instance.reportCurrentRoute(this); | ||
| 78 | +// widget.dependencies(Dependencies()); | ||
| 79 | +// super.initState(); | ||
| 80 | +// } | ||
| 81 | + | ||
| 82 | +// @override | ||
| 83 | +// void dispose() { | ||
| 84 | +// RouterReportManager.instance.reportRouteDispose(this); | ||
| 85 | +// super.dispose(); | ||
| 86 | +// } | ||
| 87 | + | ||
| 88 | +// @override | ||
| 89 | +// Widget build(BuildContext context) { | ||
| 90 | +// return widget.view(context); | ||
| 91 | +// } | ||
| 92 | +// } | 
| @@ -52,7 +52,7 @@ class GetObserver extends NavigatorObserver { | @@ -52,7 +52,7 @@ class GetObserver extends NavigatorObserver { | ||
| 52 | Get.log("CLOSE TO ROUTE ${currentRoute.name}"); | 52 | Get.log("CLOSE TO ROUTE ${currentRoute.name}"); | 
| 53 | } | 53 | } | 
| 54 | if (previousRoute != null) { | 54 | if (previousRoute != null) { | 
| 55 | - RouterReportManager.reportCurrentRoute(previousRoute); | 55 | + RouterReportManager.instance.reportCurrentRoute(previousRoute); | 
| 56 | } | 56 | } | 
| 57 | 57 | ||
| 58 | // Here we use a 'inverse didPush set', meaning that we use | 58 | // Here we use a 'inverse didPush set', meaning that we use | 
| @@ -97,7 +97,7 @@ class GetObserver extends NavigatorObserver { | @@ -97,7 +97,7 @@ class GetObserver extends NavigatorObserver { | ||
| 97 | Get.log("GOING TO ROUTE ${newRoute.name}"); | 97 | Get.log("GOING TO ROUTE ${newRoute.name}"); | 
| 98 | } | 98 | } | 
| 99 | 99 | ||
| 100 | - RouterReportManager.reportCurrentRoute(route); | 100 | + RouterReportManager.instance.reportCurrentRoute(route); | 
| 101 | _routeSend?.update((value) { | 101 | _routeSend?.update((value) { | 
| 102 | // Only PageRoute is allowed to change current value | 102 | // Only PageRoute is allowed to change current value | 
| 103 | if (route is PageRoute) { | 103 | if (route is PageRoute) { | 
| @@ -142,7 +142,7 @@ class GetObserver extends NavigatorObserver { | @@ -142,7 +142,7 @@ class GetObserver extends NavigatorObserver { | ||
| 142 | }); | 142 | }); | 
| 143 | 143 | ||
| 144 | if (route is GetPageRoute) { | 144 | if (route is GetPageRoute) { | 
| 145 | - RouterReportManager.reportRouteWillDispose(route); | 145 | + RouterReportManager.instance.reportRouteWillDispose(route); | 
| 146 | } | 146 | } | 
| 147 | routing?.call(_routeSend); | 147 | routing?.call(_routeSend); | 
| 148 | } | 148 | } | 
| @@ -158,7 +158,7 @@ class GetObserver extends NavigatorObserver { | @@ -158,7 +158,7 @@ class GetObserver extends NavigatorObserver { | ||
| 158 | Get.log("NEW ROUTE $newName"); | 158 | Get.log("NEW ROUTE $newName"); | 
| 159 | 159 | ||
| 160 | if (newRoute != null) { | 160 | if (newRoute != null) { | 
| 161 | - RouterReportManager.reportCurrentRoute(newRoute); | 161 | + RouterReportManager.instance.reportCurrentRoute(newRoute); | 
| 162 | } | 162 | } | 
| 163 | 163 | ||
| 164 | _routeSend?.update((value) { | 164 | _routeSend?.update((value) { | 
| @@ -178,7 +178,7 @@ class GetObserver extends NavigatorObserver { | @@ -178,7 +178,7 @@ class GetObserver extends NavigatorObserver { | ||
| 178 | value.isDialog = currentRoute.isDialog ? false : value.isDialog; | 178 | value.isDialog = currentRoute.isDialog ? false : value.isDialog; | 
| 179 | }); | 179 | }); | 
| 180 | if (oldRoute is GetPageRoute) { | 180 | if (oldRoute is GetPageRoute) { | 
| 181 | - RouterReportManager.reportRouteWillDispose(oldRoute); | 181 | + RouterReportManager.instance.reportRouteWillDispose(oldRoute); | 
| 182 | } | 182 | } | 
| 183 | 183 | ||
| 184 | routing?.call(_routeSend); | 184 | routing?.call(_routeSend); | 
| @@ -87,11 +87,19 @@ class SnackbarController { | @@ -87,11 +87,19 @@ class SnackbarController { | ||
| 87 | } | 87 | } | 
| 88 | } | 88 | } | 
| 89 | 89 | ||
| 90 | + bool _isTesting = false; | ||
| 91 | + | ||
| 90 | void _configureOverlay() { | 92 | void _configureOverlay() { | 
| 91 | - _overlayState = Overlay.of(Get.overlayContext!); | 93 | + final overlayContext = Get.overlayContext; | 
| 94 | + _isTesting = overlayContext == null; | ||
| 95 | + _overlayState = | ||
| 96 | + _isTesting ? OverlayState() : Overlay.of(Get.overlayContext!); | ||
| 92 | _overlayEntries.clear(); | 97 | _overlayEntries.clear(); | 
| 93 | _overlayEntries.addAll(_createOverlayEntries(_getBodyWidget())); | 98 | _overlayEntries.addAll(_createOverlayEntries(_getBodyWidget())); | 
| 99 | + if (!_isTesting) { | ||
| 94 | _overlayState!.insertAll(_overlayEntries); | 100 | _overlayState!.insertAll(_overlayEntries); | 
| 101 | + } | ||
| 102 | + | ||
| 95 | _configureSnackBarDisplay(); | 103 | _configureSnackBarDisplay(); | 
| 96 | } | 104 | } | 
| 97 | 105 | ||
| @@ -316,9 +324,11 @@ class SnackbarController { | @@ -316,9 +324,11 @@ class SnackbarController { | ||
| 316 | } | 324 | } | 
| 317 | 325 | ||
| 318 | void _removeOverlay() { | 326 | void _removeOverlay() { | 
| 327 | + if (!_isTesting) { | ||
| 319 | for (var element in _overlayEntries) { | 328 | for (var element in _overlayEntries) { | 
| 320 | element.remove(); | 329 | element.remove(); | 
| 321 | } | 330 | } | 
| 331 | + } | ||
| 322 | 332 | ||
| 323 | assert(!_transitionCompleter.isCompleted, | 333 | assert(!_transitionCompleter.isCompleted, | 
| 324 | 'Cannot remove overlay from a disposed snackbar'); | 334 | 'Cannot remove overlay from a disposed snackbar'); | 
| @@ -14,6 +14,22 @@ class GetStream<T> { | @@ -14,6 +14,22 @@ class GetStream<T> { | ||
| 14 | FutureOr<void> Function()? onCancel; | 14 | FutureOr<void> Function()? onCancel; | 
| 15 | 15 | ||
| 16 | GetStream({this.onListen, this.onPause, this.onResume, this.onCancel}); | 16 | GetStream({this.onListen, this.onPause, this.onResume, this.onCancel}); | 
| 17 | + | ||
| 18 | + factory GetStream.fromValue(T value, | ||
| 19 | + {Function()? onListen, | ||
| 20 | + Function()? onPause, | ||
| 21 | + Function()? onResume, | ||
| 22 | + FutureOr<void> Function()? onCancel}) { | ||
| 23 | + final valuedStream = GetStream<T>( | ||
| 24 | + onListen: onListen, | ||
| 25 | + onPause: onPause, | ||
| 26 | + onResume: onResume, | ||
| 27 | + onCancel: onCancel) | ||
| 28 | + .._value = value; | ||
| 29 | + | ||
| 30 | + return valuedStream; | ||
| 31 | + } | ||
| 32 | + | ||
| 17 | List<LightSubscription<T>>? _onData = <LightSubscription<T>>[]; | 33 | List<LightSubscription<T>>? _onData = <LightSubscription<T>>[]; | 
| 18 | 34 | ||
| 19 | bool? _isBusy = false; | 35 | bool? _isBusy = false; | 
| @@ -87,9 +103,12 @@ class GetStream<T> { | @@ -87,9 +103,12 @@ class GetStream<T> { | ||
| 87 | _isBusy = false; | 103 | _isBusy = false; | 
| 88 | } | 104 | } | 
| 89 | 105 | ||
| 90 | - T? _value; | 106 | + late T _value; | 
| 91 | 107 | ||
| 92 | - T? get value => _value; | 108 | + T get value { | 
| 109 | + RxInterface.proxy?.addListener(this); | ||
| 110 | + return _value; | ||
| 111 | + } | ||
| 93 | 112 | ||
| 94 | void add(T event) { | 113 | void add(T event) { | 
| 95 | assert(!isClosed, 'You cannot add event to closed Stream'); | 114 | assert(!isClosed, 'You cannot add event to closed Stream'); | 
| @@ -109,7 +128,7 @@ class GetStream<T> { | @@ -109,7 +128,7 @@ class GetStream<T> { | ||
| 109 | _notifyDone(); | 128 | _notifyDone(); | 
| 110 | _onData = null; | 129 | _onData = null; | 
| 111 | _isBusy = null; | 130 | _isBusy = null; | 
| 112 | - _value = null; | 131 | + // _value = null; | 
| 113 | } | 132 | } | 
| 114 | 133 | ||
| 115 | LightSubscription<T> listen(void Function(T event) onData, | 134 | LightSubscription<T> listen(void Function(T event) onData, | 
| @@ -2,7 +2,10 @@ library rx_stream; | @@ -2,7 +2,10 @@ library rx_stream; | ||
| 2 | 2 | ||
| 3 | import 'dart:async'; | 3 | import 'dart:async'; | 
| 4 | 4 | ||
| 5 | +import 'package:get/get_state_manager/src/simple/list_notifier.dart'; | ||
| 6 | + | ||
| 5 | import '../rx_typedefs/rx_typedefs.dart'; | 7 | import '../rx_typedefs/rx_typedefs.dart'; | 
| 8 | +import '../rx_types/rx_types.dart'; | ||
| 6 | 9 | ||
| 7 | part 'get_stream.dart'; | 10 | part 'get_stream.dart'; | 
| 8 | part 'mini_stream.dart'; | 11 | part 'mini_stream.dart'; | 
| @@ -5,7 +5,7 @@ part of rx_types; | @@ -5,7 +5,7 @@ part of rx_types; | ||
| 5 | /// of those `Widgets` and Rx values. | 5 | /// of those `Widgets` and Rx values. | 
| 6 | 6 | ||
| 7 | mixin RxObjectMixin<T> on NotifyManager<T> { | 7 | mixin RxObjectMixin<T> on NotifyManager<T> { | 
| 8 | - late T _value; | 8 | + //late T _value; | 
| 9 | 9 | ||
| 10 | /// Makes a direct update of [value] adding it to the Stream | 10 | /// Makes a direct update of [value] adding it to the Stream | 
| 11 | /// useful when you make use of Rx for custom Types to referesh your UI. | 11 | /// useful when you make use of Rx for custom Types to referesh your UI. | 
| @@ -91,24 +91,25 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | @@ -91,24 +91,25 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | ||
| 91 | 91 | ||
| 92 | @override | 92 | @override | 
| 93 | // ignore: avoid_equals_and_hash_code_on_mutable_classes | 93 | // ignore: avoid_equals_and_hash_code_on_mutable_classes | 
| 94 | - int get hashCode => _value.hashCode; | 94 | + int get hashCode => value.hashCode; | 
| 95 | 95 | ||
| 96 | /// Updates the [value] and adds it to the stream, updating the observer | 96 | /// Updates the [value] and adds it to the stream, updating the observer | 
| 97 | /// Widget, only if it's different from the previous value. | 97 | /// Widget, only if it's different from the previous value. | 
| 98 | set value(T val) { | 98 | set value(T val) { | 
| 99 | if (subject.isClosed) return; | 99 | if (subject.isClosed) return; | 
| 100 | sentToStream = false; | 100 | sentToStream = false; | 
| 101 | - if (_value == val && !firstRebuild) return; | 101 | + if (value == val && !firstRebuild) return; | 
| 102 | firstRebuild = false; | 102 | firstRebuild = false; | 
| 103 | - _value = val; | 103 | + // _value = val; | 
| 104 | sentToStream = true; | 104 | sentToStream = true; | 
| 105 | - subject.add(_value); | 105 | + subject.add(val); | 
| 106 | } | 106 | } | 
| 107 | 107 | ||
| 108 | /// Returns the current [value] | 108 | /// Returns the current [value] | 
| 109 | T get value { | 109 | T get value { | 
| 110 | - RxInterface.proxy?.addListener(subject); | ||
| 111 | - return _value; | 110 | + return subject.value; | 
| 111 | + //RxInterface.proxy?.addListener(subject); | ||
| 112 | + // return _value; | ||
| 112 | } | 113 | } | 
| 113 | 114 | ||
| 114 | Stream<T> get stream => subject.stream; | 115 | Stream<T> get stream => subject.stream; | 
| @@ -192,7 +193,7 @@ mixin NotifyManager<T> { | @@ -192,7 +193,7 @@ mixin NotifyManager<T> { | ||
| 192 | /// Base Rx class that manages all the stream logic for any Type. | 193 | /// Base Rx class that manages all the stream logic for any Type. | 
| 193 | abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | 194 | abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | 
| 194 | _RxImpl(T initial) { | 195 | _RxImpl(T initial) { | 
| 195 | - _value = initial; | 196 | + subject = GetStream.fromValue(initial); | 
| 196 | } | 197 | } | 
| 197 | 198 | ||
| 198 | void addError(Object error, [StackTrace? stackTrace]) { | 199 | void addError(Object error, [StackTrace? stackTrace]) { | 
| @@ -222,8 +223,8 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | @@ -222,8 +223,8 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | ||
| 222 | /// print( person ); | 223 | /// print( person ); | 
| 223 | /// ``` | 224 | /// ``` | 
| 224 | void update(void fn(T? val)) { | 225 | void update(void fn(T? val)) { | 
| 225 | - fn(_value); | ||
| 226 | - subject.add(_value); | 226 | + fn(value); | 
| 227 | + subject.add(value); | ||
| 227 | } | 228 | } | 
| 228 | 229 | ||
| 229 | /// Following certain practices on Rx data, we might want to react to certain | 230 | /// Following certain practices on Rx data, we might want to react to certain | 
| @@ -295,7 +296,7 @@ extension RxBoolExt on Rx<bool> { | @@ -295,7 +296,7 @@ extension RxBoolExt on Rx<bool> { | ||
| 295 | /// not really a dart thing since we have '..' operator | 296 | /// not really a dart thing since we have '..' operator | 
| 296 | // ignore: avoid_returning_this | 297 | // ignore: avoid_returning_this | 
| 297 | Rx<bool> toggle() { | 298 | Rx<bool> toggle() { | 
| 298 | - subject.add(_value = !_value); | 299 | + subject.add(!value); | 
| 299 | return this; | 300 | return this; | 
| 300 | } | 301 | } | 
| 301 | } | 302 | } | 
| @@ -327,8 +328,8 @@ extension RxnBoolExt on Rx<bool?> { | @@ -327,8 +328,8 @@ extension RxnBoolExt on Rx<bool?> { | ||
| 327 | /// not really a dart thing since we have '..' operator | 328 | /// not really a dart thing since we have '..' operator | 
| 328 | // ignore: avoid_returning_this | 329 | // ignore: avoid_returning_this | 
| 329 | Rx<bool?>? toggle() { | 330 | Rx<bool?>? toggle() { | 
| 330 | - if (_value != null) { | ||
| 331 | - subject.add(_value = !_value!); | 331 | + if (value != null) { | 
| 332 | + subject.add(!value!); | ||
| 332 | return this; | 333 | return this; | 
| 333 | } | 334 | } | 
| 334 | } | 335 | } | 
| 1 | part of rx_types; | 1 | part of rx_types; | 
| 2 | 2 | ||
| 3 | extension RxStringExt on Rx<String> { | 3 | extension RxStringExt on Rx<String> { | 
| 4 | - String operator +(String val) => _value + val; | 4 | + String operator +(String val) => value + val; | 
| 5 | 5 | ||
| 6 | int compareTo(String other) { | 6 | int compareTo(String other) { | 
| 7 | return value.compareTo(other); | 7 | return value.compareTo(other); | 
| @@ -125,7 +125,7 @@ extension RxStringExt on Rx<String> { | @@ -125,7 +125,7 @@ extension RxStringExt on Rx<String> { | ||
| 125 | } | 125 | } | 
| 126 | 126 | ||
| 127 | extension RxnStringExt on Rx<String?> { | 127 | extension RxnStringExt on Rx<String?> { | 
| 128 | - String operator +(String val) => (_value ?? '') + val; | 128 | + String operator +(String val) => (value ?? '') + val; | 
| 129 | 129 | ||
| 130 | int? compareTo(String other) { | 130 | int? compareTo(String other) { | 
| 131 | return value?.compareTo(other); | 131 | return value?.compareTo(other); | 
| @@ -5,7 +5,7 @@ class RxList<E> extends ListMixin<E> | @@ -5,7 +5,7 @@ class RxList<E> extends ListMixin<E> | ||
| 5 | with NotifyManager<List<E>>, RxObjectMixin<List<E>> | 5 | with NotifyManager<List<E>>, RxObjectMixin<List<E>> | 
| 6 | implements RxInterface<List<E>> { | 6 | implements RxInterface<List<E>> { | 
| 7 | RxList([List<E> initial = const []]) { | 7 | RxList([List<E> initial = const []]) { | 
| 8 | - _value = List.from(initial); | 8 | + subject = GetStream.fromValue(List.from(initial)); | 
| 9 | } | 9 | } | 
| 10 | 10 | ||
| 11 | factory RxList.filled(int length, E fill, {bool growable = false}) { | 11 | factory RxList.filled(int length, E fill, {bool growable = false}) { | 
| @@ -42,7 +42,7 @@ class RxList<E> extends ListMixin<E> | @@ -42,7 +42,7 @@ class RxList<E> extends ListMixin<E> | ||
| 42 | 42 | ||
| 43 | @override | 43 | @override | 
| 44 | void operator []=(int index, E val) { | 44 | void operator []=(int index, E val) { | 
| 45 | - _value[index] = val; | 45 | + value[index] = val; | 
| 46 | refresh(); | 46 | refresh(); | 
| 47 | } | 47 | } | 
| 48 | 48 | ||
| @@ -62,25 +62,25 @@ class RxList<E> extends ListMixin<E> | @@ -62,25 +62,25 @@ class RxList<E> extends ListMixin<E> | ||
| 62 | 62 | ||
| 63 | @override | 63 | @override | 
| 64 | void add(E item) { | 64 | void add(E item) { | 
| 65 | - _value.add(item); | 65 | + value.add(item); | 
| 66 | refresh(); | 66 | refresh(); | 
| 67 | } | 67 | } | 
| 68 | 68 | ||
| 69 | @override | 69 | @override | 
| 70 | void addAll(Iterable<E> item) { | 70 | void addAll(Iterable<E> item) { | 
| 71 | - _value.addAll(item); | 71 | + value.addAll(item); | 
| 72 | refresh(); | 72 | refresh(); | 
| 73 | } | 73 | } | 
| 74 | 74 | ||
| 75 | @override | 75 | @override | 
| 76 | void removeWhere(bool test(E element)) { | 76 | void removeWhere(bool test(E element)) { | 
| 77 | - _value.removeWhere(test); | 77 | + value.removeWhere(test); | 
| 78 | refresh(); | 78 | refresh(); | 
| 79 | } | 79 | } | 
| 80 | 80 | ||
| 81 | @override | 81 | @override | 
| 82 | void retainWhere(bool test(E element)) { | 82 | void retainWhere(bool test(E element)) { | 
| 83 | - _value.retainWhere(test); | 83 | + value.retainWhere(test); | 
| 84 | refresh(); | 84 | refresh(); | 
| 85 | } | 85 | } | 
| 86 | 86 | ||
| @@ -91,18 +91,18 @@ class RxList<E> extends ListMixin<E> | @@ -91,18 +91,18 @@ class RxList<E> extends ListMixin<E> | ||
| 91 | @protected | 91 | @protected | 
| 92 | List<E> get value { | 92 | List<E> get value { | 
| 93 | RxInterface.proxy?.addListener(subject); | 93 | RxInterface.proxy?.addListener(subject); | 
| 94 | - return _value; | 94 | + return subject.value; | 
| 95 | } | 95 | } | 
| 96 | 96 | ||
| 97 | @override | 97 | @override | 
| 98 | set length(int newLength) { | 98 | set length(int newLength) { | 
| 99 | - _value.length = newLength; | 99 | + value.length = newLength; | 
| 100 | refresh(); | 100 | refresh(); | 
| 101 | } | 101 | } | 
| 102 | 102 | ||
| 103 | @override | 103 | @override | 
| 104 | void insertAll(int index, Iterable<E> iterable) { | 104 | void insertAll(int index, Iterable<E> iterable) { | 
| 105 | - _value.insertAll(index, iterable); | 105 | + value.insertAll(index, iterable); | 
| 106 | refresh(); | 106 | refresh(); | 
| 107 | } | 107 | } | 
| 108 | 108 | ||
| @@ -121,7 +121,7 @@ class RxList<E> extends ListMixin<E> | @@ -121,7 +121,7 @@ class RxList<E> extends ListMixin<E> | ||
| 121 | 121 | ||
| 122 | @override | 122 | @override | 
| 123 | void sort([int compare(E a, E b)?]) { | 123 | void sort([int compare(E a, E b)?]) { | 
| 124 | - _value.sort(compare); | 124 | + value.sort(compare); | 
| 125 | refresh(); | 125 | refresh(); | 
| 126 | } | 126 | } | 
| 127 | } | 127 | } | 
| @@ -4,7 +4,7 @@ class RxMap<K, V> extends MapMixin<K, V> | @@ -4,7 +4,7 @@ class RxMap<K, V> extends MapMixin<K, V> | ||
| 4 | with NotifyManager<Map<K, V>>, RxObjectMixin<Map<K, V>> | 4 | with NotifyManager<Map<K, V>>, RxObjectMixin<Map<K, V>> | 
| 5 | implements RxInterface<Map<K, V>> { | 5 | implements RxInterface<Map<K, V>> { | 
| 6 | RxMap([Map<K, V> initial = const {}]) { | 6 | RxMap([Map<K, V> initial = const {}]) { | 
| 7 | - _value = Map.from(initial); | 7 | + subject = GetStream.fromValue(Map.from(initial)); | 
| 8 | } | 8 | } | 
| 9 | 9 | ||
| 10 | factory RxMap.from(Map<K, V> other) { | 10 | factory RxMap.from(Map<K, V> other) { | 
| @@ -32,14 +32,14 @@ class RxMap<K, V> extends MapMixin<K, V> | @@ -32,14 +32,14 @@ class RxMap<K, V> extends MapMixin<K, V> | ||
| 32 | } | 32 | } | 
| 33 | 33 | ||
| 34 | @override | 34 | @override | 
| 35 | - void operator []=(K key, V value) { | ||
| 36 | - _value[key] = value; | 35 | + void operator []=(K key, V val) { | 
| 36 | + value[key] = val; | ||
| 37 | refresh(); | 37 | refresh(); | 
| 38 | } | 38 | } | 
| 39 | 39 | ||
| 40 | @override | 40 | @override | 
| 41 | void clear() { | 41 | void clear() { | 
| 42 | - _value.clear(); | 42 | + value.clear(); | 
| 43 | refresh(); | 43 | refresh(); | 
| 44 | } | 44 | } | 
| 45 | 45 | ||
| @@ -48,7 +48,7 @@ class RxMap<K, V> extends MapMixin<K, V> | @@ -48,7 +48,7 @@ class RxMap<K, V> extends MapMixin<K, V> | ||
| 48 | 48 | ||
| 49 | @override | 49 | @override | 
| 50 | V? remove(Object? key) { | 50 | V? remove(Object? key) { | 
| 51 | - final val = _value.remove(key); | 51 | + final val = value.remove(key); | 
| 52 | refresh(); | 52 | refresh(); | 
| 53 | return val; | 53 | return val; | 
| 54 | } | 54 | } | 
| @@ -56,8 +56,9 @@ class RxMap<K, V> extends MapMixin<K, V> | @@ -56,8 +56,9 @@ class RxMap<K, V> extends MapMixin<K, V> | ||
| 56 | @override | 56 | @override | 
| 57 | @protected | 57 | @protected | 
| 58 | Map<K, V> get value { | 58 | Map<K, V> get value { | 
| 59 | - RxInterface.proxy?.addListener(subject); | ||
| 60 | - return _value; | 59 | + return subject.value; | 
| 60 | + // RxInterface.proxy?.addListener(subject); | ||
| 61 | + // return _value; | ||
| 61 | } | 62 | } | 
| 62 | } | 63 | } | 
| 63 | 64 | ||
| @@ -82,7 +83,7 @@ extension MapExtension<K, V> on Map<K, V> { | @@ -82,7 +83,7 @@ extension MapExtension<K, V> on Map<K, V> { | ||
| 82 | if (this is RxMap) { | 83 | if (this is RxMap) { | 
| 83 | final map = (this as RxMap); | 84 | final map = (this as RxMap); | 
| 84 | // map._value; | 85 | // map._value; | 
| 85 | - map._value.clear(); | 86 | + map.value.clear(); | 
| 86 | this[key] = val; | 87 | this[key] = val; | 
| 87 | } else { | 88 | } else { | 
| 88 | clear(); | 89 | clear(); | 
| @@ -92,12 +93,12 @@ extension MapExtension<K, V> on Map<K, V> { | @@ -92,12 +93,12 @@ extension MapExtension<K, V> on Map<K, V> { | ||
| 92 | 93 | ||
| 93 | void assignAll(Map<K, V> val) { | 94 | void assignAll(Map<K, V> val) { | 
| 94 | if (val is RxMap && this is RxMap) { | 95 | if (val is RxMap && this is RxMap) { | 
| 95 | - if ((val as RxMap)._value == (this as RxMap)._value) return; | 96 | + if ((val as RxMap).value == (this as RxMap).value) return; | 
| 96 | } | 97 | } | 
| 97 | if (this is RxMap) { | 98 | if (this is RxMap) { | 
| 98 | final map = (this as RxMap); | 99 | final map = (this as RxMap); | 
| 99 | - if (map._value == val) return; | ||
| 100 | - map._value = val; | 100 | + if (map.value == val) return; | 
| 101 | + map.value = val; | ||
| 101 | map.refresh(); | 102 | map.refresh(); | 
| 102 | } else { | 103 | } else { | 
| 103 | if (this == val) return; | 104 | if (this == val) return; | 
| @@ -4,7 +4,7 @@ class RxSet<E> extends SetMixin<E> | @@ -4,7 +4,7 @@ class RxSet<E> extends SetMixin<E> | ||
| 4 | with NotifyManager<Set<E>>, RxObjectMixin<Set<E>> | 4 | with NotifyManager<Set<E>>, RxObjectMixin<Set<E>> | 
| 5 | implements RxInterface<Set<E>> { | 5 | implements RxInterface<Set<E>> { | 
| 6 | RxSet([Set<E> initial = const {}]) { | 6 | RxSet([Set<E> initial = const {}]) { | 
| 7 | - _value = Set.from(initial); | 7 | + subject = GetStream.fromValue(Set.from(initial)); | 
| 8 | } | 8 | } | 
| 9 | 9 | ||
| 10 | /// Special override to push() element(s) in a reactive way | 10 | /// Special override to push() element(s) in a reactive way | 
| @@ -23,21 +23,22 @@ class RxSet<E> extends SetMixin<E> | @@ -23,21 +23,22 @@ class RxSet<E> extends SetMixin<E> | ||
| 23 | @override | 23 | @override | 
| 24 | @protected | 24 | @protected | 
| 25 | Set<E> get value { | 25 | Set<E> get value { | 
| 26 | - RxInterface.proxy?.addListener(subject); | ||
| 27 | - return _value; | 26 | + return subject.value; | 
| 27 | + // RxInterface.proxy?.addListener(subject); | ||
| 28 | + // return _value; | ||
| 28 | } | 29 | } | 
| 29 | 30 | ||
| 30 | @override | 31 | @override | 
| 31 | @protected | 32 | @protected | 
| 32 | set value(Set<E> val) { | 33 | set value(Set<E> val) { | 
| 33 | - if (_value == val) return; | ||
| 34 | - _value = val; | 34 | + if (value == val) return; | 
| 35 | + value = val; | ||
| 35 | refresh(); | 36 | refresh(); | 
| 36 | } | 37 | } | 
| 37 | 38 | ||
| 38 | @override | 39 | @override | 
| 39 | - bool add(E value) { | ||
| 40 | - final val = _value.add(value); | 40 | + bool add(E newValue) { | 
| 41 | + final val = value.add(newValue); | ||
| 41 | refresh(); | 42 | refresh(); | 
| 42 | return val; | 43 | return val; | 
| 43 | } | 44 | } | 
| @@ -60,7 +61,7 @@ class RxSet<E> extends SetMixin<E> | @@ -60,7 +61,7 @@ class RxSet<E> extends SetMixin<E> | ||
| 60 | 61 | ||
| 61 | @override | 62 | @override | 
| 62 | bool remove(Object? item) { | 63 | bool remove(Object? item) { | 
| 63 | - var hasRemoved = _value.remove(item); | 64 | + var hasRemoved = value.remove(item); | 
| 64 | if (hasRemoved) { | 65 | if (hasRemoved) { | 
| 65 | refresh(); | 66 | refresh(); | 
| 66 | } | 67 | } | 
| @@ -74,31 +75,31 @@ class RxSet<E> extends SetMixin<E> | @@ -74,31 +75,31 @@ class RxSet<E> extends SetMixin<E> | ||
| 74 | 75 | ||
| 75 | @override | 76 | @override | 
| 76 | void addAll(Iterable<E> item) { | 77 | void addAll(Iterable<E> item) { | 
| 77 | - _value.addAll(item); | 78 | + value.addAll(item); | 
| 78 | refresh(); | 79 | refresh(); | 
| 79 | } | 80 | } | 
| 80 | 81 | ||
| 81 | @override | 82 | @override | 
| 82 | void clear() { | 83 | void clear() { | 
| 83 | - _value.clear(); | 84 | + value.clear(); | 
| 84 | refresh(); | 85 | refresh(); | 
| 85 | } | 86 | } | 
| 86 | 87 | ||
| 87 | @override | 88 | @override | 
| 88 | void removeAll(Iterable<Object?> elements) { | 89 | void removeAll(Iterable<Object?> elements) { | 
| 89 | - _value.removeAll(elements); | 90 | + value.removeAll(elements); | 
| 90 | refresh(); | 91 | refresh(); | 
| 91 | } | 92 | } | 
| 92 | 93 | ||
| 93 | @override | 94 | @override | 
| 94 | void retainAll(Iterable<Object?> elements) { | 95 | void retainAll(Iterable<Object?> elements) { | 
| 95 | - _value.retainAll(elements); | 96 | + value.retainAll(elements); | 
| 96 | refresh(); | 97 | refresh(); | 
| 97 | } | 98 | } | 
| 98 | 99 | ||
| 99 | @override | 100 | @override | 
| 100 | void retainWhere(bool Function(E) E) { | 101 | void retainWhere(bool Function(E) E) { | 
| 101 | - _value.retainWhere(E); | 102 | + value.retainWhere(E); | 
| 102 | refresh(); | 103 | refresh(); | 
| 103 | } | 104 | } | 
| 104 | } | 105 | } | 
| @@ -4,6 +4,7 @@ import 'dart:async'; | @@ -4,6 +4,7 @@ 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/simple/list_notifier.dart'; | ||
| 7 | import '../rx_stream/rx_stream.dart'; | 8 | import '../rx_stream/rx_stream.dart'; | 
| 8 | import '../rx_typedefs/rx_typedefs.dart'; | 9 | import '../rx_typedefs/rx_typedefs.dart'; | 
| 9 | 10 | 
| @@ -14,9 +14,6 @@ typedef GetXControllerBuilder<T extends DisposableInterface> = Widget Function( | @@ -14,9 +14,6 @@ typedef GetXControllerBuilder<T extends DisposableInterface> = Widget Function( | ||
| 14 | class GetX<T extends DisposableInterface> extends StatefulWidget { | 14 | class GetX<T extends DisposableInterface> extends StatefulWidget { | 
| 15 | final GetXControllerBuilder<T> builder; | 15 | final GetXControllerBuilder<T> builder; | 
| 16 | final bool global; | 16 | final bool global; | 
| 17 | - | ||
| 18 | - // final Stream Function(T) stream; | ||
| 19 | - // final StreamController Function(T) streamController; | ||
| 20 | final bool autoRemove; | 17 | final bool autoRemove; | 
| 21 | final bool assignId; | 18 | final bool assignId; | 
| 22 | final void Function(GetXState<T> state)? initState, | 19 | final void Function(GetXState<T> state)? initState, | 
| @@ -7,7 +7,7 @@ import '../../get_state_manager.dart'; | @@ -7,7 +7,7 @@ import '../../get_state_manager.dart'; | ||
| 7 | import '../simple/list_notifier.dart'; | 7 | import '../simple/list_notifier.dart'; | 
| 8 | 8 | ||
| 9 | mixin StateMixin<T> on ListNotifierMixin { | 9 | mixin StateMixin<T> on ListNotifierMixin { | 
| 10 | - T? _value; | 10 | + late T _value; | 
| 11 | RxStatus? _status; | 11 | RxStatus? _status; | 
| 12 | 12 | ||
| 13 | bool _isNullOrEmpty(dynamic val) { | 13 | bool _isNullOrEmpty(dynamic val) { | 
| @@ -32,23 +32,23 @@ mixin StateMixin<T> on ListNotifierMixin { | @@ -32,23 +32,23 @@ mixin StateMixin<T> on ListNotifierMixin { | ||
| 32 | return _status ??= _status = RxStatus.loading(); | 32 | return _status ??= _status = RxStatus.loading(); | 
| 33 | } | 33 | } | 
| 34 | 34 | ||
| 35 | - T? get state => value; | 35 | + T get state => value; | 
| 36 | 36 | ||
| 37 | @protected | 37 | @protected | 
| 38 | - T? get value { | 38 | + T get value { | 
| 39 | notifyChildrens(); | 39 | notifyChildrens(); | 
| 40 | return _value; | 40 | return _value; | 
| 41 | } | 41 | } | 
| 42 | 42 | ||
| 43 | @protected | 43 | @protected | 
| 44 | - set value(T? newValue) { | 44 | + set value(T newValue) { | 
| 45 | if (_value == newValue) return; | 45 | if (_value == newValue) return; | 
| 46 | _value = newValue; | 46 | _value = newValue; | 
| 47 | refresh(); | 47 | refresh(); | 
| 48 | } | 48 | } | 
| 49 | 49 | ||
| 50 | @protected | 50 | @protected | 
| 51 | - void change(T? newState, {RxStatus? status}) { | 51 | + void change(T newState, {RxStatus? status}) { | 
| 52 | var _canUpdate = false; | 52 | var _canUpdate = false; | 
| 53 | if (status != null) { | 53 | if (status != null) { | 
| 54 | _status = status; | 54 | _status = status; | 
| @@ -82,13 +82,13 @@ class Value<T> extends ListNotifier | @@ -82,13 +82,13 @@ class Value<T> extends ListNotifier | ||
| 82 | } | 82 | } | 
| 83 | 83 | ||
| 84 | @override | 84 | @override | 
| 85 | - T? get value { | 85 | + T get value { | 
| 86 | notifyChildrens(); | 86 | notifyChildrens(); | 
| 87 | return _value; | 87 | return _value; | 
| 88 | } | 88 | } | 
| 89 | 89 | ||
| 90 | @override | 90 | @override | 
| 91 | - set value(T? newValue) { | 91 | + set value(T newValue) { | 
| 92 | if (_value == newValue) return; | 92 | if (_value == newValue) return; | 
| 93 | _value = newValue; | 93 | _value = newValue; | 
| 94 | refresh(); | 94 | refresh(); | 
| @@ -119,9 +119,7 @@ extension ReactiveT<T> on T { | @@ -119,9 +119,7 @@ extension ReactiveT<T> on T { | ||
| 119 | typedef Condition = bool Function(); | 119 | typedef Condition = bool Function(); | 
| 120 | 120 | ||
| 121 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycleBase { | 121 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycleBase { | 
| 122 | - GetNotifier(T initial) : super(initial) { | ||
| 123 | - $configureLifeCycle(); | ||
| 124 | - } | 122 | + GetNotifier(T initial) : super(initial); | 
| 125 | 123 | ||
| 126 | @override | 124 | @override | 
| 127 | @mustCallSuper | 125 | @mustCallSuper | 
| @@ -194,3 +192,44 @@ class RxStatus { | @@ -194,3 +192,44 @@ class RxStatus { | ||
| 194 | } | 192 | } | 
| 195 | 193 | ||
| 196 | typedef NotifierBuilder<T> = Widget Function(T state); | 194 | typedef NotifierBuilder<T> = Widget Function(T state); | 
| 195 | + | ||
| 196 | +abstract class GState<T> { | ||
| 197 | + const GState(); | ||
| 198 | + factory GState.loading() => GLoading(); | ||
| 199 | + factory GState.error(String message) => GError(message); | ||
| 200 | + factory GState.empty() => GEmpty(); | ||
| 201 | + factory GState.success(T data) => GSuccess(data); | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +class GLoading<T> extends GState<T> {} | ||
| 205 | + | ||
| 206 | +class GSuccess<T> extends GState<T> { | ||
| 207 | + final T data; | ||
| 208 | + | ||
| 209 | + GSuccess(this.data); | ||
| 210 | +} | ||
| 211 | + | ||
| 212 | +class GError<T, S> extends GState<T> { | ||
| 213 | + final S? error; | ||
| 214 | + GError([this.error]); | ||
| 215 | +} | ||
| 216 | + | ||
| 217 | +class GEmpty<T> extends GState<T> {} | ||
| 218 | + | ||
| 219 | +extension StatusDataExt<T> on GState<T> { | ||
| 220 | + bool get isLoading => this is GLoading; | ||
| 221 | + bool get isSuccess => this is GSuccess; | ||
| 222 | + bool get isError => this is GError; | ||
| 223 | + bool get isEmpty => this is GEmpty; | ||
| 224 | + String get errorMessage { | ||
| 225 | + final isError = this is GError; | ||
| 226 | + if (isError) { | ||
| 227 | + final err = this as GError; | ||
| 228 | + if (err.error != null && err.error is String) { | ||
| 229 | + return err.error as String; | ||
| 230 | + } | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + return ''; | ||
| 234 | + } | ||
| 235 | +} | 
| 1 | import 'dart:async'; | 1 | import 'dart:async'; | 
| 2 | + | ||
| 2 | import 'package:flutter/foundation.dart'; | 3 | import 'package:flutter/foundation.dart'; | 
| 3 | import 'package:flutter/widgets.dart'; | 4 | import 'package:flutter/widgets.dart'; | 
| 5 | + | ||
| 4 | import '../../../get_rx/src/rx_types/rx_types.dart'; | 6 | import '../../../get_rx/src/rx_types/rx_types.dart'; | 
| 5 | 7 | ||
| 6 | typedef WidgetCallback = Widget Function(); | 8 | typedef WidgetCallback = Widget Function(); | 
| @@ -54,6 +56,15 @@ class _ObxState extends State<ObxWidget> { | @@ -54,6 +56,15 @@ class _ObxState extends State<ObxWidget> { | ||
| 54 | RxInterface.notifyChildren(_observer, widget.build); | 56 | RxInterface.notifyChildren(_observer, widget.build); | 
| 55 | } | 57 | } | 
| 56 | 58 | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + | ||
| 64 | + | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + | ||
| 57 | /// The simplest reactive widget in GetX. | 68 | /// The simplest reactive widget in GetX. | 
| 58 | /// | 69 | /// | 
| 59 | /// Just pass your Rx variable in the root scope of the callback to have it | 70 | /// Just pass your Rx variable in the root scope of the callback to have it | 
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | + | ||
| 2 | import '../../../get_instance/src/get_instance.dart'; | 3 | import '../../../get_instance/src/get_instance.dart'; | 
| 3 | import '../../../instance_manager.dart'; | 4 | import '../../../instance_manager.dart'; | 
| 4 | import '../../get_state_manager.dart'; | 5 | import '../../get_state_manager.dart'; | 
| 5 | -import 'list_notifier.dart'; | ||
| 6 | - | ||
| 7 | -/// Complies with `GetStateUpdater` | ||
| 8 | -/// | ||
| 9 | -/// This mixin's function represents a `GetStateUpdater`, and might be used | ||
| 10 | -/// by `GetBuilder()`, `SimpleBuilder()` (or similar) to comply | ||
| 11 | -/// with [GetStateUpdate] signature. REPLACING the [StateSetter]. | ||
| 12 | -/// Avoids the potential (but extremely unlikely) issue of having | ||
| 13 | -/// the Widget in a dispose() state, and abstracts the | ||
| 14 | -/// API from the ugly fn((){}). | ||
| 15 | -mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> { | ||
| 16 | - // To avoid the creation of an anonym function to be GC later. | ||
| 17 | - // ignore: prefer_function_declarations_over_variables | ||
| 18 | - | ||
| 19 | - /// Experimental method to replace setState((){}); | ||
| 20 | - /// Used with GetStateUpdate. | ||
| 21 | - void getUpdate() { | ||
| 22 | - if (mounted) setState(() {}); | ||
| 23 | - } | ||
| 24 | -} | ||
| 25 | 6 | ||
| 26 | typedef GetControllerBuilder<T extends DisposableInterface> = Widget Function( | 7 | typedef GetControllerBuilder<T extends DisposableInterface> = Widget Function( | 
| 27 | T controller); | 8 | T controller); | 
| 28 | 9 | ||
| 29 | -// class _InheritedGetxController<T extends GetxController> | ||
| 30 | -// extends InheritedWidget { | ||
| 31 | -// final T model; | ||
| 32 | -// final int version; | ||
| 33 | - | ||
| 34 | -// _InheritedGetxController({ | ||
| 35 | -// Key key, | ||
| 36 | -// @required Widget child, | ||
| 37 | -// @required this.model, | ||
| 38 | -// }) : version = model.notifierVersion, | ||
| 39 | -// super(key: key, child: child); | ||
| 40 | - | ||
| 41 | -// @override | ||
| 42 | -// bool updateShouldNotify(_InheritedGetxController<T> oldWidget) => | ||
| 43 | -// (oldWidget.version != version); | ||
| 44 | -// } | 10 | +extension WatchExt on BuildContext { | 
| 11 | + T listen<T extends GetxController>() { | ||
| 12 | + return Scope.of(this, rebuild: true); | ||
| 13 | + } | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +extension ReadExt on BuildContext { | ||
| 17 | + T find<T extends GetxController>() { | ||
| 18 | + return Scope.of(this); | ||
| 19 | + } | ||
| 20 | +} | ||
| 45 | 21 | ||
| 46 | -// extension WatchEtx on GetxController { | ||
| 47 | -// T watch<T extends GetxController>() { | ||
| 48 | -// final instance = Get.find<T>(); | ||
| 49 | -// _GetBuilderState._currentState.watch(instance.update); | ||
| 50 | -// return instance; | 22 | +// extension FilterExt on BuildContext { | 
| 23 | +// T filter<T extends GetxController>(Object Function(T value)? filter) { | ||
| 24 | +// return Scope.of(this, filter: filter, rebuild: true); | ||
| 51 | // } | 25 | // } | 
| 52 | // } | 26 | // } | 
| 53 | 27 | ||
| 54 | -class GetBuilder<T extends GetxController> extends StatefulWidget { | 28 | +class GetBuilder<T extends GetxController> extends StatelessWidget { | 
| 55 | final GetControllerBuilder<T> builder; | 29 | final GetControllerBuilder<T> builder; | 
| 56 | final bool global; | 30 | final bool global; | 
| 57 | final Object? id; | 31 | final Object? id; | 
| @@ -59,10 +33,10 @@ class GetBuilder<T extends GetxController> extends StatefulWidget { | @@ -59,10 +33,10 @@ class GetBuilder<T extends GetxController> extends StatefulWidget { | ||
| 59 | final bool autoRemove; | 33 | final bool autoRemove; | 
| 60 | final bool assignId; | 34 | final bool assignId; | 
| 61 | final Object Function(T value)? filter; | 35 | final Object Function(T value)? filter; | 
| 62 | - final void Function(GetBuilderState<T> state)? initState, | 36 | + final void Function(ScopeElement<T> state)? initState, | 
| 63 | dispose, | 37 | dispose, | 
| 64 | didChangeDependencies; | 38 | didChangeDependencies; | 
| 65 | - final void Function(GetBuilder oldWidget, GetBuilderState<T> state)? | 39 | + final void Function(Scope<T> oldWidget, ScopeElement<T> state)? | 
| 66 | didUpdateWidget; | 40 | didUpdateWidget; | 
| 67 | final T? init; | 41 | final T? init; | 
| 68 | 42 | ||
| @@ -82,40 +56,127 @@ class GetBuilder<T extends GetxController> extends StatefulWidget { | @@ -82,40 +56,127 @@ class GetBuilder<T extends GetxController> extends StatefulWidget { | ||
| 82 | this.didUpdateWidget, | 56 | this.didUpdateWidget, | 
| 83 | }) : super(key: key); | 57 | }) : super(key: key); | 
| 84 | 58 | ||
| 85 | - // static T of<T extends GetxController>( | ||
| 86 | - // BuildContext context, { | ||
| 87 | - // bool rebuild = false, | ||
| 88 | - // }) { | ||
| 89 | - // var widget = rebuild | ||
| 90 | - // ? context | ||
| 91 | - // .dependOnInheritedWidgetOfExactType<_InheritedGetxController<T>>() | ||
| 92 | - // : context | ||
| 93 | - // .getElementForInheritedWidgetOfExactType< | ||
| 94 | - // _InheritedGetxController<T>>() | ||
| 95 | - // ?.widget; | ||
| 96 | - | ||
| 97 | - // if (widget == null) { | ||
| 98 | - // throw 'Error: Could not find the correct dependency.'; | 59 | + @override | 
| 60 | + Widget build(BuildContext context) { | ||
| 61 | + return Scope<T>( | ||
| 62 | + init: init, | ||
| 63 | + global: global, | ||
| 64 | + autoRemove: autoRemove, | ||
| 65 | + assignId: assignId, | ||
| 66 | + initState: initState, | ||
| 67 | + filter: filter, | ||
| 68 | + tag: tag, | ||
| 69 | + dispose: dispose, | ||
| 70 | + id: id, | ||
| 71 | + didChangeDependencies: didChangeDependencies, | ||
| 72 | + didUpdateWidget: didUpdateWidget, | ||
| 73 | + child: Builder(builder: (context) { | ||
| 74 | + final controller = Scope.of<T>(context, rebuild: true); | ||
| 75 | + return builder(controller); | ||
| 76 | + }), | ||
| 77 | + ); | ||
| 78 | + // return widget.builder(controller!); | ||
| 79 | + } | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +class Scope<T extends GetxController> extends InheritedWidget { | ||
| 83 | + /// Create an inherited widget that updates its dependents when [controller] | ||
| 84 | + /// sends notifications. | ||
| 85 | + /// | ||
| 86 | + /// The [child] argument is required | ||
| 87 | + const Scope({ | ||
| 88 | + Key? key, | ||
| 89 | + required Widget child, | ||
| 90 | + this.init, | ||
| 91 | + this.global = true, | ||
| 92 | + this.autoRemove = true, | ||
| 93 | + this.assignId = false, | ||
| 94 | + this.initState, | ||
| 95 | + this.filter, | ||
| 96 | + this.tag, | ||
| 97 | + this.dispose, | ||
| 98 | + this.id, | ||
| 99 | + this.didChangeDependencies, | ||
| 100 | + this.didUpdateWidget, | ||
| 101 | + }) : super(key: key, child: child); | ||
| 102 | + | ||
| 103 | + /// The [Listenable] object to which to listen. | ||
| 104 | + /// | ||
| 105 | + /// Whenever this object sends change notifications, the dependents of this | ||
| 106 | + /// widget are triggered. | ||
| 107 | + /// | ||
| 108 | + /// By default, whenever the [controller] is changed (including when changing to | ||
| 109 | + /// or from null), if the old controller is not equal to the new controller (as | ||
| 110 | + /// determined by the `==` operator), notifications are sent. This behavior | ||
| 111 | + /// can be overridden by overriding [updateShouldNotify]. | ||
| 112 | + /// | ||
| 113 | + /// While the [controller] is null, no notifications are sent, since the null | ||
| 114 | + /// object cannot itself send notifications. | ||
| 115 | + final T? init; | ||
| 116 | + | ||
| 117 | + final bool global; | ||
| 118 | + final Object? id; | ||
| 119 | + final String? tag; | ||
| 120 | + final bool autoRemove; | ||
| 121 | + final bool assignId; | ||
| 122 | + final Object Function(T value)? filter; | ||
| 123 | + final void Function(ScopeElement<T> state)? initState, | ||
| 124 | + dispose, | ||
| 125 | + didChangeDependencies; | ||
| 126 | + final void Function(Scope<T> oldWidget, ScopeElement<T> state)? | ||
| 127 | + didUpdateWidget; | ||
| 128 | + | ||
| 129 | + static T of<T extends GetxController>( | ||
| 130 | + BuildContext context, { | ||
| 131 | + bool rebuild = false, | ||
| 132 | + // Object Function(T value)? filter, | ||
| 133 | + }) { | ||
| 134 | + final inheritedElement = context | ||
| 135 | + .getElementForInheritedWidgetOfExactType<Scope<T>>() as ScopeElement<T>; | ||
| 136 | + | ||
| 137 | + if (rebuild) { | ||
| 138 | + // var newFilter = filter?.call(inheritedElement.controller!); | ||
| 139 | + // if (newFilter != null) { | ||
| 140 | + // context.dependOnInheritedElement(inheritedElement, aspect: newFilter); | ||
| 99 | // } else { | 141 | // } else { | 
| 100 | - // return (widget as _InheritedGetxController<T>).model; | ||
| 101 | - // } | 142 | + context.dependOnInheritedElement(inheritedElement); | 
| 102 | // } | 143 | // } | 
| 144 | + } | ||
| 145 | + | ||
| 146 | + var widget = inheritedElement.controller; | ||
| 147 | + | ||
| 148 | + if (widget == null) { | ||
| 149 | + throw 'Error: Could not find the correct dependency.'; | ||
| 150 | + } else { | ||
| 151 | + return widget; | ||
| 152 | + } | ||
| 153 | + } | ||
| 103 | 154 | ||
| 104 | @override | 155 | @override | 
| 105 | - GetBuilderState<T> createState() => GetBuilderState<T>(); | 156 | + bool updateShouldNotify(Scope<T> oldWidget) { | 
| 157 | + return oldWidget.id != id || | ||
| 158 | + oldWidget.global != global || | ||
| 159 | + oldWidget.autoRemove != autoRemove || | ||
| 160 | + oldWidget.assignId != assignId; | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + @override | ||
| 164 | + InheritedElement createElement() => ScopeElement<T>(this); | ||
| 106 | } | 165 | } | 
| 107 | 166 | ||
| 108 | -class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 109 | - with GetStateUpdaterMixin { | 167 | +/// The ScopeElement is responsible for injecting dependencies into the widget | 
| 168 | +/// tree so that they can be observed | ||
| 169 | +class ScopeElement<T extends GetxController> extends InheritedElement { | ||
| 170 | + ScopeElement(Scope<T> widget) : super(widget) { | ||
| 171 | + initState(); | ||
| 172 | + } | ||
| 173 | + | ||
| 110 | T? controller; | 174 | T? controller; | 
| 111 | bool? _isCreator = false; | 175 | bool? _isCreator = false; | 
| 112 | VoidCallback? _remove; | 176 | VoidCallback? _remove; | 
| 113 | Object? _filter; | 177 | Object? _filter; | 
| 114 | 178 | ||
| 115 | - @override | ||
| 116 | void initState() { | 179 | void initState() { | 
| 117 | - // _GetBuilderState._currentState = this; | ||
| 118 | - super.initState(); | ||
| 119 | widget.initState?.call(this); | 180 | widget.initState?.call(this); | 
| 120 | 181 | ||
| 121 | var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag); | 182 | var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag); | 
| @@ -169,9 +230,7 @@ class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -169,9 +230,7 @@ class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 169 | } | 230 | } | 
| 170 | } | 231 | } | 
| 171 | 232 | ||
| 172 | - @override | ||
| 173 | void dispose() { | 233 | void dispose() { | 
| 174 | - super.dispose(); | ||
| 175 | widget.dispose?.call(this); | 234 | widget.dispose?.call(this); | 
| 176 | if (_isCreator! || widget.assignId) { | 235 | if (_isCreator! || widget.assignId) { | 
| 177 | if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) { | 236 | if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) { | 
| @@ -188,39 +247,49 @@ class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -188,39 +247,49 @@ class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
| 188 | } | 247 | } | 
| 189 | 248 | ||
| 190 | @override | 249 | @override | 
| 250 | + Scope<T> get widget => super.widget as Scope<T>; | ||
| 251 | + | ||
| 252 | + var _dirty = false; | ||
| 253 | + | ||
| 254 | + @override | ||
| 255 | + void update(Scope<T> newWidget) { | ||
| 256 | + final oldNotifier = widget.id; | ||
| 257 | + final newNotifier = newWidget.id; | ||
| 258 | + if (oldNotifier != newNotifier) { | ||
| 259 | + _subscribeToController(); | ||
| 260 | + } | ||
| 261 | + widget.didUpdateWidget?.call(widget, this); | ||
| 262 | + super.update(newWidget); | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + @override | ||
| 191 | void didChangeDependencies() { | 266 | void didChangeDependencies() { | 
| 192 | super.didChangeDependencies(); | 267 | super.didChangeDependencies(); | 
| 193 | widget.didChangeDependencies?.call(this); | 268 | widget.didChangeDependencies?.call(this); | 
| 194 | } | 269 | } | 
| 195 | 270 | ||
| 196 | @override | 271 | @override | 
| 197 | - void didUpdateWidget(GetBuilder oldWidget) { | ||
| 198 | - super.didUpdateWidget(oldWidget as GetBuilder<T>); | ||
| 199 | - // to avoid conflicts when modifying a "grouped" id list. | ||
| 200 | - if (oldWidget.id != widget.id) { | ||
| 201 | - _subscribeToController(); | 272 | + Widget build() { | 
| 273 | + if (_dirty) { | ||
| 274 | + notifyClients(widget); | ||
| 202 | } | 275 | } | 
| 203 | - widget.didUpdateWidget?.call(oldWidget, this); | 276 | + return super.build(); | 
| 204 | } | 277 | } | 
| 205 | 278 | ||
| 206 | - @override | ||
| 207 | - Widget build(BuildContext context) { | ||
| 208 | - // return _InheritedGetxController<T>( | ||
| 209 | - // model: controller, | ||
| 210 | - // child: widget.builder(controller), | ||
| 211 | - // ); | ||
| 212 | - return widget.builder(controller!); | 279 | + void getUpdate() { | 
| 280 | + _dirty = true; | ||
| 281 | + markNeedsBuild(); | ||
| 213 | } | 282 | } | 
| 214 | -} | ||
| 215 | 283 | ||
| 216 | -// extension FindExt on BuildContext { | ||
| 217 | -// T find<T extends GetxController>() { | ||
| 218 | -// return GetBuilder.of<T>(this, rebuild: false); | ||
| 219 | -// } | ||
| 220 | -// } | 284 | + @override | 
| 285 | + void notifyClients(Scope<T> oldWidget) { | ||
| 286 | + super.notifyClients(oldWidget); | ||
| 287 | + _dirty = false; | ||
| 288 | + } | ||
| 221 | 289 | ||
| 222 | -// extension ObserverEtx on BuildContext { | ||
| 223 | -// T obs<T extends GetxController>() { | ||
| 224 | -// return GetBuilder.of<T>(this, rebuild: true); | ||
| 225 | -// } | ||
| 226 | -// } | 290 | + @override | 
| 291 | + void unmount() { | ||
| 292 | + dispose(); | ||
| 293 | + super.unmount(); | ||
| 294 | + } | ||
| 295 | +} | 
| @@ -159,15 +159,11 @@ class TaskManager { | @@ -159,15 +159,11 @@ class TaskManager { | ||
| 159 | } | 159 | } | 
| 160 | } | 160 | } | 
| 161 | 161 | ||
| 162 | - Widget exchange( | ||
| 163 | - List<VoidCallback> disposers, | ||
| 164 | - GetStateUpdate setState, | ||
| 165 | - Widget Function(BuildContext) builder, | ||
| 166 | - BuildContext context, | ||
| 167 | - ) { | 162 | + T exchange<T>(List<VoidCallback> disposers, GetStateUpdate setState, | 
| 163 | + T Function() builder) { | ||
| 168 | _remove = disposers; | 164 | _remove = disposers; | 
| 169 | _setter = setState; | 165 | _setter = setState; | 
| 170 | - final result = builder(context); | 166 | + final result = builder(); | 
| 171 | _remove = null; | 167 | _remove = null; | 
| 172 | _setter = null; | 168 | _setter = null; | 
| 173 | return result; | 169 | return result; | 
| @@ -8,8 +8,11 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget { | @@ -8,8 +8,11 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget { | ||
| 8 | final bool global; | 8 | final bool global; | 
| 9 | final String? id; | 9 | final String? id; | 
| 10 | final bool autoRemove; | 10 | final bool autoRemove; | 
| 11 | - final void Function(State state)? initState, dispose, didChangeDependencies; | ||
| 12 | - final void Function(GetBuilder oldWidget, State state)? didUpdateWidget; | 11 | + final void Function(ScopeElement<T> state)? initState, | 
| 12 | + dispose, | ||
| 13 | + didChangeDependencies; | ||
| 14 | + final void Function(Scope<T> oldWidget, ScopeElement<T> state)? | ||
| 15 | + didUpdateWidget; | ||
| 13 | final T? init; | 16 | final T? init; | 
| 14 | 17 | ||
| 15 | const MixinBuilder({ | 18 | const MixinBuilder({ | 
| 1 | import 'dart:async'; | 1 | import 'dart:async'; | 
| 2 | + | ||
| 2 | import 'package:flutter/widgets.dart'; | 3 | import 'package:flutter/widgets.dart'; | 
| 3 | -import 'get_state.dart'; | 4 | + | 
| 4 | import 'list_notifier.dart'; | 5 | import 'list_notifier.dart'; | 
| 5 | 6 | ||
| 6 | typedef ValueBuilderUpdateCallback<T> = void Function(T snapshot); | 7 | typedef ValueBuilderUpdateCallback<T> = void Function(T snapshot); | 
| @@ -69,35 +70,39 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T>> { | @@ -69,35 +70,39 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T>> { | ||
| 69 | } | 70 | } | 
| 70 | } | 71 | } | 
| 71 | 72 | ||
| 73 | +class ObxElement = StatelessElement with ObserverComponent; | ||
| 74 | + | ||
| 72 | // It's a experimental feature | 75 | // It's a experimental feature | 
| 73 | -class SimpleBuilder extends StatefulWidget { | ||
| 74 | - final Widget Function(BuildContext) builder; | 76 | +class SimpleBuilder extends ObxStatelessWidget { | 
| 77 | + final WidgetBuilder builder; | ||
| 75 | 78 | ||
| 76 | const SimpleBuilder({Key? key, required this.builder}) : super(key: key); | 79 | const SimpleBuilder({Key? key, required this.builder}) : super(key: key); | 
| 77 | 80 | ||
| 78 | @override | 81 | @override | 
| 79 | - _SimpleBuilderState createState() => _SimpleBuilderState(); | 82 | + Widget build(BuildContext context) => builder(context); | 
| 80 | } | 83 | } | 
| 81 | 84 | ||
| 82 | -class _SimpleBuilderState extends State<SimpleBuilder> | ||
| 83 | - with GetStateUpdaterMixin { | 85 | +/// A StatelessWidget than can listen reactive changes. | 
| 86 | +abstract class ObxStatelessWidget extends StatelessWidget { | ||
| 87 | + /// Initializes [key] for subclasses. | ||
| 88 | + const ObxStatelessWidget({Key? key}) : super(key: key); | ||
| 89 | + @override | ||
| 90 | + StatelessElement createElement() => ObxElement(this); | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +/// a Component that can track changes in a reactive variable | ||
| 94 | +mixin ObserverComponent on ComponentElement { | ||
| 84 | final disposers = <Disposer>[]; | 95 | final disposers = <Disposer>[]; | 
| 85 | 96 | ||
| 86 | @override | 97 | @override | 
| 87 | - void dispose() { | ||
| 88 | - super.dispose(); | 98 | + Widget build() => | 
| 99 | + TaskManager.instance.exchange(disposers, markNeedsBuild, super.build); | ||
| 100 | + | ||
| 101 | + @override | ||
| 102 | + void unmount() { | ||
| 103 | + super.unmount(); | ||
| 89 | for (final disposer in disposers) { | 104 | for (final disposer in disposers) { | 
| 90 | disposer(); | 105 | disposer(); | 
| 91 | } | 106 | } | 
| 92 | } | 107 | } | 
| 93 | - | ||
| 94 | - @override | ||
| 95 | - Widget build(BuildContext context) { | ||
| 96 | - return TaskManager.instance.exchange( | ||
| 97 | - disposers, | ||
| 98 | - getUpdate, | ||
| 99 | - widget.builder, | ||
| 100 | - context, | ||
| 101 | - ); | ||
| 102 | - } | ||
| 103 | } | 108 | } | 
test/.DS_Store
0 → 100644
No preview for this file type
- 
Please register or login to post a comment