LCOV - code coverage report
Current view: top level - graph - notifier_extension.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 50 50 100.0 %
Date: 2021-06-18 12:41:16 Functions: 0 0 -

          Line data    Source code
       1             : library notifier_extension;
       2             : 
       3             : import 'dart:async';
       4             : 
       5             : import 'package:state_notifier/state_notifier.dart';
       6             : 
       7             : class DelayedStateNotifier<T> extends StateNotifier<T?> {
       8           2 :   DelayedStateNotifier() : super(null);
       9             : 
      10           1 :   @override
      11             :   RemoveListener addListener(void Function(T) listener,
      12             :       {bool fireImmediately = true}) {
      13           1 :     final _listener = (T? value) {
      14             :       // if `value` is `null` and `T` is actually a nullable
      15             :       // type, then the listener MUST be called with `null`
      16           1 :       if (_typesEqual<T, T?>() && value == null) {
      17           1 :         listener(null as T);
      18             :       } else {
      19             :         // if `value != null` and `T` is non-nullable, also
      20           1 :         listener(value!);
      21             :       }
      22             :     };
      23           1 :     return super.addListener(_listener, fireImmediately: false);
      24             :   }
      25             : 
      26           2 :   bool _typesEqual<T1, T2>() => T1 == T2;
      27             : }
      28             : 
      29             : class _FunctionalStateNotifier<S, T> extends DelayedStateNotifier<T> {
      30             :   final DelayedStateNotifier<S> _source;
      31             :   final String? name;
      32             :   late RemoveListener _sourceDisposeFn;
      33             :   Timer? _timer;
      34             : 
      35           1 :   _FunctionalStateNotifier(this._source, {this.name});
      36             : 
      37           1 :   DelayedStateNotifier<T> where(bool Function(S) test) {
      38           4 :     _sourceDisposeFn = _source.addListener((_state) {
      39           1 :       if (test(_state)) {
      40           1 :         state = _state as T;
      41             :       }
      42             :     }, fireImmediately: false);
      43             :     return this;
      44             :   }
      45             : 
      46           1 :   DelayedStateNotifier<void> forEach(void Function(S) action) {
      47           3 :     _sourceDisposeFn = _source.addListener(action, fireImmediately: false);
      48             :     return this;
      49             :   }
      50             : 
      51           1 :   DelayedStateNotifier<T> map(T Function(S) convert) {
      52           4 :     _sourceDisposeFn = _source.addListener((state) {
      53           2 :       super.state = convert(state);
      54             :     }, fireImmediately: false);
      55             :     return this;
      56             :   }
      57             : 
      58             :   final _bufferedState = <S>[];
      59             : 
      60           1 :   DelayedStateNotifier<T> throttle(Duration Function() durationFn) {
      61           2 :     _timer = _makeTimer(durationFn);
      62           4 :     _sourceDisposeFn = _source.addListener((model) {
      63           2 :       _bufferedState.add(model);
      64             :     }, fireImmediately: false);
      65             :     return this;
      66             :   }
      67             : 
      68           1 :   Timer _makeTimer(Duration Function() durationFn) {
      69           3 :     return Timer(durationFn(), () {
      70           1 :       if (mounted) {
      71           2 :         if (_bufferedState.isNotEmpty) {
      72           2 :           super.state = _bufferedState as T; // since T == List<S>;
      73           2 :           _bufferedState.clear(); // clear buffer
      74             :         }
      75           2 :         _timer = _makeTimer(durationFn); // reset timer
      76             :       }
      77             :     });
      78             :   }
      79             : 
      80           1 :   @override
      81             :   RemoveListener addListener(
      82             :     Listener<T> listener, {
      83             :     bool fireImmediately = true,
      84             :   }) {
      85             :     // final _listener = (T? event) {
      86             :     //   return listener.call(event!);
      87             :     // };
      88             :     final dispose =
      89           1 :         super.addListener(listener, fireImmediately: fireImmediately);
      90           1 :     return () {
      91           1 :       dispose.call();
      92           2 :       _timer?.cancel();
      93           2 :       _sourceDisposeFn.call();
      94             :     };
      95             :   }
      96             : 
      97           1 :   @override
      98             :   void dispose() {
      99           1 :     if (mounted) {
     100           1 :       super.dispose();
     101             :     }
     102           2 :     _source.dispose();
     103           2 :     _timer?.cancel();
     104             :   }
     105             : }
     106             : 
     107             : /// Functional utilities for [StateNotifier]
     108             : extension StateNotifierX<T> on DelayedStateNotifier<T> {
     109             :   /// Filters incoming events by [test]
     110           1 :   DelayedStateNotifier<T> where(bool Function(T) test) {
     111           2 :     return _FunctionalStateNotifier<T, T>(this, name: 'where').where(test);
     112             :   }
     113             : 
     114             :   /// Maps events of type [T] onto events of type [R] via [convert]
     115           1 :   DelayedStateNotifier<R> map<R>(R Function(T) convert) {
     116           2 :     return _FunctionalStateNotifier<T, R>(this, name: 'map').map(convert);
     117             :   }
     118             : 
     119             :   /// Applies a function [action] to every incoming event of type [T]
     120           1 :   DelayedStateNotifier<void> forEach(void Function(T) action) {
     121           1 :     return _FunctionalStateNotifier<T, void>(this, name: 'forEach')
     122           1 :         .forEach(action);
     123             :   }
     124             : 
     125             :   /// Buffers all incoming [T] events for a duration obtained via
     126             :   /// [durationFn] and emits them as a [List<T>] (unless there were none)
     127           1 :   DelayedStateNotifier<List<T>> throttle(Duration Function() durationFn) {
     128           1 :     return _FunctionalStateNotifier<T, List<T>>(this, name: 'throttle')
     129           1 :         .throttle(durationFn);
     130             :   }
     131             : }

Generated by: LCOV version 1.15