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