LCOV - code coverage report
Current view: top level - list/paged - paged_list_filter_bloc.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 34 36 94.4 %
Date: 2020-03-25 12:10:52 Functions: 0 0 -

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

Generated by: LCOV version 1.14