LCOV - code coverage report
Current view: top level - list/filter - filter_list_bloc.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 31 33 93.9 %
Date: 2019-10-10 15:54:03 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:collection';
       2             : 
       3             : import 'package:bloc/bloc.dart';
       4             : import 'package:flutter_bloc/flutter_bloc.dart';
       5             : import 'package:flutter_bloc_patterns/base_list.dart';
       6             : import 'package:flutter_bloc_patterns/src/common/view_state.dart';
       7             : import 'package:flutter_bloc_patterns/src/list/base/list_events.dart';
       8             : import 'package:flutter_bloc_patterns/src/list/filter/filter_list_repository.dart';
       9             : 
      10             : /// A list BLoC with allowing filtering capabilities but without pagination.
      11             : /// Thus it should be used with a reasonable small amount of data.
      12             : ///
      13             : /// Designed to collaborate with [BlocBuilder] and [ViewStateBuilder] for
      14             : /// displaying data.
      15             : ///
      16             : /// Call [loadElements] to perform initial data fetch.
      17             : /// Call [refreshElements] to perform a refresh.
      18             : ///
      19             : /// [T] - the type of list elements.
      20             : /// [F] - the type of filter.
      21             : class FilterListBloc<T, F> extends Bloc<ListEvent, ViewState> {
      22             :   final FilterRepository<T, F> _repository;
      23             :   F _filter;
      24             : 
      25           2 :   FilterListBloc(FilterRepository<T, F> repository)
      26           0 :       : assert(repository != null),
      27             :         this._repository = repository;
      28             : 
      29           2 :   @override
      30           2 :   ViewState get initialState => Loading();
      31             : 
      32           0 :   F get filter => _filter;
      33             : 
      34             :   /// Loads elements using the given [filter].
      35             :   ///
      36             :   /// It's most suitable for initial data fetch or for retry action when
      37             :   /// the first fetch fails. It can also be used when [filter] changes when a
      38             :   /// full reload is required.
      39           6 :   void loadElements({F filter}) => dispatch(LoadList(filter));
      40             : 
      41             :   /// Refreshes elements using the given [filter].
      42             :   ///
      43             :   /// The refresh is designed for being called after the initial fetch
      44             :   /// succeeds. It can be performed when the list has already been loaded.
      45             :   ///
      46             :   /// It can be used when [filter] changes and there's no need for displaying a
      47             :   /// loading indicator.
      48           6 :   void refreshElements({F filter}) => dispatch(RefreshList(filter));
      49             : 
      50             :   @override
      51           2 :   Stream<ViewState> mapEventToState(ListEvent event) async* {
      52           2 :     if (event is LoadList) {
      53           6 :       yield* _mapLoadList(event.filter);
      54           4 :     } else if (event is RefreshList && _isRefreshPossible(event)) {
      55           6 :       yield* _mapRefreshList(event.filter);
      56             :     }
      57             :   }
      58             : 
      59           2 :   bool _isRefreshPossible(ListEvent event) =>
      60           6 :       currentState is Success || currentState is Empty;
      61             : 
      62           2 :   Stream<ViewState> _mapLoadList(F filter) async* {
      63           4 :     yield Loading();
      64           4 :     yield* _getListState(filter);
      65             :   }
      66             : 
      67           2 :   Stream<ViewState> _mapRefreshList(F filter) async* {
      68           2 :     final elements = _getCurrentStateElements();
      69           4 :     yield Refreshing(elements);
      70           4 :     yield* _getListState(filter);
      71             :   }
      72             : 
      73           2 :   List<T> _getCurrentStateElements() =>
      74           9 :       (currentState is Success) ? (currentState as Success).data : [];
      75             : 
      76           2 :   Stream<ViewState> _getListState(F filter) async* {
      77             :     try {
      78           4 :       final List<T> elements = await _getElementsFromRepository(filter);
      79           4 :       yield elements.isNotEmpty
      80           4 :           ? Success<List<T>>(UnmodifiableListView(elements))
      81           2 :           : Empty();
      82             :     } catch (e) {
      83           4 :       yield Failure(e);
      84             :     } finally {
      85           2 :       _filter = filter;
      86             :     }
      87             :   }
      88             : 
      89           2 :   Future<List> _getElementsFromRepository(F filter) {
      90             :     if (filter != null) {
      91           2 :       return _repository.getBy(filter);
      92             :     } else {
      93           4 :       return _repository.getAll();
      94             :     }
      95             :   }
      96             : }

Generated by: LCOV version 1.14