LCOV - code coverage report
Current view: top level - src - multi_bloc_listener.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 18 18 100.0 %
Date: 2021-10-20 08:54:00 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/foundation.dart';
       2             : import 'package:flutter/widgets.dart';
       3             : import 'package:flutter_hooks/flutter_hooks.dart';
       4             : 
       5             : import 'package:flutter_hooks_bloc/src/bloc_listener.dart';
       6             : import 'package:flutter_hooks_bloc/src/flutter_bloc.dart';
       7             : 
       8             : /// {@template multi_bloc_listener}
       9             : /// Merges multiple [BlocListener] widgets into one widget tree.
      10             : ///
      11             : /// [MultiBlocListener] improves the readability and eliminates the need
      12             : /// to nest multiple [BlocListener]s.
      13             : ///
      14             : /// By using [MultiBlocListener] we can go from:
      15             : ///
      16             : /// ```dart
      17             : /// BlocListener<BlocA, BlocAState>(
      18             : ///   listener: (context, state) {},
      19             : ///   child: BlocListener<BlocB, BlocBState>(
      20             : ///     listener: (context, state) {},
      21             : ///     child: BlocListener<BlocC, BlocCState>(
      22             : ///       listener: (context, state) {},
      23             : ///       child: ChildA(),
      24             : ///     ),
      25             : ///   ),
      26             : /// )
      27             : /// ```
      28             : ///
      29             : /// to:
      30             : ///
      31             : /// ```dart
      32             : /// MultiBlocListener(
      33             : ///   listeners: [
      34             : ///     BlocListener<BlocA, BlocAState>(
      35             : ///       listener: (context, state) {},
      36             : ///     ),
      37             : ///     BlocListener<BlocB, BlocBState>(
      38             : ///       listener: (context, state) {},
      39             : ///     ),
      40             : ///     BlocListener<BlocC, BlocCState>(
      41             : ///       listener: (context, state) {},
      42             : ///     ),
      43             : ///   ],
      44             : ///   child: ChildA(),
      45             : /// )
      46             : /// ```
      47             : ///
      48             : /// [MultiBlocListener] avoids converts a tree of nested [BlocListener] and
      49             : /// only add a widget to the widget tree.
      50             : /// As a result, the only advantages of using [MultiBlocListener] are both the
      51             : /// reduce of widgets in the widget tree and better readability due to the
      52             : /// reduction in nesting and boilerplate.
      53             : /// {@endtemplate}
      54             : class MultiBlocListener extends HookWidget {
      55             :   /// {@macro multi_bloc_listener}
      56           2 :   MultiBlocListener({Key? key, required this.listeners, required this.child})
      57           3 :       : assert(listeners.isNotEmpty),
      58           3 :         assert(listeners._debugBlocListenerWithNoChild()),
      59           2 :         super(key: key);
      60             : 
      61             :   /// List of [BlocListener] and/or  [NestableBlocListener].
      62             :   /// Must have at least one element
      63             :   final List<NestableBlocListener> listeners;
      64             : 
      65             :   /// `child` [Widget] for [MultiBlocListener]
      66             :   final Widget child;
      67             : 
      68           1 :   @override
      69             :   Widget build(BuildContext context) {
      70           2 :     for (final it in listeners) {
      71           1 :       it.listen();
      72             :     }
      73           1 :     return child;
      74             :   }
      75             : 
      76           1 :   @override
      77             :   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
      78           1 :     super.debugFillProperties(properties);
      79           1 :     properties.add(
      80           3 :       BlocListenerTree(listeners: listeners).toDiagnosticsNode(
      81             :         name: 'listeners',
      82             :         style: DiagnosticsTreeStyle.dense,
      83             :       ),
      84             :     );
      85             :   }
      86             : 
      87           1 :   @override
      88             :   List<DiagnosticsNode> debugDescribeChildren() =>
      89           3 :       [for (final listener in listeners) listener.asDiagnosticsNode()];
      90             : }
      91             : 
      92             : /// The [NestableBlocListener] is the base for every item in a
      93             : /// [MultiBlocProvider]. Thus, the bloc listener is not limited to be a
      94             : /// [BlocListener], but can another type.
      95             : ///
      96             : /// see also
      97             : /// - [MultiBlocListener]
      98             : abstract class NestableBlocListener {
      99             :   /// The `listen` method describe how a widget must listen a [BlocBase]
     100             :   void listen();
     101             : 
     102             :   /// Given that the [NestableBlocListener] are used in a [MultiBlocProvider]
     103             :   /// The must not have a child each one. Then, the `hasNoChild` allows
     104             :   /// the [MultiBlocProvider] to check that they don't have them.
     105             :   bool get hasNoChild;
     106             : 
     107             :   /// Generates a [DiagnosticsNode] for show the `bloc` states in the debugger.
     108             :   DiagnosticsNode asDiagnosticsNode();
     109             : }
     110             : 
     111             : extension _DebugBlocListenerWithNoChildX on List<NestableBlocListener> {
     112           8 :   bool _debugBlocListenerWithNoChild() => every((it) => it.hasNoChild);
     113             : }
     114             : 
     115             : /// {@template bloc_listener_tree}
     116             : /// The [BlocListenerTree] is a [DiagnosticableTree] for showwing
     117             : /// the `bloc` providers in the devtools.
     118             : /// {@endtemplate}
     119             : @visibleForTesting
     120             : class BlocListenerTree extends DiagnosticableTree {
     121             :   /// {@macro bloc_listener_tree}
     122           1 :   const BlocListenerTree({required this.listeners});
     123             : 
     124             :   /// List of [NestableBlocListener] ([BlocListener] for example) that
     125             :   /// will be used in the [MultiBlocListener].
     126             :   final List<NestableBlocListener> listeners;
     127             : 
     128           1 :   @override
     129             :   List<DiagnosticsNode> debugDescribeChildren() =>
     130           3 :       [for (final listener in listeners) listener.asDiagnosticsNode()];
     131             : }

Generated by: LCOV version 1.15