fix: glitching when loading

This commit is contained in:
Kingkor Roy Tirtho 2024-03-19 21:33:25 +06:00
parent aea4bd7d16
commit 3081237999
9 changed files with 25 additions and 18 deletions

View File

@ -13,10 +13,10 @@ class HomeFeaturedSection extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final featuredPlaylists = ref.watch(featuredPlaylistsProvider); final featuredPlaylists = ref.watch(featuredPlaylistsProvider);
final featuredPlaylistsNotifier = final featuredPlaylistsNotifier =
ref.read(featuredPlaylistsProvider.notifier); ref.watch(featuredPlaylistsProvider.notifier);
return Skeletonizer( return Skeletonizer(
enabled: featuredPlaylists.isLoadingAndEmpty, enabled: featuredPlaylists.isLoading,
child: HorizontalPlaybuttonCardView<PlaylistSimple>( child: HorizontalPlaybuttonCardView<PlaylistSimple>(
items: featuredPlaylists.asData?.value.items ?? [], items: featuredPlaylists.asData?.value.items ?? [],
title: Text(context.l10n.featured), title: Text(context.l10n.featured),

View File

@ -80,7 +80,7 @@ class UserAlbums extends HookConsumerWidget {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
controller: controller, controller: controller,
child: Skeletonizer( child: Skeletonizer(
enabled: albumsQuery.isLoadingAndEmpty, enabled: albumsQuery.isLoading,
child: Center( child: Center(
child: Wrap( child: Wrap(
runSpacing: 20, runSpacing: 20,

View File

@ -84,11 +84,11 @@ class HorizontalPlaybuttonCardView<T> extends HookWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = items[index]; final item = items[index];
return switch (item.runtimeType) { return switch (item) {
PlaylistSimple => PlaylistSimple() =>
PlaylistCard(item as PlaylistSimple), PlaylistCard(item as PlaylistSimple),
Album => AlbumCard(item as Album), Album() => AlbumCard(item as Album),
Artist => Padding( Artist() => Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 12.0), horizontal: 12.0),
child: ArtistCard(item as Artist), child: ArtistCard(item as Artist),

View File

@ -33,7 +33,7 @@ class AlbumPage extends HookConsumerWidget {
tracks: tracks.asData?.value.items ?? [], tracks: tracks.asData?.value.items ?? [],
pagination: PaginationProps( pagination: PaginationProps(
hasNextPage: tracks.asData?.value.hasMore ?? false, hasNextPage: tracks.asData?.value.hasMore ?? false,
isLoading: tracks.isLoading, isLoading: tracks.isLoadingNextPage,
onFetchMore: () async { onFetchMore: () async {
await tracksNotifier.fetchMore(); await tracksNotifier.fetchMore();
}, },

View File

@ -39,7 +39,7 @@ class ArtistPage extends HookConsumerWidget {
return Center(child: Text(artistQuery.error.toString())); return Center(child: Text(artistQuery.error.toString()));
} }
return Skeletonizer( return Skeletonizer(
enabled: artistQuery.isLoadingAndEmpty, enabled: artistQuery.isLoading,
child: CustomScrollView( child: CustomScrollView(
controller: scrollController, controller: scrollController,
slivers: [ slivers: [

View File

@ -36,7 +36,7 @@ class PlaylistPage extends HookConsumerWidget {
), ),
pagination: PaginationProps( pagination: PaginationProps(
hasNextPage: tracks.asData?.value.hasMore ?? false, hasNextPage: tracks.asData?.value.hasMore ?? false,
isLoading: tracks.isLoading, isLoading: tracks.isLoadingNextPage,
onFetchMore: tracksNotifier.fetchMore, onFetchMore: tracksNotifier.fetchMore,
onRefresh: () async { onRefresh: () async {
ref.invalidate(playlistTracksProvider(playlist.id!)); ref.invalidate(playlistTracksProvider(playlist.id!));

View File

@ -37,7 +37,7 @@ class SearchTracksSection extends HookConsumerWidget {
style: theme.textTheme.titleLarge!, style: theme.textTheme.titleLarge!,
), ),
), ),
if (searchTrack.isLoadingAndEmpty) if (searchTrack.isLoading)
const CircularProgressIndicator() const CircularProgressIndicator()
else if (searchTrack.hasError) else if (searchTrack.hasError)
Text(searchTrack.error.toString()) Text(searchTrack.error.toString())

View File

@ -1,6 +1,5 @@
part of '../spotify.dart'; part of '../spotify.dart';
extension PaginationExtension<T> on AsyncValue<T> { extension PaginationExtension<T> on AsyncValue<T> {
bool get isLoadingAndEmpty => value == null && isLoading; bool get isLoadingNextPage => this is AsyncData && this is AsyncLoadingNext;
bool get isLoadingNextPage => value != null && isLoading;
} }

View File

@ -1,17 +1,25 @@
part of '../spotify.dart'; part of '../spotify.dart';
// ignore: subtype_of_sealed_class
class AsyncLoadingNext<T> extends AsyncData<T> {
const AsyncLoadingNext(super.value);
}
abstract class PaginatedAsyncNotifier<K, T extends BasePaginatedState<K, int>> abstract class PaginatedAsyncNotifier<K, T extends BasePaginatedState<K, int>>
extends AsyncNotifier<T> with SpotifyMixin<T> { extends AsyncNotifier<T> with SpotifyMixin<T> {
Future<List<K>> fetch(int offset, int limit); Future<List<K>> fetch(int offset, int limit);
Future<void> fetchMore() async { Future<void> fetchMore() async {
if (state.value == null || !state.value!.hasMore) return; if (state.value == null || !state.value!.hasMore) return;
state = const AsyncValue.loading();
state = AsyncLoadingNext(state.asData!.value);
state = await AsyncValue.guard( state = await AsyncValue.guard(
() async { () async {
final items = await fetch( final items = await fetch(
state.value!.offset + state.value!.limit, state.value!.limit); state.value!.offset + state.value!.limit,
state.value!.limit,
);
return state.value!.copyWith( return state.value!.copyWith(
hasMore: items.length == state.value!.limit, hasMore: items.length == state.value!.limit,
items: [ items: [
@ -57,7 +65,7 @@ abstract class CursorPaginatedAsyncNotifier<K,
Future<void> fetchMore() async { Future<void> fetchMore() async {
if (state.value == null || !state.value!.hasMore) return; if (state.value == null || !state.value!.hasMore) return;
state = const AsyncValue.loading(); state = AsyncLoadingNext(state.asData!.value);
state = await AsyncValue.guard( state = await AsyncValue.guard(
() async { () async {
@ -105,7 +113,7 @@ abstract class FamilyPaginatedAsyncNotifier<
Future<void> fetchMore() async { Future<void> fetchMore() async {
if (state.value == null || !state.value!.hasMore) return; if (state.value == null || !state.value!.hasMore) return;
state = const AsyncLoading(); state = AsyncLoadingNext(state.asData!.value);
state = await AsyncValue.guard( state = await AsyncValue.guard(
() async { () async {
@ -165,7 +173,7 @@ abstract class FamilyCursorPaginatedAsyncNotifier<
Future<void> fetchMore() async { Future<void> fetchMore() async {
if (state.value == null || !state.value!.hasMore) return; if (state.value == null || !state.value!.hasMore) return;
state = const AsyncLoading(); state = AsyncLoadingNext(state.asData!.value);
state = await AsyncValue.guard( state = await AsyncValue.guard(
() async { () async {