mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Squashed commit of the following:
commit e160d4f561ff2e945fd67bf12b223c012da58b1e Author: Kingkor Roy Tirtho <krtirtho@gmail.com> Date: Sat Sep 14 10:48:08 2024 +0600 fix: pagination issues in playlist and album pages
This commit is contained in:
parent
40bfcc1961
commit
3afe3cea80
@ -65,6 +65,56 @@ class TrackViewBodySection extends HookConsumerWidget {
|
|||||||
|
|
||||||
final isActive = playlist.collections.contains(props.collectionId);
|
final isActive = playlist.collections.contains(props.collectionId);
|
||||||
|
|
||||||
|
final onTapTrackTile = useCallback((Track track, int index) async {
|
||||||
|
if (trackViewState.isSelecting) {
|
||||||
|
trackViewState.toggleTrackSelection(track.id!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final isRemoteDevice = await showSelectDeviceDialog(context, ref);
|
||||||
|
|
||||||
|
if (isRemoteDevice) {
|
||||||
|
final remotePlayback = ref.read(connectProvider.notifier);
|
||||||
|
final remoteQueue = ref.read(queueProvider);
|
||||||
|
if (remoteQueue.collections.contains(props.collectionId) ||
|
||||||
|
remoteQueue.tracks.any((s) => s.id == track.id)) {
|
||||||
|
await playlistNotifier.jumpToTrack(track);
|
||||||
|
} else {
|
||||||
|
final tracks = await props.pagination.onFetchAll();
|
||||||
|
await remotePlayback.load(
|
||||||
|
props.collection is AlbumSimple
|
||||||
|
? WebSocketLoadEventData.album(
|
||||||
|
tracks: tracks,
|
||||||
|
collection: props.collection as AlbumSimple,
|
||||||
|
initialIndex: index,
|
||||||
|
)
|
||||||
|
: WebSocketLoadEventData.playlist(
|
||||||
|
tracks: tracks,
|
||||||
|
collection: props.collection as PlaylistSimple,
|
||||||
|
initialIndex: index,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isActive || playlist.tracks.contains(track)) {
|
||||||
|
await playlistNotifier.jumpToTrack(track);
|
||||||
|
} else {
|
||||||
|
final tracks = await props.pagination.onFetchAll();
|
||||||
|
await playlistNotifier.load(
|
||||||
|
tracks,
|
||||||
|
initialIndex: index,
|
||||||
|
autoPlay: true,
|
||||||
|
);
|
||||||
|
playlistNotifier.addCollection(props.collectionId);
|
||||||
|
if (props.collection is AlbumSimple) {
|
||||||
|
historyNotifier.addAlbums([props.collection as AlbumSimple]);
|
||||||
|
} else {
|
||||||
|
historyNotifier.addPlaylists([props.collection as PlaylistSimple]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [isActive, playlist, props, playlistNotifier, historyNotifier]);
|
||||||
|
|
||||||
return SliverMainAxisGroup(
|
return SliverMainAxisGroup(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
@ -130,58 +180,7 @@ class TrackViewBodySection extends HookConsumerWidget {
|
|||||||
trackViewState.selectTrack(track.id!);
|
trackViewState.selectTrack(track.id!);
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
},
|
},
|
||||||
onTap: () async {
|
onTap: () => onTapTrackTile(track, index),
|
||||||
if (trackViewState.isSelecting) {
|
|
||||||
trackViewState.toggleTrackSelection(track.id!);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final isRemoteDevice =
|
|
||||||
await showSelectDeviceDialog(context, ref);
|
|
||||||
|
|
||||||
if (isRemoteDevice) {
|
|
||||||
final remotePlayback = ref.read(connectProvider.notifier);
|
|
||||||
final remoteQueue = ref.read(queueProvider);
|
|
||||||
if (remoteQueue.collections.contains(props.collectionId) ||
|
|
||||||
remoteQueue.tracks.any((s) => s.id == track.id)) {
|
|
||||||
await playlistNotifier.jumpToTrack(track);
|
|
||||||
} else {
|
|
||||||
final tracks = await props.pagination.onFetchAll();
|
|
||||||
await remotePlayback.load(
|
|
||||||
props.collection is AlbumSimple
|
|
||||||
? WebSocketLoadEventData.album(
|
|
||||||
tracks: tracks,
|
|
||||||
collection: props.collection as AlbumSimple,
|
|
||||||
initialIndex: index,
|
|
||||||
)
|
|
||||||
: WebSocketLoadEventData.playlist(
|
|
||||||
tracks: tracks,
|
|
||||||
collection: props.collection as PlaylistSimple,
|
|
||||||
initialIndex: index,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isActive || playlist.tracks.contains(track)) {
|
|
||||||
await playlistNotifier.jumpToTrack(track);
|
|
||||||
} else {
|
|
||||||
final tracks = await props.pagination.onFetchAll();
|
|
||||||
await playlistNotifier.load(
|
|
||||||
tracks,
|
|
||||||
initialIndex: index,
|
|
||||||
autoPlay: true,
|
|
||||||
);
|
|
||||||
playlistNotifier.addCollection(props.collectionId);
|
|
||||||
if (props.collection is AlbumSimple) {
|
|
||||||
historyNotifier
|
|
||||||
.addAlbums([props.collection as AlbumSimple]);
|
|
||||||
} else {
|
|
||||||
historyNotifier
|
|
||||||
.addPlaylists([props.collection as PlaylistSimple]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -90,12 +90,18 @@ class HistoryTopAlbumsNotifier extends FamilyPaginatedAsyncNotifier<
|
|||||||
fetch(arg, offset, limit) async {
|
fetch(arg, offset, limit) async {
|
||||||
final albumsQuery = createAlbumsQuery(limit: limit, offset: offset);
|
final albumsQuery = createAlbumsQuery(limit: limit, offset: offset);
|
||||||
|
|
||||||
return getAlbumsWithCount(await albumsQuery.get());
|
final items = getAlbumsWithCount(await albumsQuery.get());
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: items.length == limit,
|
||||||
|
nextOffset: offset + limit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
build(arg) async {
|
build(arg) async {
|
||||||
final albums = await fetch(arg, 0, 20);
|
final (items: albums, :hasMore, :nextOffset) = await fetch(arg, 0, 20);
|
||||||
|
|
||||||
final subscription = createAlbumsQuery().watch().listen((event) {
|
final subscription = createAlbumsQuery().watch().listen((event) {
|
||||||
if (state.asData == null) return;
|
if (state.asData == null) return;
|
||||||
@ -111,9 +117,9 @@ class HistoryTopAlbumsNotifier extends FamilyPaginatedAsyncNotifier<
|
|||||||
|
|
||||||
return HistoryTopAlbumsState(
|
return HistoryTopAlbumsState(
|
||||||
items: albums,
|
items: albums,
|
||||||
offset: albums.length,
|
offset: nextOffset,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
hasMore: true,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,12 +55,18 @@ class HistoryTopPlaylistsNotifier extends FamilyPaginatedAsyncNotifier<
|
|||||||
fetch(arg, offset, limit) async {
|
fetch(arg, offset, limit) async {
|
||||||
final playlistsQuery = createPlaylistsQuery()..limit(limit, offset: offset);
|
final playlistsQuery = createPlaylistsQuery()..limit(limit, offset: offset);
|
||||||
|
|
||||||
return getPlaylistsWithCount(await playlistsQuery.get());
|
final items = getPlaylistsWithCount(await playlistsQuery.get());
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: items.length == limit,
|
||||||
|
nextOffset: offset + limit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
build(arg) async {
|
build(arg) async {
|
||||||
final playlists = await fetch(arg, 0, 20);
|
final (items: playlists, :hasMore, :nextOffset) = await fetch(arg, 0, 20);
|
||||||
|
|
||||||
final subscription = createPlaylistsQuery().watch().listen((event) {
|
final subscription = createPlaylistsQuery().watch().listen((event) {
|
||||||
if (state.asData == null) return;
|
if (state.asData == null) return;
|
||||||
@ -76,9 +82,9 @@ class HistoryTopPlaylistsNotifier extends FamilyPaginatedAsyncNotifier<
|
|||||||
|
|
||||||
return HistoryTopPlaylistsState(
|
return HistoryTopPlaylistsState(
|
||||||
items: playlists,
|
items: playlists,
|
||||||
offset: playlists.length,
|
offset: nextOffset,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
hasMore: true,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +89,18 @@ class HistoryTopTracksNotifier extends FamilyPaginatedAsyncNotifier<
|
|||||||
fetch(arg, offset, limit) async {
|
fetch(arg, offset, limit) async {
|
||||||
final tracksQuery = createTracksQuery()..limit(limit, offset: offset);
|
final tracksQuery = createTracksQuery()..limit(limit, offset: offset);
|
||||||
|
|
||||||
return getTracksWithCount(await tracksQuery.get());
|
final items = getTracksWithCount(await tracksQuery.get());
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: items.length == limit,
|
||||||
|
nextOffset: offset + limit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
build(arg) async {
|
build(arg) async {
|
||||||
final tracks = await fetch(arg, 0, 20);
|
final (items: tracks, :hasMore, :nextOffset) = await fetch(arg, 0, 20);
|
||||||
|
|
||||||
final subscription = createTracksQuery().watch().listen((event) {
|
final subscription = createTracksQuery().watch().listen((event) {
|
||||||
if (state.asData == null) return;
|
if (state.asData == null) return;
|
||||||
@ -110,9 +116,9 @@ class HistoryTopTracksNotifier extends FamilyPaginatedAsyncNotifier<
|
|||||||
|
|
||||||
return HistoryTopTracksState(
|
return HistoryTopTracksState(
|
||||||
items: tracks,
|
items: tracks,
|
||||||
offset: tracks.length,
|
offset: nextOffset,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
hasMore: true,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,13 @@ class AlbumTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<Track,
|
|||||||
@override
|
@override
|
||||||
fetch(arg, offset, limit) async {
|
fetch(arg, offset, limit) async {
|
||||||
final tracks = await spotify.albums.tracks(arg.id!).getPage(limit, offset);
|
final tracks = await spotify.albums.tracks(arg.id!).getPage(limit, offset);
|
||||||
return tracks.items?.map((e) => e.asTrack(arg)).toList() ?? [];
|
final items = tracks.items?.map((e) => e.asTrack(arg)).toList() ?? [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: !tracks.isLast,
|
||||||
|
nextOffset: tracks.nextOffset,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,12 +45,12 @@ class AlbumTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<Track,
|
|||||||
ref.cacheFor();
|
ref.cacheFor();
|
||||||
|
|
||||||
ref.watch(spotifyProvider);
|
ref.watch(spotifyProvider);
|
||||||
final tracks = await fetch(arg, 0, 20);
|
final (:items, :nextOffset, :hasMore) = await fetch(arg, 0, 20);
|
||||||
return AlbumTracksState(
|
return AlbumTracksState(
|
||||||
items: tracks,
|
items: items,
|
||||||
offset: 0,
|
offset: nextOffset,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
hasMore: tracks.length == 20,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,13 @@ class ArtistAlbumsNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
.albums(arg, country: market)
|
.albums(arg, country: market)
|
||||||
.getPage(limit, offset);
|
.getPage(limit, offset);
|
||||||
|
|
||||||
return albums.items?.toList() ?? [];
|
final items = albums.items?.toList() ?? [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: !albums.isLast,
|
||||||
|
nextOffset: albums.nextOffset,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -46,12 +52,12 @@ class ArtistAlbumsNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
ref.watch(
|
ref.watch(
|
||||||
userPreferencesProvider.select((s) => s.market),
|
userPreferencesProvider.select((s) => s.market),
|
||||||
);
|
);
|
||||||
final albums = await fetch(arg, 0, 20);
|
final (:items, :hasMore, :nextOffset) = await fetch(arg, 0, 20);
|
||||||
return ArtistAlbumsState(
|
return ArtistAlbumsState(
|
||||||
items: albums,
|
items: items,
|
||||||
offset: 0,
|
offset: nextOffset,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
hasMore: albums.length == 20,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,13 @@ class CategoryPlaylistsNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
(json) => PlaylistsFeatured.fromJson(json),
|
(json) => PlaylistsFeatured.fromJson(json),
|
||||||
).getPage(limit, offset);
|
).getPage(limit, offset);
|
||||||
|
|
||||||
return playlists.items?.whereNotNull().toList() ?? [];
|
final items = playlists.items?.whereNotNull().toList() ?? [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: !playlists.isLast,
|
||||||
|
nextOffset: playlists.nextOffset,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -50,13 +56,13 @@ class CategoryPlaylistsNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
ref.watch(userPreferencesProvider.select((s) => s.locale));
|
ref.watch(userPreferencesProvider.select((s) => s.locale));
|
||||||
ref.watch(userPreferencesProvider.select((s) => s.market));
|
ref.watch(userPreferencesProvider.select((s) => s.market));
|
||||||
|
|
||||||
final playlists = await fetch(arg, 0, 8);
|
final (:items, :hasMore, :nextOffset) = await fetch(arg, 0, 8);
|
||||||
|
|
||||||
return CategoryPlaylistsState(
|
return CategoryPlaylistsState(
|
||||||
items: playlists,
|
items: items,
|
||||||
offset: 0,
|
offset: nextOffset,
|
||||||
limit: 8,
|
limit: 8,
|
||||||
hasMore: playlists.length == 8,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,16 @@ class PlaylistTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
|
|
||||||
/// Filter out tracks with null id because some personal playlists
|
/// Filter out tracks with null id because some personal playlists
|
||||||
/// may contain local tracks that are not available in the Spotify catalog
|
/// may contain local tracks that are not available in the Spotify catalog
|
||||||
return tracks.items
|
final items = tracks.items
|
||||||
?.where((track) => track.id != null && track.type == "track")
|
?.where((track) => track.id != null && track.type == "track")
|
||||||
.toList() ??
|
.toList() ??
|
||||||
<Track>[];
|
<Track>[];
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: !tracks.isLast,
|
||||||
|
nextOffset: tracks.nextOffset,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -47,13 +53,13 @@ class PlaylistTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
ref.cacheFor();
|
ref.cacheFor();
|
||||||
|
|
||||||
ref.watch(spotifyProvider);
|
ref.watch(spotifyProvider);
|
||||||
final tracks = await fetch(arg, 0, 20);
|
final (items: tracks, :hasMore, :nextOffset) = await fetch(arg, 0, 20);
|
||||||
|
|
||||||
return PlaylistTracksState(
|
return PlaylistTracksState(
|
||||||
items: tracks,
|
items: tracks,
|
||||||
offset: 0,
|
offset: nextOffset,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
hasMore: tracks.length == 20,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,13 @@ class SearchNotifier<Y> extends AutoDisposeFamilyPaginatedAsyncNotifier<Y,
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
fetch(arg, offset, limit) async {
|
fetch(arg, offset, limit) async {
|
||||||
if (state.value == null) return [];
|
if (state.value == null) {
|
||||||
|
return (
|
||||||
|
items: <Y>[],
|
||||||
|
hasMore: false,
|
||||||
|
nextOffset: 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
final results = await spotify.search
|
final results = await spotify.search
|
||||||
.get(
|
.get(
|
||||||
ref.read(searchTermStateProvider),
|
ref.read(searchTermStateProvider),
|
||||||
@ -46,7 +52,13 @@ class SearchNotifier<Y> extends AutoDisposeFamilyPaginatedAsyncNotifier<Y,
|
|||||||
)
|
)
|
||||||
.getPage(limit, offset);
|
.getPage(limit, offset);
|
||||||
|
|
||||||
return results.expand((e) => e.items ?? <Y>[]).toList().cast<Y>();
|
final items = results.expand((e) => e.items ?? <Y>[]).toList().cast<Y>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
items: items,
|
||||||
|
hasMore: items.length == limit,
|
||||||
|
nextOffset: offset + limit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -59,13 +71,13 @@ class SearchNotifier<Y> extends AutoDisposeFamilyPaginatedAsyncNotifier<Y,
|
|||||||
userPreferencesProvider.select((value) => value.market),
|
userPreferencesProvider.select((value) => value.market),
|
||||||
);
|
);
|
||||||
|
|
||||||
final results = await fetch(arg, 0, 10);
|
final (:items, :hasMore, :nextOffset) = await fetch(arg, 0, 10);
|
||||||
|
|
||||||
return SearchState<Y>(
|
return SearchState<Y>(
|
||||||
items: results,
|
items: items,
|
||||||
offset: 0,
|
offset: nextOffset,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
hasMore: results.length == 10,
|
hasMore: hasMore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
part of '../../spotify.dart';
|
part of '../../spotify.dart';
|
||||||
|
|
||||||
|
typedef PseudoPaginatedProps<T> = ({
|
||||||
|
List<T> items,
|
||||||
|
int nextOffset,
|
||||||
|
bool hasMore,
|
||||||
|
});
|
||||||
|
|
||||||
abstract class FamilyPaginatedAsyncNotifier<
|
abstract class FamilyPaginatedAsyncNotifier<
|
||||||
K,
|
K,
|
||||||
T extends BasePaginatedState<K, dynamic>,
|
T extends BasePaginatedState<K, dynamic>,
|
||||||
A> extends FamilyAsyncNotifier<T, A> with SpotifyMixin<T> {
|
A> extends FamilyAsyncNotifier<T, A> with SpotifyMixin<T> {
|
||||||
Future<List<K>> fetch(A arg, int offset, int limit);
|
Future<PseudoPaginatedProps<K>> fetch(A arg, 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;
|
||||||
@ -13,18 +19,18 @@ abstract class FamilyPaginatedAsyncNotifier<
|
|||||||
|
|
||||||
state = await AsyncValue.guard(
|
state = await AsyncValue.guard(
|
||||||
() async {
|
() async {
|
||||||
final items = await fetch(
|
final (:items, :hasMore, :nextOffset) = await fetch(
|
||||||
arg,
|
arg,
|
||||||
state.value!.offset + 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: hasMore,
|
||||||
items: [
|
items: [
|
||||||
...state.value!.items,
|
...state.value!.items,
|
||||||
...items,
|
...items,
|
||||||
],
|
],
|
||||||
offset: state.value!.offset + state.value!.limit,
|
offset: nextOffset,
|
||||||
) as T;
|
) as T;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -37,16 +43,16 @@ abstract class FamilyPaginatedAsyncNotifier<
|
|||||||
bool hasMore = true;
|
bool hasMore = true;
|
||||||
while (hasMore) {
|
while (hasMore) {
|
||||||
await update((state) async {
|
await update((state) async {
|
||||||
final items = await fetch(
|
final res = await fetch(
|
||||||
arg,
|
arg,
|
||||||
state.offset + state.limit,
|
state.offset,
|
||||||
state.limit,
|
state.limit,
|
||||||
);
|
);
|
||||||
|
|
||||||
hasMore = items.length == state.limit;
|
hasMore = res.hasMore;
|
||||||
return state.copyWith(
|
return state.copyWith(
|
||||||
items: [...state.items, ...items],
|
items: [...state.items, ...res.items],
|
||||||
offset: state.offset + state.limit,
|
offset: res.nextOffset,
|
||||||
hasMore: hasMore,
|
hasMore: hasMore,
|
||||||
) as T;
|
) as T;
|
||||||
});
|
});
|
||||||
@ -60,7 +66,7 @@ abstract class AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
K,
|
K,
|
||||||
T extends BasePaginatedState<K, dynamic>,
|
T extends BasePaginatedState<K, dynamic>,
|
||||||
A> extends AutoDisposeFamilyAsyncNotifier<T, A> with SpotifyMixin<T> {
|
A> extends AutoDisposeFamilyAsyncNotifier<T, A> with SpotifyMixin<T> {
|
||||||
Future<List<K>> fetch(A arg, int offset, int limit);
|
Future<PseudoPaginatedProps<K>> fetch(A arg, 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;
|
||||||
@ -69,18 +75,19 @@ abstract class AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
|
|
||||||
state = await AsyncValue.guard(
|
state = await AsyncValue.guard(
|
||||||
() async {
|
() async {
|
||||||
final items = await fetch(
|
final (:items, :hasMore, :nextOffset) = await fetch(
|
||||||
arg,
|
arg,
|
||||||
state.value!.offset + 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: hasMore,
|
||||||
items: [
|
items: [
|
||||||
...state.value!.items,
|
...state.value!.items,
|
||||||
...items,
|
...items,
|
||||||
],
|
],
|
||||||
offset: state.value!.offset + state.value!.limit,
|
offset: nextOffset,
|
||||||
) as T;
|
) as T;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -93,16 +100,16 @@ abstract class AutoDisposeFamilyPaginatedAsyncNotifier<
|
|||||||
bool hasMore = true;
|
bool hasMore = true;
|
||||||
while (hasMore) {
|
while (hasMore) {
|
||||||
await update((state) async {
|
await update((state) async {
|
||||||
final items = await fetch(
|
final res = await fetch(
|
||||||
arg,
|
arg,
|
||||||
state.offset + state.limit,
|
state.offset,
|
||||||
state.limit,
|
state.limit,
|
||||||
);
|
);
|
||||||
|
|
||||||
hasMore = items.length == state.limit;
|
hasMore = res.hasMore;
|
||||||
return state.copyWith(
|
return state.copyWith(
|
||||||
items: [...state.items, ...items],
|
items: [...state.items, ...res.items],
|
||||||
offset: state.offset + state.limit,
|
offset: res.nextOffset,
|
||||||
hasMore: hasMore,
|
hasMore: hasMore,
|
||||||
) as T;
|
) as T;
|
||||||
});
|
});
|
||||||
|
@ -758,6 +758,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.20.5"
|
version: "0.20.5"
|
||||||
|
flutter_hooks_lint:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_hooks_lint
|
||||||
|
sha256: fc6e18505b597737e5d620656e340ac60e7a58980cca29e18c1216bd15083674
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
flutter_inappwebview:
|
flutter_inappwebview:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -158,6 +158,7 @@ dev_dependencies:
|
|||||||
xml: ^6.5.0
|
xml: ^6.5.0
|
||||||
io: ^1.0.4
|
io: ^1.0.4
|
||||||
drift_dev: ^2.18.0
|
drift_dev: ^2.18.0
|
||||||
|
flutter_hooks_lint: ^1.2.0
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
uuid: ^4.4.0
|
uuid: ^4.4.0
|
||||||
|
Loading…
Reference in New Issue
Block a user