LCOV - code coverage report
Current view: top level - list/paged - paged_list_filter_bloc.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 36 38 94.7 %
Date: 2019-11-04 17:53:55 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:bloc/bloc.dart';
       2             : import 'package:flutter_bloc_patterns/base_list.dart';
       3             : import 'package:flutter_bloc_patterns/paged_filter_list.dart';
       4             : import 'package:flutter_bloc_patterns/src/common/view_state.dart';
       5             : import 'package:flutter_bloc_patterns/src/list/paged/page.dart';
       6             : import 'package:flutter_bloc_patterns/src/list/paged/paged_list.dart';
       7             : import 'package:flutter_bloc_patterns/src/list/paged/paged_list_events.dart';
       8             : import 'package:flutter_bloc_patterns/src/list/paged/paged_list_repository.dart';
       9             : 
      10             : /// A list BLoC with pagination and filtering.
      11             : ///
      12             : /// Designed to collaborate with [ViewStateBuilder] for displaying data.
      13             : ///
      14             : /// Call [loadFirstPage] to fetch first page of data. This is where filter
      15             : /// value can be set and it cannot be changed when loading the next page.
      16             : /// Call [loadNextPage] to fetch next page of data.
      17             : ///
      18             : /// [T] - the type of list elements.
      19             : /// [F] - the type of filter.
      20             : class PagedListFilterBloc<T, F> extends Bloc<PagedListEvent, ViewState> {
      21             :   static const defaultPageSize = 10;
      22             : 
      23             :   final PagedListFilterRepository<T, F> _pagedFilterRepository;
      24             :   F _filter;
      25             : 
      26           2 :   PagedListFilterBloc(PagedListFilterRepository<T, F> pagedListFilterRepository)
      27           0 :       : assert(pagedListFilterRepository != null),
      28             :         this._pagedFilterRepository = pagedListFilterRepository;
      29             : 
      30           2 :   @override
      31           2 :   ViewState get initialState => Initial();
      32             : 
      33           2 :   List<T> get _currentElements =>
      34          12 :       (state is Success) ? (state as Success).data.elements : [];
      35             : 
      36             :   Page _page;
      37             : 
      38           0 :   F get filter => _filter;
      39             : 
      40             :   /// Loads elements using the given [filter] and [pageSize]. When no size
      41             :   /// is given [_defaultPageSize] is used.
      42             :   ///
      43             :   /// It's most suitable for initial data fetch or for retry action when
      44             :   /// the first fetch fails.
      45           2 :   void loadFirstPage({int pageSize = defaultPageSize, F filter}) {
      46           4 :     _page = Page.first(size: pageSize);
      47           2 :     _filter = filter;
      48           8 :     add(LoadPage(_page, filter: _filter));
      49             :   }
      50             : 
      51             :   /// Loads next page. When no page has been loaded before the first one is
      52             :   /// loaded with the default page size [_defaultPageSize].
      53           2 :   void loadNextPage() {
      54           6 :     _page = _page?.next() ?? Page.first(size: defaultPageSize);
      55           8 :     add(LoadPage(_page, filter: _filter));
      56             :   }
      57             : 
      58             :   @override
      59           2 :   Stream<ViewState> mapEventToState(PagedListEvent event) async* {
      60           2 :     if (event is LoadPage) {
      61           8 :       yield* _mapLoadPage(event.page, event.filter);
      62             :     }
      63             :   }
      64             : 
      65           2 :   Stream<ViewState> _mapLoadPage(Page page, F filter) async* {
      66             :     try {
      67           4 :       yield* _emitLoadingWhenFirstPage(page);
      68             :       final List<T> pageElements =
      69           6 :           await _pagedFilterRepository.getBy(page, filter);
      70           4 :       yield* (pageElements.isEmpty)
      71           2 :           ? _emitEmptyPageLoaded(page)
      72           2 :           : _emitNextPageLoaded(page, pageElements);
      73           2 :     } on PageNotFoundException catch (_) {
      74           4 :       yield* _emitEmptyPageLoaded(page);
      75             :     } catch (e) {
      76           4 :       yield Failure(e);
      77             :     }
      78             :   }
      79             : 
      80           2 :   Stream<ViewState> _emitLoadingWhenFirstPage(Page page) async* {
      81           2 :     if (page.isFirst) {
      82           4 :       yield Loading();
      83             :     }
      84             :   }
      85             : 
      86           2 :   Stream<ViewState> _emitEmptyPageLoaded(Page page) async* {
      87           4 :     yield (_isFirst(page))
      88           2 :         ? Empty()
      89           3 :         : Success(PagedList<T>(_currentElements, hasReachedMax: true));
      90             :   }
      91             : 
      92           6 :   bool _isFirst(Page page) => page.number == 0;
      93             : 
      94           2 :   Stream<ViewState> _emitNextPageLoaded(
      95             :     Page page,
      96             :     List<T> pageElements,
      97             :   ) async* {
      98           4 :     final List<T> allElements = _currentElements + pageElements;
      99           4 :     yield Success(
     100           8 :       PagedList<T>(allElements, hasReachedMax: pageElements.length < page.size),
     101             :     );
     102             :   }
     103             : }

Generated by: LCOV version 1.14