roi peker

fix comment, adds Rx features.

- small comment fix (https://github.com/jonataslaw/getx/pull/560#commitcomment-42045326)
- added `RxBool.toggle()`as an easy shortcut for switching true/false values.
- added `_RxImp.nil()` to easily set the value to `null` (`nil` comes from LISP :P) seems to be a useful sometimes, for instance if using `RxString` in `TextField.decoration.errorText` is the only way to avoid the "error state".
- adds missing docs to Rx classes.
@@ -3,8 +3,12 @@ import 'dart:collection'; @@ -3,8 +3,12 @@ import 'dart:collection';
3 3
4 import '../rx_core/rx_interface.dart'; 4 import '../rx_core/rx_interface.dart';
5 5
  6 +
  7 +/// global object that registers against `GetX` and `Obx`, and allows the reactivity
  8 +/// of those `Widgets` and Rx values.
6 RxInterface getObs; 9 RxInterface getObs;
7 10
  11 +/// Base Rx class that manages all the stream logic for any Type.
8 class _RxImpl<T> implements RxInterface<T> { 12 class _RxImpl<T> implements RxInterface<T> {
9 StreamController<T> subject = StreamController<T>.broadcast(); 13 StreamController<T> subject = StreamController<T>.broadcast();
10 final _subscriptions = HashMap<Stream<T>, StreamSubscription>(); 14 final _subscriptions = HashMap<Stream<T>, StreamSubscription>();
@@ -17,7 +21,7 @@ class _RxImpl<T> implements RxInterface<T> { @@ -17,7 +21,7 @@ class _RxImpl<T> implements RxInterface<T> {
17 /// Example: 21 /// Example:
18 /// ``` 22 /// ```
19 /// var counter = 0.obs ; 23 /// var counter = 0.obs ;
20 - /// counter >>= 3; // same as counter.value=3; 24 + /// counter <<= 3; // same as counter.value=3;
21 /// print(counter); // calls .toString() now 25 /// print(counter); // calls .toString() now
22 /// ``` 26 /// ```
23 /// 27 ///
@@ -99,11 +103,27 @@ class _RxImpl<T> implements RxInterface<T> { @@ -99,11 +103,27 @@ class _RxImpl<T> implements RxInterface<T> {
99 subject.add(_value); 103 subject.add(_value);
100 } 104 }
101 105
  106 + /// updates the value to [null] and adds it to the Stream.
  107 + /// Even with null-safety coming, is still an important feature to support, as
  108 + /// [call()] doesn't accept [null] values. For instance,
  109 + /// [InputDecoration.errorText] has to be null to not show the "error state".
  110 + ///
  111 + /// Sample:
  112 + /// ```
  113 + /// final inputError = ''.obs..nil();
  114 + /// print('${inputError.runtimeType}: $inputError'); // outputs > RxString: null
  115 + /// ```
  116 + void nil() {
  117 + subject.add(_value=null);
  118 + }
  119 +
  120 + /// Same as `toString()` but using a getter.
102 String get string => value.toString(); 121 String get string => value.toString();
103 122
104 @override 123 @override
105 String toString() => value.toString(); 124 String toString() => value.toString();
106 125
  126 + /// Returns the json representation of `value`.
107 dynamic toJson() => value; 127 dynamic toJson() => value;
108 128
109 /// This equality override works for _RxImpl instances and the internal 129 /// This equality override works for _RxImpl instances and the internal
@@ -121,12 +141,15 @@ class _RxImpl<T> implements RxInterface<T> { @@ -121,12 +141,15 @@ class _RxImpl<T> implements RxInterface<T> {
121 // ignore: avoid_equals_and_hash_code_on_mutable_classes 141 // ignore: avoid_equals_and_hash_code_on_mutable_classes
122 int get hashCode => _value.hashCode; 142 int get hashCode => _value.hashCode;
123 143
  144 + /// Closes the subscriptions for this Rx, releasing the resources.
124 void close() { 145 void close() {
125 _subscriptions.forEach((observable, subscription) => subscription.cancel()); 146 _subscriptions.forEach((observable, subscription) => subscription.cancel());
126 _subscriptions.clear(); 147 _subscriptions.clear();
127 subject.close(); 148 subject.close();
128 } 149 }
129 150
  151 + /// This is an internal method.
  152 + /// Subscribe to changes on the inner stream.
130 void addListener(Stream<T> rxGetx) { 153 void addListener(Stream<T> rxGetx) {
131 if (_subscriptions.containsKey(rxGetx)) { 154 if (_subscriptions.containsKey(rxGetx)) {
132 return; 155 return;
@@ -138,6 +161,9 @@ class _RxImpl<T> implements RxInterface<T> { @@ -138,6 +161,9 @@ class _RxImpl<T> implements RxInterface<T> {
138 161
139 bool firstRebuild = true; 162 bool firstRebuild = true;
140 163
  164 +
  165 + /// Updates the [value] and adds it to the stream, updating the observer
  166 + /// Widget, only it's different from the previous value.
141 set value(T val) { 167 set value(T val) {
142 if (_value == val && !firstRebuild) return; 168 if (_value == val && !firstRebuild) return;
143 firstRebuild = false; 169 firstRebuild = false;
@@ -145,6 +171,7 @@ class _RxImpl<T> implements RxInterface<T> { @@ -145,6 +171,7 @@ class _RxImpl<T> implements RxInterface<T> {
145 subject.add(_value); 171 subject.add(_value);
146 } 172 }
147 173
  174 + /// Returns the current [value]
148 T get value { 175 T get value {
149 if (getObs != null) { 176 if (getObs != null) {
150 getObs.addListener(subject.stream); 177 getObs.addListener(subject.stream);
@@ -158,11 +185,15 @@ class _RxImpl<T> implements RxInterface<T> { @@ -158,11 +185,15 @@ class _RxImpl<T> implements RxInterface<T> {
158 {Function onError, void Function() onDone, bool cancelOnError}) => 185 {Function onError, void Function() onDone, bool cancelOnError}) =>
159 stream.listen(onData, onError: onError, onDone: onDone); 186 stream.listen(onData, onError: onError, onDone: onDone);
160 187
  188 +
  189 + /// Binds an existing stream to this Rx to keep the values in sync.
161 void bindStream(Stream<T> stream) => stream.listen((va) => value = va); 190 void bindStream(Stream<T> stream) => stream.listen((va) => value = va);
162 191
163 Stream<R> map<R>(R mapper(T data)) => stream.map(mapper); 192 Stream<R> map<R>(R mapper(T data)) => stream.map(mapper);
164 } 193 }
165 194
  195 +
  196 +/// Rx class for `bool` Type.
166 class RxBool extends _RxImpl<bool> { 197 class RxBool extends _RxImpl<bool> {
167 RxBool([bool initial]) { 198 RxBool([bool initial]) {
168 _value = initial; 199 _value = initial;
@@ -174,11 +205,20 @@ class RxBool extends _RxImpl<bool> { @@ -174,11 +205,20 @@ class RxBool extends _RxImpl<bool> {
174 205
175 bool operator ^(bool other) => !other == value; 206 bool operator ^(bool other) => !other == value;
176 207
  208 + /// Toggles the bool [value] between false and true.
  209 + /// A shortcut for `flag.value = !flag.value;`
  210 + RxBool toggle() {
  211 + subject.add(_value = !_value);
  212 + return this;
  213 + }
  214 +
177 String toString() { 215 String toString() {
178 return value ? "true" : "false"; 216 return value ? "true" : "false";
179 } 217 }
180 } 218 }
181 219
  220 +/// Base Rx class for `num` Types (`double` and `int`) as mostly share the same
  221 +/// operator overload, we centralize the common code here.
182 abstract class _BaseRxNum<T> extends _RxImpl<num> { 222 abstract class _BaseRxNum<T> extends _RxImpl<num> {
183 _BaseRxNum operator +(num val) { 223 _BaseRxNum operator +(num val) {
184 subject.add(_value += val); 224 subject.add(_value += val);
@@ -216,18 +256,21 @@ abstract class _BaseRxNum<T> extends _RxImpl<num> { @@ -216,18 +256,21 @@ abstract class _BaseRxNum<T> extends _RxImpl<num> {
216 bool operator >(num other) => _value > other; 256 bool operator >(num other) => _value > other;
217 } 257 }
218 258
  259 +/// Rx class for `double` Type.
219 class RxDouble extends _BaseRxNum<double> { 260 class RxDouble extends _BaseRxNum<double> {
220 RxDouble([double initial]) { 261 RxDouble([double initial]) {
221 _value = initial; 262 _value = initial;
222 } 263 }
223 } 264 }
224 265
  266 +/// Rx class for `num` Type.
225 class RxNum extends _BaseRxNum<num> { 267 class RxNum extends _BaseRxNum<num> {
226 RxNum([num initial]) { 268 RxNum([num initial]) {
227 _value = initial; 269 _value = initial;
228 } 270 }
229 } 271 }
230 272
  273 +/// Rx class for `String` Type.
231 class RxString extends _RxImpl<String> { 274 class RxString extends _RxImpl<String> {
232 RxString([String initial]) { 275 RxString([String initial]) {
233 _value = initial; 276 _value = initial;
@@ -244,12 +287,17 @@ class RxString extends _RxImpl<String> { @@ -244,12 +287,17 @@ class RxString extends _RxImpl<String> {
244 } 287 }
245 } 288 }
246 289
  290 +/// Rx class for `int` Type.
247 class RxInt extends _BaseRxNum<int> { 291 class RxInt extends _BaseRxNum<int> {
248 RxInt([int initial]) { 292 RxInt([int initial]) {
249 _value = initial; 293 _value = initial;
250 } 294 }
251 } 295 }
252 296
  297 +
  298 +/// Foundation class used for custom `Types` outside the common native Dart types.
  299 +/// For example, any custom "Model" class, like User().obs will use `Rx` as
  300 +/// wrapper.
253 class Rx<T> extends _RxImpl<T> { 301 class Rx<T> extends _RxImpl<T> {
254 Rx([T initial]) { 302 Rx([T initial]) {
255 _value = initial; 303 _value = initial;
@@ -262,21 +310,26 @@ class Rx<T> extends _RxImpl<T> { @@ -262,21 +310,26 @@ class Rx<T> extends _RxImpl<T> {
262 } 310 }
263 311
264 extension StringExtension on String { 312 extension StringExtension on String {
  313 + /// Returns a `RxString` with [this] `String` as initial value.
265 RxString get obs => RxString(this); 314 RxString get obs => RxString(this);
266 } 315 }
267 316
268 extension IntExtension on int { 317 extension IntExtension on int {
  318 + /// Returns a `RxInt` with [this] `int` as initial value.
269 RxInt get obs => RxInt(this); 319 RxInt get obs => RxInt(this);
270 } 320 }
271 321
272 extension DoubleExtension on double { 322 extension DoubleExtension on double {
  323 + /// Returns a `RxDouble` with [this] `double` as initial value.
273 RxDouble get obs => RxDouble(this); 324 RxDouble get obs => RxDouble(this);
274 } 325 }
275 326
276 extension BoolExtension on bool { 327 extension BoolExtension on bool {
  328 + /// Returns a `RxBool` with [this] `bool` as initial value.
277 RxBool get obs => RxBool(this); 329 RxBool get obs => RxBool(this);
278 } 330 }
279 331
280 extension RxT<T> on T { 332 extension RxT<T> on T {
  333 + /// Returns a `Rx` instace with [this] `T` as initial value.
281 Rx<T> get obs => Rx<T>(this); 334 Rx<T> get obs => Rx<T>(this);
282 } 335 }