Line data Source code
1 : import 'dart:async';
2 : import 'rx_interface.dart';
3 :
4 : class _RxImpl<T> implements RxInterface<T> {
5 : StreamController<T> subject = StreamController<T>.broadcast();
6 : Map<Stream<T>, StreamSubscription> _subscriptions = Map();
7 :
8 : T _value;
9 4 : T get value {
10 : if (getObs != null) {
11 9 : getObs.addListener(subject.stream);
12 : }
13 4 : return _value;
14 : }
15 :
16 0 : String get string => value.toString();
17 :
18 2 : close() {
19 6 : _subscriptions.forEach((observable, subscription) {
20 2 : subscription.cancel();
21 : });
22 4 : _subscriptions.clear();
23 4 : subject.close();
24 : }
25 :
26 3 : addListener(Stream<T> rxGetx) {
27 6 : if (_subscriptions.containsKey(rxGetx)) {
28 : return;
29 : }
30 12 : _subscriptions[rxGetx] = rxGetx.listen((data) {
31 6 : subject.add(data);
32 : });
33 : }
34 :
35 : bool firstRebuild = true;
36 :
37 4 : set value(T val) {
38 8 : if (_value == val && !firstRebuild) return;
39 4 : firstRebuild = false;
40 4 : _value = val;
41 12 : subject.add(_value);
42 : }
43 :
44 0 : Stream<T> get stream => subject.stream;
45 :
46 0 : StreamSubscription<T> listen(void Function(T) onData,
47 : {Function onError, void Function() onDone, bool cancelOnError}) =>
48 0 : stream.listen(onData, onError: onError, onDone: onDone);
49 :
50 0 : void bindStream(Stream<T> stream) => stream.listen((va) => value = va);
51 0 : Stream<R> map<R>(R mapper(T data)) => stream.map(mapper);
52 : }
53 :
54 : class RxMap<K, V> extends RxInterface implements Map<K, V> {
55 3 : RxMap([Map<K, V> initial]) {
56 3 : _value = initial;
57 : }
58 :
59 : @override
60 : StreamController subject = StreamController<Map<K, V>>.broadcast();
61 : final Map<Stream<Map<K, V>>, StreamSubscription> _subscriptions = {};
62 :
63 : Map<K, V> _value;
64 3 : Map<K, V> get value {
65 : if (getObs != null) {
66 9 : getObs.addListener(subject.stream);
67 : }
68 3 : return _value;
69 : }
70 :
71 0 : String get string => value.toString();
72 :
73 0 : @override
74 : void close() {
75 0 : _subscriptions.forEach((observable, subscription) {
76 0 : subscription.cancel();
77 : });
78 0 : _subscriptions.clear();
79 0 : subject.close();
80 : }
81 :
82 0 : @override
83 : void addListener(Stream rxGetx) {
84 0 : if (_subscriptions.containsKey(rxGetx)) {
85 : return;
86 : }
87 0 : _subscriptions[rxGetx] = rxGetx.listen((data) {
88 0 : subject.add(data);
89 : });
90 : }
91 :
92 0 : set value(Map<K, V> val) {
93 0 : if (_value == val) return;
94 0 : _value = val;
95 0 : subject.add(_value);
96 : }
97 :
98 0 : Stream<Map<K, V>> get stream => subject.stream;
99 :
100 0 : StreamSubscription<Map<K, V>> listen(void Function(Map<K, V>) onData,
101 : {Function onError, void Function() onDone, bool cancelOnError}) =>
102 0 : stream.listen(onData, onError: onError, onDone: onDone);
103 :
104 0 : void bindStream(Stream<Map<K, V>> stream) =>
105 0 : stream.listen((va) => value = va);
106 :
107 0 : void add(K key, V value) {
108 0 : _value[key] = value;
109 0 : subject.add(_value);
110 : }
111 :
112 0 : void addIf(condition, K key, V value) {
113 0 : if (condition is Condition) condition = condition();
114 0 : if (condition is bool && condition) {
115 0 : _value[key] = value;
116 0 : subject.add(_value);
117 : }
118 : }
119 :
120 0 : void addAllIf(condition, Map<K, V> values) {
121 0 : if (condition is Condition) condition = condition();
122 0 : if (condition is bool && condition) addAll(values);
123 : }
124 :
125 0 : @override
126 : V operator [](Object key) {
127 0 : return value[key];
128 : }
129 :
130 0 : @override
131 : void operator []=(K key, V value) {
132 0 : _value[key] = value;
133 0 : subject.add(_value);
134 : }
135 :
136 3 : @override
137 : void addAll(Map<K, V> other) {
138 6 : _value.addAll(other);
139 9 : subject.add(_value);
140 : }
141 :
142 0 : @override
143 : void addEntries(Iterable<MapEntry<K, V>> entries) {
144 0 : _value.addEntries(entries);
145 0 : subject.add(_value);
146 : }
147 :
148 0 : @override
149 : void clear() {
150 0 : _value.clear();
151 0 : subject.add(_value);
152 : }
153 :
154 0 : @override
155 0 : Map<K2, V2> cast<K2, V2>() => _value.cast<K2, V2>();
156 :
157 0 : @override
158 0 : bool containsKey(Object key) => _value.containsKey(key);
159 :
160 0 : @override
161 0 : bool containsValue(Object value) => _value.containsValue(value);
162 :
163 0 : @override
164 0 : Iterable<MapEntry<K, V>> get entries => _value.entries;
165 :
166 0 : @override
167 : void forEach(void Function(K, V) f) {
168 0 : _value.forEach(f);
169 : }
170 :
171 0 : @override
172 0 : bool get isEmpty => _value.isEmpty;
173 :
174 0 : @override
175 0 : bool get isNotEmpty => _value.isNotEmpty;
176 :
177 0 : @override
178 0 : Iterable<K> get keys => _value.keys;
179 :
180 0 : @override
181 0 : int get length => value.length;
182 :
183 0 : @override
184 : Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> Function(K, V) transform) =>
185 0 : value.map(transform);
186 :
187 0 : @override
188 : V putIfAbsent(K key, V Function() ifAbsent) {
189 0 : final val = _value.putIfAbsent(key, ifAbsent);
190 0 : subject.add(_value);
191 : return val;
192 : }
193 :
194 0 : @override
195 : V remove(Object key) {
196 0 : final val = _value.remove(key);
197 0 : subject.add(_value);
198 : return val;
199 : }
200 :
201 0 : @override
202 : void removeWhere(bool Function(K, V) test) {
203 0 : _value.removeWhere(test);
204 0 : subject.add(_value);
205 : }
206 :
207 0 : @override
208 0 : Iterable<V> get values => value.values;
209 :
210 0 : @override
211 0 : String toString() => _value.toString();
212 :
213 0 : @override
214 : V update(K key, V Function(V) update, {V Function() ifAbsent}) {
215 0 : final val = _value.update(key, update, ifAbsent: ifAbsent);
216 0 : subject.add(_value);
217 : return val;
218 : }
219 :
220 0 : @override
221 : void updateAll(V Function(K, V) update) {
222 0 : _value.updateAll(update);
223 0 : subject.add(_value);
224 : }
225 : }
226 :
227 : /// Create a list similar to `List<T>`
228 : class RxList<E> extends Iterable<E> implements RxInterface<E> {
229 3 : RxList([List<E> initial]) {
230 3 : _list = initial;
231 : }
232 :
233 0 : @override
234 0 : Iterator<E> get iterator => _list.iterator;
235 :
236 0 : @override
237 0 : bool get isEmpty => value.isEmpty;
238 :
239 0 : @override
240 0 : bool get isNotEmpty => value.isNotEmpty;
241 :
242 : StreamController<E> subject = StreamController<E>.broadcast();
243 : Map<Stream<E>, StreamSubscription> _subscriptions = Map();
244 :
245 : /// Adds [item] only if [condition] resolves to true.
246 0 : void addIf(condition, E item) {
247 0 : if (condition is Condition) condition = condition();
248 0 : if (condition is bool && condition) add(item);
249 : }
250 :
251 : /// Adds all [items] only if [condition] resolves to true.
252 0 : void addAllIf(condition, Iterable<E> items) {
253 0 : if (condition is Condition) condition = condition();
254 0 : if (condition is bool && condition) addAll(items);
255 : }
256 :
257 0 : operator []=(int index, E val) {
258 0 : _list[index] = val;
259 0 : subject.add(val);
260 : }
261 :
262 0 : E operator [](int index) {
263 0 : return value[index];
264 : }
265 :
266 0 : void add(E item) {
267 0 : _list.add(item);
268 0 : subject.add(item);
269 : }
270 :
271 3 : void addAll(Iterable<E> item) {
272 6 : _list.addAll(item);
273 6 : subject.add(null);
274 : }
275 :
276 : /// Adds only if [item] is not null.
277 0 : void addNonNull(E item) {
278 0 : if (item != null) add(item);
279 : }
280 :
281 : /// Adds only if [item] is not null.
282 3 : void addAllNonNull(Iterable<E> item) {
283 3 : if (item != null) addAll(item);
284 : }
285 :
286 0 : void insert(int index, E item) {
287 0 : _list.insert(index, item);
288 0 : subject.add(item);
289 : }
290 :
291 0 : void insertAll(int index, Iterable<E> iterable) {
292 0 : _list.insertAll(index, iterable);
293 0 : subject.add(iterable.last);
294 : }
295 :
296 9 : int get length => value.length;
297 :
298 : /// Removes an item from the list.
299 : ///
300 : /// This is O(N) in the number of items in the list.
301 : ///
302 : /// Returns whether the item was present in the list.
303 0 : bool remove(Object item) {
304 0 : bool hasRemoved = _list.remove(item);
305 : if (hasRemoved) {
306 0 : subject.add(item);
307 : }
308 : return hasRemoved;
309 : }
310 :
311 0 : E removeAt(int index) {
312 0 : E item = _list.removeAt(index);
313 0 : subject.add(item);
314 : return item;
315 : }
316 :
317 0 : E removeLast() {
318 0 : E item = _list.removeLast();
319 0 : subject.add(item);
320 : return item;
321 : }
322 :
323 0 : void removeRange(int start, int end) {
324 0 : _list.removeRange(start, end);
325 0 : subject.add(null);
326 : }
327 :
328 0 : void removeWhere(bool Function(E) test) {
329 0 : _list.removeWhere(test);
330 0 : subject.add(null);
331 : }
332 :
333 0 : void clear() {
334 0 : _list.clear();
335 0 : subject.add(null);
336 : }
337 :
338 0 : void sort([int compare(E a, E b)]) {
339 0 : _list.sort();
340 0 : subject.add(null);
341 : }
342 :
343 0 : close() {
344 0 : _subscriptions.forEach((observable, subscription) {
345 0 : subscription.cancel();
346 : });
347 0 : _subscriptions.clear();
348 0 : subject.close();
349 : }
350 :
351 : /// Replaces all existing items of this list with [item]
352 0 : void assign(E item) {
353 0 : clear();
354 0 : add(item);
355 : }
356 :
357 : /// Replaces all existing items of this list with [items]
358 0 : void assignAll(Iterable<E> items) {
359 0 : clear();
360 0 : addAll(items);
361 : }
362 :
363 3 : List<E> get value {
364 : if (getObs != null) {
365 9 : getObs.addListener(subject.stream);
366 : }
367 3 : return _list;
368 : }
369 :
370 0 : String get string => value.toString();
371 :
372 0 : addListener(Stream<E> rxGetx) {
373 0 : if (_subscriptions.containsKey(rxGetx)) {
374 : return;
375 : }
376 0 : _subscriptions[rxGetx] = rxGetx.listen((data) {
377 0 : subject.add(data);
378 : });
379 : }
380 :
381 0 : set value(Iterable<E> val) {
382 0 : if (_list == val) return;
383 0 : _list = val;
384 0 : subject.add(null);
385 : }
386 :
387 0 : Stream<E> get stream => subject.stream;
388 :
389 0 : StreamSubscription<E> listen(void Function(E) onData,
390 : {Function onError, void Function() onDone, bool cancelOnError}) =>
391 0 : stream.listen(onData, onError: onError, onDone: onDone);
392 :
393 0 : void bindStream(Stream<Iterable<E>> stream) =>
394 0 : stream.listen((va) => value = va);
395 :
396 : List<E> _list = <E>[];
397 : }
398 :
399 : RxInterface getObs;
400 :
401 : typedef bool Condition();
402 :
403 : typedef E ChildrenListComposer<S, E>(S value);
404 :
405 : class RxBool extends _RxImpl<bool> {
406 3 : RxBool([bool initial]) {
407 3 : _value = initial;
408 : }
409 : }
410 :
411 : class RxDouble extends _RxImpl<double> {
412 3 : RxDouble([double initial]) {
413 3 : _value = initial;
414 : }
415 : }
416 :
417 : class RxNum extends _RxImpl<num> {
418 0 : RxNum([num initial]) {
419 0 : _value = initial;
420 : }
421 : }
422 :
423 : class RxString extends _RxImpl<String> {
424 3 : RxString([String initial]) {
425 3 : _value = initial;
426 : }
427 : }
428 :
429 : class RxInt extends _RxImpl<int> {
430 4 : RxInt([int initial]) {
431 4 : _value = initial;
432 : }
433 : }
434 :
435 : class Rx<T> extends _RxImpl<T> {
436 3 : Rx([T initial]) {
437 3 : _value = initial;
438 : }
439 : }
440 :
441 : extension StringExtension on String {
442 6 : RxString get obs => RxString(this);
443 : }
444 :
445 : extension IntExtension on int {
446 8 : RxInt get obs => RxInt(this);
447 : }
448 :
449 : extension DoubleExtension on double {
450 6 : RxDouble get obs => RxDouble(this);
451 : }
452 :
453 : extension BoolExtension on bool {
454 6 : RxBool get obs => RxBool(this);
455 : }
456 :
457 : extension MapExtension<K, V> on Map<K, V> {
458 3 : RxMap<K, V> get obs {
459 : if (this != null)
460 9 : return RxMap<K, V>(<K, V>{})..addAll(this);
461 : else
462 0 : return RxMap<K, V>(null);
463 : }
464 : }
465 :
466 : extension ListExtension<E> on List<E> {
467 3 : RxList<E> get obs {
468 : if (this != null)
469 9 : return RxList<E>(<E>[])..addAllNonNull(this);
470 : else
471 0 : return RxList<E>(null);
472 : }
473 : }
474 :
475 : extension RxT<T> on T {
476 0 : Rx<T> get obs => Rx(this);
477 : }
|