Line data Source code
1 : import 'dart:async'; 2 : 3 : import 'rx.dart'; 4 : 5 : extension RxExtensions<T> on Rx<T> { 6 : /// [callback] is called every time that the [Rx<T>] changes. 7 : /// 8 : /// If [condition] is not null the [callback] only is called if [condition] returns true. 9 1 : RxReaction ever(void Function(T) callback, {bool Function(T)? condition}) { 10 : // ignore: cancel_subscriptions 11 3 : final StreamSubscription subscription = stream.listen((event) { 12 : if (condition != null) { 13 1 : if (condition(event)) { 14 1 : callback(event); 15 : } 16 : } else { 17 1 : callback(event); 18 : } 19 : }); 20 1 : return RxReaction(subscription, null); 21 : } 22 : 23 : /// the [callback] will be executed only 1 time 24 : /// 25 : /// If [condition] is not null the [callback] only is called if [condition] returns true. 26 1 : RxReaction once(void Function(T) callback, {bool Function(T)? condition}) { 27 : late RxReaction reaction; 28 : // ignore: cancel_subscriptions 29 3 : StreamSubscription subscription = stream.listen((event) { 30 : if (condition != null) { 31 1 : if (condition(event)) { 32 1 : callback(event); 33 1 : reaction.dispose(); 34 : } 35 : } else { 36 1 : callback(event); 37 1 : reaction.dispose(); 38 : } 39 : }); 40 1 : return reaction = RxReaction(subscription, null); 41 : } 42 : 43 : /// the [callback] will be called every certain time interval ignoring the other changes 44 1 : RxReaction interval(Duration duration, void Function(T) callback) { 45 1 : var debouncer = Debouncer(duration); 46 : // ignore: cancel_subscriptions 47 3 : final StreamSubscription subscription = stream.listen((event) { 48 1 : if (!debouncer.isRunning) { 49 2 : debouncer.call(() { 50 1 : callback(event); 51 1 : debouncer = Debouncer(duration); 52 : }); 53 : } 54 : }); 55 1 : return RxReaction(subscription, debouncer); 56 : } 57 : 58 : /// Every time that the [Rx<T>] changes the [callback] will be called after a delay. 59 1 : RxReaction debounce(Duration delay, void Function(T) callback) { 60 1 : final debouncer = Debouncer(delay); 61 : // ignore: cancel_subscriptions 62 3 : final StreamSubscription subscription = stream.listen((event) { 63 2 : debouncer.call(() { 64 1 : callback(event); 65 : }); 66 : }); 67 1 : return RxReaction(subscription, debouncer); 68 : } 69 : } 70 : 71 : /// this class allow us to cancel schedules tasks and subscriptions 72 : class RxReaction { 73 1 : RxReaction(this._subscription, this._debouncer); 74 : 75 : final StreamSubscription _subscription; 76 : final Debouncer? _debouncer; 77 : bool _disposed = false; 78 : 79 1 : Future<void> dispose() async { 80 1 : if (_disposed) return; 81 : // cancel a schedule task 82 2 : _debouncer?.cancel(); 83 : // cancel the events susbcription 84 2 : await _subscription.cancel(); 85 1 : _disposed = true; 86 : } 87 : } 88 : 89 : /// this class is an implementenacion of a debounce functionallity 90 : class Debouncer { 91 1 : Debouncer(this.delay); 92 : 93 : /// delay for a schedule task 94 : final Duration delay; 95 : 96 : // timer for a schedule task 97 : Timer? _timer; 98 : 99 1 : void call(void Function() action) { 100 2 : _timer?.cancel(); // cancel the current task 101 3 : _timer = Timer(delay, action); 102 : } 103 : 104 : /// Notifies if the delayed call is active. 105 3 : bool get isRunning => _timer?.isActive ?? false; 106 : 107 : /// Cancel the current delayed call. 108 3 : void cancel() => _timer?.cancel(); 109 : }