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