import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/models/metadata/metadata.dart'; import 'package:spotube/provider/metadata_plugin/utils/common.dart'; abstract class FamilyPaginatedAsyncNotifier extends FamilyAsyncNotifier, A> with MetadataPluginMixin { Future> fetch(int offset, int limit); Future fetchMore() async { if (state.value == null || !state.value!.hasMore) return; state = AsyncLoadingNext(state.asData!.value); state = await AsyncValue.guard( () async { final newState = await fetch( state.value!.nextOffset!, state.value!.limit, ); final oldItems = state.value!.items.isEmpty ? [] : state.value!.items.cast(); final items = newState.items.isEmpty ? [] : newState.items.cast(); return newState.copyWith(items: [...oldItems, ...items]) as SpotubePaginationResponseObject; }, ); } Future> fetchAll() async { if (state.value == null) return []; if (!state.value!.hasMore) return state.value!.items.cast(); bool hasMore = true; while (hasMore) { await update((state) async { final newState = await fetch( state.nextOffset!, state.limit, ); hasMore = newState.hasMore; final oldItems = state.items.isEmpty ? [] : state.items.cast(); final items = newState.items.isEmpty ? [] : newState.items.cast(); return newState.copyWith(items: [...oldItems, ...items]) as SpotubePaginationResponseObject; }); } return state.value!.items.cast(); } } abstract class AutoDisposeFamilyPaginatedAsyncNotifier extends AutoDisposeFamilyAsyncNotifier, A> with MetadataPluginMixin { Future> fetch(int offset, int limit); Future fetchMore() async { if (state.value == null || !state.value!.hasMore) return; state = AsyncLoadingNext(state.asData!.value); state = await AsyncValue.guard( () async { final newState = await fetch( state.value!.nextOffset!, state.value!.limit, ); return newState.copyWith(items: [ ...state.value!.items.cast(), ...newState.items.cast(), ]) as SpotubePaginationResponseObject; }, ); } Future> fetchAll() async { if (state.value == null) return []; if (!state.value!.hasMore) return state.value!.items.cast(); bool hasMore = true; while (hasMore) { await update((state) async { final newState = await fetch( state.nextOffset!, state.limit, ); hasMore = newState.hasMore; return newState.copyWith(items: [ ...state.items.cast(), ...newState.items.cast(), ]) as SpotubePaginationResponseObject; }); } return state.value!.items.cast(); } }