Line data Source code
1 : part of 'paginated_list.dart'; 2 : 3 : /// PaginatedList binder extensions 4 : extension PaginatedListBinder<T> on Stream<Result<PaginatedList<T>>> { 5 : /// Convenience method that maps the data from the paginated list to a stream, 6 : /// handling error, loading and success states 7 1 : Stream<PaginatedList<T>> mergeWithPaginatedList( 8 : BehaviorSubject<PaginatedList<T>> paginatedList, 9 : ) => 10 2 : map<PaginatedList<T>>((result) { 11 : // Get the current paginated list data 12 1 : final subjectValue = paginatedList.hasValue 13 1 : ? paginatedList.value 14 1 : : PaginatedList<T>( 15 1 : list: [], 16 : pageSize: 0, 17 : isLoading: false, 18 : ); 19 : 20 : // If the data is still being fetched/loading, respond with isLoading as true 21 1 : if (result is ResultLoading<PaginatedList<T>>) { 22 2 : if (subjectValue._backupList.isNotEmpty) { 23 1 : return subjectValue.copyWith( 24 : isLoading: true, 25 1 : list: subjectValue._backupList, 26 : ); 27 : } 28 : 29 1 : return subjectValue.copyWith( 30 : isLoading: true, 31 : isInitialized: false, 32 : ); 33 : } 34 : 35 : // If an error occurred, pass this error down and mark loading as false 36 1 : if (result is ResultError<PaginatedList<T>>) { 37 2 : subjectValue._backupList.clear(); 38 1 : return subjectValue.copyWith( 39 : isLoading: false, 40 : isInitialized: false, 41 1 : error: result.error, 42 1 : list: [], 43 : ); 44 : } 45 : 46 : // If we got the resulting data successfully, merge and return it 47 1 : if (result is ResultSuccess<PaginatedList<T>>) { 48 : // Have we previously reset data. If yes clear the temporary data 49 2 : final isReset = subjectValue._backupList.isNotEmpty; 50 : final listData = isReset 51 3 : ? <T>[...result.data.list] 52 1 : : <T>[ 53 1 : ...subjectValue.list, 54 2 : ...result.data.list, 55 : ]; 56 : if (isReset) { 57 1 : subjectValue.length = 0; 58 2 : subjectValue._backupList.clear(); 59 : } 60 : 61 1 : return subjectValue.copyWith( 62 2 : totalCount: result.data.totalCount, 63 2 : pageSize: result.data.pageSize, 64 : list: listData, 65 : isLoading: false, 66 : isInitialized: true, 67 : ); 68 : } 69 : 70 : return subjectValue; 71 1 : }).distinct(); 72 : } 73 : 74 : /// PaginatedList stream extensions 75 : extension PaginatedListStreamExtensions<T> on Stream<PaginatedList<T>> { 76 : /// Awaited value of this method will return once the data has been loaded or 77 : /// refreshed. 78 1 : Future<void> waitToLoad() async { 79 4 : await firstWhere((list) => list.isLoading); 80 4 : await firstWhere((list) => !list.isLoading); 81 : } 82 : } 83 : 84 : /// PaginatedList snapshot extensions 85 : extension PaginatedListSnapshotExt<T> on AsyncSnapshot<PaginatedList<T>> { 86 : /// Is this the initial loading of the snapshot data 87 5 : bool get isInitialLoading => !hasData || (hasData && data!.isInitialLoading); 88 : 89 : /// Is the next page loading 90 1 : bool get isNextPageLoading => 91 4 : !hasData || (hasData && data!.isNextPageLoading); 92 : 93 : /// Is the data loading 94 5 : bool get isLoading => !hasData || (hasData && data!.isLoading); 95 : 96 : /// Is the [data] an [error] 97 4 : bool get hasPageError => hasData && data!.error != null; 98 : 99 : /// Returns the element of the snapshot or null (if element outside range), 100 : /// assuming the snapshot data exists. 101 3 : T? getItem(int index) => data!.getItem(index); 102 : 103 : /// Returns the number of items from the snapshot, assuming the data exists. 104 3 : int get itemCount => data!.itemCount; 105 : 106 : /// Returns the current page number, assuming the data exists. 107 3 : int get pageNumber => data!.pageNumber; 108 : }