import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/models/metadata/metadata.dart'; // ignore: implementation_imports import 'package:riverpod/src/async_notifier.dart'; import 'package:spotube/provider/metadata_plugin/utils/common.dart'; mixin PaginatedAsyncNotifierMixin // ignore: invalid_use_of_internal_member on AsyncNotifierBase> { 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 as List, ...newState.items as List, ]) as SpotubePaginationResponseObject; }, ); } Future> fetchAll() async { if (state.value == null) return []; if (!state.value!.hasMore) return state.value!.items as List; 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 as List, ...newState.items as List, ]) as SpotubePaginationResponseObject; }); } return state.value!.items as List; } } abstract class PaginatedAsyncNotifier extends AsyncNotifier> with PaginatedAsyncNotifierMixin, MetadataPluginMixin {} abstract class AutoDisposePaginatedAsyncNotifier extends AutoDisposeAsyncNotifier> with PaginatedAsyncNotifierMixin, MetadataPluginMixin {}