LCOV - code coverage report
Current view: top level - src/state/widgets - watch_filter.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 52 52 100.0 %
Date: 2022-11-04 14:47:16 Functions: 0 0 -

          Line data    Source code
       1             : // ignore_for_file: avoid_dynamic_calls
       2             : 
       3             : import 'package:meedu/provider.dart';
       4             : import 'package:meedu/state.dart';
       5             : 
       6             : typedef _BuildWhen<S> = bool Function(S prev, S current);
       7             : typedef _BuildBySelect<Notifier, Result> = Result Function(Notifier);
       8             : 
       9             : /// enum used to identifier filters used in a provider
      10             : enum Filter {
      11             :   /// .select filter for SimpleProvider and StateProvider
      12             :   select,
      13             : 
      14             :   /// .when filter fot StateProvider
      15             :   /// this filter only can be  used with ref.watch
      16             :   when,
      17             : }
      18             : 
      19             : /// class to save a Notifier, the listener and the rebuild function
      20             : class Target<Notifier, Result> extends ListeneableProvider<Notifier> {
      21             :   // ignore: public_member_api_docs
      22           6 :   Target(this.notifier);
      23             : 
      24             :   /// a SimpleNotifier or a StateNotifier
      25             :   final Notifier notifier;
      26             : 
      27             :   /// listener to listen the changes in our Notifiers
      28             :   late void Function(dynamic) listener;
      29             : 
      30             :   /// function to rebuild the Consumer
      31             :   void Function()? rebuild;
      32             : 
      33             :   /// used to store the value returned by .select or .when
      34             :   late Result selectValue;
      35             : 
      36             :   /// callback defined when a filter is used
      37             :   late Function callback;
      38             : 
      39             :   /// filter type
      40             :   late Filter filter;
      41             : 
      42             :   /// if the filter is a selected and we only want to
      43             :   /// rebuild the consumer when the callback returns true
      44             :   late bool listenWhenTheCallbackReturnsTrue;
      45             : }
      46             : 
      47             : /// extension for SimpleProvider
      48             : extension SimpleProviderExt<Notifier> on SimpleProvider<Notifier> {
      49             :   /// use this method to rebuild your Consumer when a value has changed
      50             :   /// or you can use a boolean condition. Check the documentation for more info.
      51             :   ///
      52             :   /// [booleanCallback] If your callback returns a boolean and you want to
      53             :   /// rebuild your consumers or notify to your listeners only when the boolean
      54             :   /// value is true you can set [booleanCallback] as true
      55             :   ///
      56             :   /// EXAMPLE:
      57             :   /// ```dart
      58             :   ///    final controller = ref.watch(
      59             :   ///    provider.select(
      60             :   ///      (_) => _.user != null,
      61             :   ///      booleanCallback: true,
      62             :   ///    ),
      63             :   ///  );
      64             :   /// ```
      65             :   ///
      66           4 :   Target<Notifier, Result> select<Result>(
      67             :     _BuildBySelect<Notifier, Result> callback, {
      68             :     bool booleanCallback = false,
      69             :   }) {
      70             :     // get the  Notifier attached to this SimpleProvider
      71           8 :     final target = Target<Notifier, Result>(read);
      72           4 :     target.filter = Filter.select;
      73           4 :     target.callback = callback;
      74           4 :     target.listenWhenTheCallbackReturnsTrue = booleanCallback;
      75             :     return target;
      76             :   }
      77             : }
      78             : 
      79             : /// extension for StateProvider
      80             : extension StateProviderExt<Notifier extends StateNotifier<S>, S>
      81             :     on StateProvider<Notifier, S> {
      82             :   /// use this method to rebuild your Consumer using the previous state and the current
      83             :   /// state to return a boolean
      84           3 :   Target<Notifier, bool> when(_BuildWhen<S> callback) {
      85           6 :     final target = Target<Notifier, bool>(read);
      86           3 :     target.filter = Filter.when;
      87           3 :     target.callback = callback;
      88           3 :     target.listenWhenTheCallbackReturnsTrue = false;
      89             :     return target;
      90             :   }
      91             : 
      92             :   /// use this method to rebuild your Consumer when a value in the state has changed
      93             :   /// or you can use a boolean condition. Check the documentation for more info.
      94             :   ///
      95             :   /// [booleanCallback] If your callback returns a boolean and you want to
      96             :   /// rebuild your consumers or notify to your listeners only when the boolean
      97             :   /// value is true you can set [booleanCallback] as true
      98             :   ///
      99             :   /// EXAMPLE:
     100             :   /// ```dart
     101             :   ///    final controller = ref.watch(
     102             :   ///    provider.select(
     103             :   ///      (_) => _.user != null,
     104             :   ///      booleanCallback: true,
     105             :   ///    ),
     106             :   ///  );
     107             :   /// ```
     108             :   ///
     109           3 :   Target<Notifier, Result> select<Result>(
     110             :     _BuildBySelect<S, Result> callback, {
     111             :     bool booleanCallback = false,
     112             :   }) {
     113           6 :     final target = Target<Notifier, Result>(read);
     114           3 :     target.filter = Filter.select;
     115           3 :     target.callback = callback;
     116           3 :     target.listenWhenTheCallbackReturnsTrue = booleanCallback;
     117             :     return target;
     118             :   }
     119             : }
     120             : 
     121             : /// create the listener for provider.select filter (SimpleProvider)
     122           4 : void createSimpleSelectListener(Target target) {
     123           4 :   final notifier = target.notifier;
     124             :   // get an initial value using the callback
     125           8 :   dynamic prevValue = target.callback(notifier);
     126           4 :   target.selectValue = prevValue;
     127             : 
     128             :   // listener with  the logic to rebuild the Consumer
     129             :   // ignore: prefer_function_declarations_over_variables
     130           4 :   final listener = (_) {
     131           8 :     final value = target.callback(notifier);
     132           4 :     if (target.listenWhenTheCallbackReturnsTrue) {
     133             :       assert(
     134           6 :         value is bool,
     135             :         'The value returned by the callback must be a boolean because '
     136             :         'listenWhenTheCallbackReturnsTrue is true',
     137             :       );
     138             :     }
     139             : 
     140           4 :     target.selectValue = value;
     141             :     bool allowRebuild = false;
     142           7 :     if (value is bool && target.listenWhenTheCallbackReturnsTrue) {
     143             :       allowRebuild = value;
     144           1 :     } else if (prevValue != value) {
     145             :       allowRebuild = true;
     146             :     }
     147             : 
     148             :     // check if the value has changed
     149           3 :     if (allowRebuild && target.rebuild != null) {
     150           6 :       target.rebuild!(); // rebuild the Consumer
     151             :     }
     152             :     prevValue = value;
     153             :   };
     154             :   // save the listener to be added to our Notifier later
     155           4 :   target.listener = listener;
     156             : }
     157             : 
     158             : /// create the listener for provider.select filter (StateProvider)
     159           3 : void createStateSelectListener(Target target) {
     160          12 :   dynamic prevValue = target.callback(target.notifier.state);
     161           3 :   target.selectValue = prevValue;
     162             : 
     163             :   // ignore: prefer_function_declarations_over_variables
     164           3 :   final listener = (newState) {
     165          12 :     final value = target.callback(target.notifier.state);
     166           3 :     if (target.listenWhenTheCallbackReturnsTrue) {
     167             :       assert(
     168           4 :         value is bool,
     169             :         'The value returned by the callback must be a boolean because '
     170             :         'listenWhenTheCallbackReturnsTrue is true',
     171             :       );
     172             :     }
     173             : 
     174           3 :     target.selectValue = value;
     175             : 
     176             :     bool allowRebuild = false;
     177           5 :     if (value is bool && target.listenWhenTheCallbackReturnsTrue) {
     178             :       allowRebuild = value;
     179           1 :     } else if (prevValue != value) {
     180             :       allowRebuild = true;
     181             :     }
     182             : 
     183             :     // check if the value has changed
     184           3 :     if (allowRebuild && target.rebuild != null) {
     185           6 :       target.rebuild!();
     186             :     }
     187             :     prevValue = value;
     188             :   };
     189           3 :   target.listener = listener;
     190             : }
     191             : 
     192             : /// create the listener for provider.when filter
     193           3 : void createWhenListener(Target target) {
     194           3 :   final notifier = target.notifier as StateNotifier;
     195          15 :   target.selectValue = target.callback(notifier.state, notifier.state);
     196             : 
     197             :   // ignore: prefer_function_declarations_over_variables
     198           3 :   final listener = (newState) {
     199             :     // rebuild the Consumer using the boolean returned by the callback
     200           9 :     final allowRebuild = target.callback(notifier.oldState, newState);
     201           3 :     target.selectValue = allowRebuild;
     202             :     if (allowRebuild) {
     203           3 :       if (target.rebuild != null) {
     204           6 :         target.rebuild!();
     205             :       }
     206             :     }
     207             :   };
     208           3 :   target.listener = listener;
     209             : }

Generated by: LCOV version 1.16