mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
feat: newly released albums of user followed artist
This commit is contained in:
parent
38929fed6e
commit
33cb7947d6
@ -4,10 +4,8 @@ import 'package:collection/collection.dart';
|
||||
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart';
|
||||
import 'package:spotube/components/shared/waypoint.dart';
|
||||
import 'package:spotube/components/artist/artist_card.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
@ -22,17 +20,12 @@ class UserArtists extends HookConsumerWidget {
|
||||
final theme = Theme.of(context);
|
||||
final auth = ref.watch(AuthenticationNotifier.provider);
|
||||
|
||||
final artistQuery = useQueries.artist.followedByMe(ref);
|
||||
|
||||
final hasNextPage = artistQuery.pages.isEmpty
|
||||
? false
|
||||
: (artistQuery.pages.last.items?.length ?? 0) == 15;
|
||||
final artistQuery = useQueries.artist.followedByMeAll(ref);
|
||||
|
||||
final searchText = useState('');
|
||||
|
||||
final filteredArtists = useMemoized(() {
|
||||
final artists = artistQuery.pages
|
||||
.expand<Artist>((page) => page.items ?? const Iterable.empty());
|
||||
final artists = artistQuery.data ?? [];
|
||||
|
||||
if (searchText.value.isEmpty) {
|
||||
return artists.toList();
|
||||
@ -46,7 +39,7 @@ class UserArtists extends HookConsumerWidget {
|
||||
.where((e) => e.item1 > 50)
|
||||
.map((e) => e.item2)
|
||||
.toList();
|
||||
}, [artistQuery.pages, searchText.value]);
|
||||
}, [artistQuery.data, searchText.value]);
|
||||
|
||||
final controller = useScrollController();
|
||||
|
||||
@ -72,7 +65,7 @@ class UserArtists extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
body: artistQuery.pages.isEmpty
|
||||
body: artistQuery.data?.isEmpty == true
|
||||
? Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
@ -86,7 +79,7 @@ class UserArtists extends HookConsumerWidget {
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await artistQuery.refreshAll();
|
||||
await artistQuery.refresh();
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
controller: controller,
|
||||
@ -97,18 +90,9 @@ class UserArtists extends HookConsumerWidget {
|
||||
child: Wrap(
|
||||
spacing: 15,
|
||||
runSpacing: 5,
|
||||
children: filteredArtists.mapIndexed((index, artist) {
|
||||
if (index == artistQuery.pages.length - 1 &&
|
||||
hasNextPage) {
|
||||
return Waypoint(
|
||||
controller: controller,
|
||||
isGrid: true,
|
||||
onTouchEdge: artistQuery.fetchNext,
|
||||
child: ArtistCard(artist),
|
||||
);
|
||||
}
|
||||
return ArtistCard(artist);
|
||||
}).toList(),
|
||||
children: filteredArtists
|
||||
.mapIndexed((index, artist) => ArtistCard(artist))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -14,8 +14,8 @@ import 'package:spotube/services/queries/queries.dart';
|
||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||
|
||||
class PersonalizedItemCard extends HookWidget {
|
||||
final Iterable<Page<PlaylistSimple>>? playlists;
|
||||
final Iterable<Page<AlbumSimple>>? albums;
|
||||
final Iterable<PlaylistSimple>? playlists;
|
||||
final Iterable<AlbumSimple>? albums;
|
||||
final String title;
|
||||
final bool hasNextPage;
|
||||
final void Function() onFetchMore;
|
||||
@ -36,18 +36,6 @@ class PersonalizedItemCard extends HookWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final scrollController = useScrollController();
|
||||
|
||||
final playlistItems = playlists
|
||||
?.expand(
|
||||
(page) => page.items ?? const Iterable<PlaylistSimple>.empty(),
|
||||
)
|
||||
.toList();
|
||||
|
||||
final albumItems = albums
|
||||
?.expand(
|
||||
(page) => page.items ?? const Iterable<AlbumSimple>.empty(),
|
||||
)
|
||||
.toList();
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
@ -82,9 +70,8 @@ class PersonalizedItemCard extends HookWidget {
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...?playlistItems
|
||||
?.map((playlist) => PlaylistCard(playlist)),
|
||||
...?albumItems?.map(
|
||||
...?playlists?.map((playlist) => PlaylistCard(playlist)),
|
||||
...?albums?.map(
|
||||
(album) => AlbumCard(
|
||||
TypeConversionUtils.simpleAlbum_X_Album(album),
|
||||
),
|
||||
@ -108,20 +95,43 @@ class PersonalizedPage extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final featuredPlaylistsQuery = useQueries.playlist.featured(ref);
|
||||
final playlists = useMemoized(
|
||||
() => featuredPlaylistsQuery.pages
|
||||
.whereType<Page<PlaylistSimple>>()
|
||||
.expand((page) => page.items ?? const <PlaylistSimple>[]),
|
||||
[featuredPlaylistsQuery.pages],
|
||||
);
|
||||
|
||||
final newReleases = useQueries.album.newReleases(ref);
|
||||
final userArtists = useQueries.artist
|
||||
.followedByMeAll(ref)
|
||||
.data
|
||||
?.map((s) => s.id!)
|
||||
.toList() ??
|
||||
const [];
|
||||
|
||||
final albums = useMemoized(
|
||||
() => newReleases.pages
|
||||
.whereType<Page<AlbumSimple>>()
|
||||
.expand((page) => page.items ?? const <AlbumSimple>[])
|
||||
.where((album) {
|
||||
return album.artists
|
||||
?.any((artist) => userArtists.contains(artist.id!)) ==
|
||||
true;
|
||||
}),
|
||||
[newReleases.pages],
|
||||
);
|
||||
|
||||
return ListView(
|
||||
children: [
|
||||
PersonalizedItemCard(
|
||||
playlists:
|
||||
featuredPlaylistsQuery.pages.whereType<Page<PlaylistSimple>>(),
|
||||
playlists: playlists,
|
||||
title: context.l10n.featured,
|
||||
hasNextPage: featuredPlaylistsQuery.hasNextPage,
|
||||
onFetchMore: featuredPlaylistsQuery.fetchNext,
|
||||
),
|
||||
PersonalizedItemCard(
|
||||
albums: newReleases.pages.whereType<Page<AlbumSimple>>(),
|
||||
albums: albums,
|
||||
title: context.l10n.new_releases,
|
||||
hasNextPage: newReleases.hasNextPage,
|
||||
onFetchMore: newReleases.fetchNext,
|
||||
|
@ -58,7 +58,7 @@ class AlbumQueries {
|
||||
try {
|
||||
final albums = await spotify.browse
|
||||
.getNewReleases(country: market)
|
||||
.getPage(5, pageParam);
|
||||
.getPage(50, pageParam);
|
||||
|
||||
return albums;
|
||||
} catch (e, stack) {
|
||||
|
@ -38,6 +38,32 @@ class ArtistQueries {
|
||||
);
|
||||
}
|
||||
|
||||
Query<List<Artist>, dynamic> followedByMeAll(WidgetRef ref) {
|
||||
return useSpotifyQuery(
|
||||
"user-following-artists-all",
|
||||
(spotify) async {
|
||||
CursorPage<Artist>? page =
|
||||
await spotify.me.following(FollowingType.artist).getPage(50);
|
||||
|
||||
final following = <Artist>[];
|
||||
|
||||
if (page.isLast == true) {
|
||||
return page.items?.toList() ?? [];
|
||||
}
|
||||
|
||||
while (page?.isLast != true) {
|
||||
following.addAll(page?.items ?? []);
|
||||
page = await spotify.me
|
||||
.following(FollowingType.artist)
|
||||
.getPage(50, page?.after ?? '');
|
||||
}
|
||||
|
||||
return following;
|
||||
},
|
||||
ref: ref,
|
||||
);
|
||||
}
|
||||
|
||||
Query<bool, dynamic> doIFollow(
|
||||
WidgetRef ref,
|
||||
String artist,
|
||||
|
Loading…
Reference in New Issue
Block a user