LCOV - code coverage report
Current view: top level - models - paginated_list.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 48 48 100.0 %
Date: 2021-09-21 09:25:57 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:collection';
       3             : 
       4             : import 'package:flutter/cupertino.dart';
       5             : import 'package:rx_bloc/rx_bloc.dart';
       6             : import 'package:rxdart/rxdart.dart';
       7             : 
       8             : part 'paginated_list_extensions.dart';
       9             : 
      10             : /// PaginatedList class is an extension on the list class that allows for easier
      11             : /// data manipulation and work with paginated data.
      12             : ///
      13             : /// The [PaginatedList] class requires a [list] of data and a [pageSize] integer
      14             : /// which will allow the list to be separated into multiple pages.
      15             : ///
      16             : /// If the number of total items is known in advance, it can be specified as the
      17             : /// [totalCount] parameter.
      18             : ///
      19             : /// The [isLoading] parameter represents whether the data is loading or has
      20             : /// loaded. This can be useful when building ui-related refresh states.
      21             : ///
      22             : /// If an error occurs while using the paginated list, it can be stored inside
      23             : /// the [error] parameter. Usually you would store any data fetching or related
      24             : /// errors.
      25             : ///
      26             : /// The number of loaded pages can be accessed any time by referring to the
      27             : /// [pageNumber] value. Please note, that the number of pages is affected by the
      28             : /// actual [length] of the list and the [pageSize].
      29             : ///
      30             : /// Unlike the [length] of the list which is the actual number of items in the
      31             : /// list, the [itemCount] represents the number of items that should be rendered
      32             : /// on screen. The [itemCount] is equal to [length], unless the next page is
      33             : /// loading. Then, the [itemCount] also accounts for the loading widget at the
      34             : /// bottom of the list in case there are more items to be loaded.
      35             : ///
      36             : /// In order to tell whether there is a next page to be loaded, [hasNextPage]
      37             : /// can be used for that case.
      38             : ///
      39             : /// Getters [isInitialLoading] and [isNextPageLoading] reflect the current
      40             : /// loading state of the list. If there is no data and [isLoading] is true, the
      41             : /// getter [isInitialLoading] will return true. Similarly, if [isLoading] is
      42             : /// true and we can load a new page, the getter [isNextPageLoading] will return
      43             : /// true.
      44             : ///
      45             : class PaginatedList<E> extends ListBase<E> {
      46             :   /// PaginatedList constructor
      47           2 :   PaginatedList({
      48             :     required this.list,
      49             :     required this.pageSize,
      50             :     this.error,
      51             :     this.totalCount,
      52             :     this.isLoading = false,
      53             :     bool isInitialized = false,
      54             :   }) : _isInitialized = isInitialized;
      55             : 
      56             :   /// The list containing the actual data.
      57             :   final List<E> list;
      58             : 
      59             :   /// The number of elements per one page.
      60             :   final int pageSize;
      61             : 
      62             :   /// If an exception is thrown, the [error] field will capture it.
      63             :   final Exception? error;
      64             : 
      65             :   /// Optional field containing total number of elements (if known).
      66             :   final int? totalCount;
      67             : 
      68             :   /// Indicates whether the paginated list is loading or not.
      69             :   final bool isLoading;
      70             : 
      71             :   /// Indicates whether the paginated list has been populated with data
      72             :   final bool _isInitialized;
      73             : 
      74             :   /// Temporary list which stores data in between refreshes
      75             :   List<E> _backupList = [];
      76             : 
      77             :   /// Setter for the length of the list.
      78           2 :   @override
      79           4 :   set length(int newLength) => list.length = newLength;
      80             : 
      81             :   /// Returns the actual list length.
      82           2 :   @override
      83           4 :   int get length => list.length;
      84             : 
      85             :   /// Returns the number of items in a list. When loading a new page, the number
      86             :   /// of items is increased by one, which can be used to represent the bottom
      87             :   /// loading widget.
      88           2 :   int get itemCount =>
      89          11 :       hasNextPage && isNextPageLoading ? list.length + 1 : list.length;
      90             : 
      91             :   /// The number of loaded pages.
      92          14 :   int get pageNumber => list.isNotEmpty ? (length / pageSize).ceil() : 0;
      93             : 
      94             :   /// The next page to load
      95           2 :   int get pageToLoad => pageNumber;
      96             : 
      97             :   /// Getter used for telling us whether there is a new page to load.
      98           8 :   bool get hasNextPage => totalCount == null || list.length < totalCount!;
      99             : 
     100             :   /// Getter used for telling us whether this the initial data being loaded.
     101          10 :   bool get isInitialLoading => isLoading && list.isEmpty && !_isInitialized;
     102             : 
     103             :   /// Getter for telling us whether we are loading a new page.
     104           8 :   bool get isNextPageLoading => isLoading && list.isNotEmpty;
     105             : 
     106           2 :   @override
     107           4 :   E operator [](int index) => list[index];
     108             : 
     109           1 :   @override
     110             :   void operator []=(int index, E value) {
     111           2 :     list[index] = value;
     112             :   }
     113             : 
     114             :   /// Returns a modified version of the current PaginatedList
     115           2 :   PaginatedList<E> copyWith({
     116             :     List<E>? list,
     117             :     bool? isLoading,
     118             :     int? totalCount,
     119             :     Exception? error,
     120             :     int? pageSize,
     121             :     bool? isInitialized,
     122             :   }) =>
     123           2 :       PaginatedList(
     124           1 :         list: list ?? this.list,
     125           1 :         isLoading: isLoading ?? this.isLoading,
     126           2 :         totalCount: totalCount ?? this.totalCount,
     127           2 :         pageSize: pageSize ?? this.pageSize,
     128           2 :         isInitialized: isInitialized ?? _isInitialized,
     129             :         error: error,
     130           4 :       ).._backupList = _backupList;
     131             : 
     132             :   /// Returns element at given index. If element outside bound, null is returned
     133          12 :   E? getItem(int index) => (index >= length || index < 0) ? null : list[index];
     134             : 
     135             :   /// Resets the list data
     136           2 :   void reset({bool hard = false}) {
     137           4 :     _backupList.clear();
     138             : 
     139           2 :     if (hard == false) {
     140           6 :       _backupList.addAll(list);
     141             :     }
     142             : 
     143           2 :     length = 0;
     144             :   }
     145             : 
     146           1 :   @override
     147             :   operator ==(other) =>
     148           1 :       other is PaginatedList<E> &&
     149           3 :       other.pageSize == pageSize &&
     150           3 :       other.error == error &&
     151           3 :       other.totalCount == totalCount &&
     152           3 :       other.isLoading == isLoading &&
     153           3 :       other.list == list;
     154             : 
     155           1 :   @override
     156             :   int get hashCode =>
     157           3 :       pageSize.hashCode ^
     158           3 :       error.hashCode ^
     159           3 :       totalCount.hashCode ^
     160           3 :       isLoading.hashCode ^
     161           3 :       _isInitialized.hashCode ^
     162           2 :       list.hashCode;
     163             : 
     164           1 :   @override
     165           1 :   String toString() =>
     166           3 :       '{pageSize: $pageSize, error: $error, totalCount: $totalCount, '
     167           2 :       'isLoading: $isLoading, list: $list}';
     168             : }

Generated by: LCOV version 1.15