mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-05-08 16:24:36 +00:00
feat: use providers on library page
This commit is contained in:
parent
786342912b
commit
4ae530d29d
@ -4,7 +4,6 @@ import 'package:collection/collection.dart';
|
||||
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:skeletonizer/skeletonizer.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/fake.dart';
|
||||
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
@ -15,7 +14,7 @@ import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart';
|
||||
import 'package:spotube/components/shared/waypoint.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
import 'package:spotube/services/queries/queries.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||
|
||||
@ -25,32 +24,28 @@ class UserAlbums extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final auth = ref.watch(AuthenticationNotifier.provider);
|
||||
final albumsQuery = useQueries.album.ofMine(ref);
|
||||
final albumsQuery = ref.watch(favoriteAlbumsProvider);
|
||||
final albumsQueryNotifier = ref.watch(favoriteAlbumsProvider.notifier);
|
||||
|
||||
final controller = useScrollController();
|
||||
|
||||
final searchText = useState('');
|
||||
|
||||
final allAlbums = useMemoized(
|
||||
() => albumsQuery.pages
|
||||
.expand((element) => element.items ?? <AlbumSimple>[]),
|
||||
[albumsQuery.pages],
|
||||
);
|
||||
|
||||
final albums = useMemoized(() {
|
||||
if (searchText.value.isEmpty) {
|
||||
return allAlbums;
|
||||
return albumsQuery.value?.items ?? [];
|
||||
}
|
||||
return allAlbums
|
||||
.map((e) => (
|
||||
weightedRatio(e.name!, searchText.value),
|
||||
e,
|
||||
))
|
||||
.sorted((a, b) => b.$1.compareTo(a.$1))
|
||||
.where((e) => e.$1 > 50)
|
||||
.map((e) => e.$2)
|
||||
.toList();
|
||||
}, [allAlbums, searchText.value]);
|
||||
return albumsQuery.value?.items
|
||||
.map((e) => (
|
||||
weightedRatio(e.name!, searchText.value),
|
||||
e,
|
||||
))
|
||||
.sorted((a, b) => b.$1.compareTo(a.$1))
|
||||
.where((e) => e.$1 > 50)
|
||||
.map((e) => e.$2)
|
||||
.toList() ??
|
||||
[];
|
||||
}, [albumsQuery.value, searchText.value]);
|
||||
|
||||
if (auth == null) {
|
||||
return const AnonymousFallback();
|
||||
@ -60,7 +55,7 @@ class UserAlbums extends HookConsumerWidget {
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await albumsQuery.refresh();
|
||||
ref.invalidate(favoriteAlbumsProvider);
|
||||
},
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
@ -85,7 +80,7 @@ class UserAlbums extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
controller: controller,
|
||||
child: Skeletonizer(
|
||||
enabled: albumsQuery.pages.isEmpty,
|
||||
enabled: albumsQuery.isLoadingAndEmpty,
|
||||
child: Center(
|
||||
child: Wrap(
|
||||
runSpacing: 20,
|
||||
@ -93,7 +88,8 @@ class UserAlbums extends HookConsumerWidget {
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
if (albumsQuery.pages.isEmpty)
|
||||
if (albumsQuery.value == null ||
|
||||
albumsQuery.value!.items.isEmpty)
|
||||
...List.generate(
|
||||
10,
|
||||
(index) => AlbumCard(FakeData.album),
|
||||
@ -107,11 +103,12 @@ class UserAlbums extends HookConsumerWidget {
|
||||
AlbumCard(
|
||||
TypeConversionUtils.simpleAlbum_X_Album(album),
|
||||
),
|
||||
if (albums.isNotEmpty && albumsQuery.hasNextPage)
|
||||
if (albums.isNotEmpty &&
|
||||
albumsQuery.value?.hasMore == true)
|
||||
Waypoint(
|
||||
controller: controller,
|
||||
isGrid: true,
|
||||
onTouchEdge: albumsQuery.fetchNext,
|
||||
onTouchEdge: albumsQueryNotifier.fetchMore,
|
||||
child: AlbumCard(FakeData.album),
|
||||
)
|
||||
],
|
||||
|
||||
@ -13,7 +13,7 @@ import 'package:spotube/components/shared/fallbacks/not_found.dart';
|
||||
import 'package:spotube/components/shared/inter_scrollbar/inter_scrollbar.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
import 'package:spotube/services/queries/queries.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class UserArtists extends HookConsumerWidget {
|
||||
const UserArtists({super.key});
|
||||
@ -23,12 +23,12 @@ class UserArtists extends HookConsumerWidget {
|
||||
final theme = Theme.of(context);
|
||||
final auth = ref.watch(AuthenticationNotifier.provider);
|
||||
|
||||
final artistQuery = useQueries.artist.followedByMeAll(ref);
|
||||
final artistQuery = ref.watch(followedArtistsProvider);
|
||||
|
||||
final searchText = useState('');
|
||||
|
||||
final filteredArtists = useMemoized(() {
|
||||
final artists = artistQuery.data ?? [];
|
||||
final artists = artistQuery.value?.items ?? [];
|
||||
|
||||
if (searchText.value.isEmpty) {
|
||||
return artists.toList();
|
||||
@ -42,7 +42,7 @@ class UserArtists extends HookConsumerWidget {
|
||||
.where((e) => e.$1 > 50)
|
||||
.map((e) => e.$2)
|
||||
.toList();
|
||||
}, [artistQuery.data, searchText.value]);
|
||||
}, [artistQuery.value?.items, searchText.value]);
|
||||
|
||||
final controller = useScrollController();
|
||||
|
||||
@ -66,7 +66,7 @@ class UserArtists extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
body: artistQuery.data?.isEmpty == true
|
||||
body: artistQuery.value?.items.isEmpty == true
|
||||
? Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
@ -80,7 +80,7 @@ class UserArtists extends HookConsumerWidget {
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await artistQuery.refresh();
|
||||
ref.invalidate(followedArtistsProvider);
|
||||
},
|
||||
child: InterScrollbar(
|
||||
controller: controller,
|
||||
@ -109,8 +109,9 @@ class UserArtists extends HookConsumerWidget {
|
||||
)
|
||||
]
|
||||
: filteredArtists
|
||||
.mapIndexed((index, artist) =>
|
||||
ArtistCard(artist))
|
||||
.mapIndexed(
|
||||
(index, artist) => ArtistCard(artist),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
|
||||
@ -217,7 +217,7 @@ class UserLocalTracks extends HookConsumerWidget {
|
||||
FilledButton(
|
||||
child: const Icon(SpotubeIcons.refresh),
|
||||
onPressed: () {
|
||||
ref.refresh(localTracksProvider);
|
||||
ref.invalidate(localTracksProvider);
|
||||
},
|
||||
)
|
||||
],
|
||||
@ -269,7 +269,7 @@ class UserLocalTracks extends HookConsumerWidget {
|
||||
return Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
ref.refresh(localTracksProvider);
|
||||
ref.invalidate(localTracksProvider);
|
||||
},
|
||||
child: InterScrollbar(
|
||||
controller: controller,
|
||||
|
||||
@ -17,7 +17,7 @@ import 'package:spotube/components/shared/waypoint.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
import 'package:spotube/services/queries/queries.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class UserPlaylists extends HookConsumerWidget {
|
||||
const UserPlaylists({super.key});
|
||||
@ -28,13 +28,9 @@ class UserPlaylists extends HookConsumerWidget {
|
||||
|
||||
final auth = ref.watch(AuthenticationNotifier.provider);
|
||||
|
||||
final playlistsQuery = useQueries.playlist.ofMine(ref);
|
||||
|
||||
final pagePlaylists = useMemoized(
|
||||
() => playlistsQuery.pages
|
||||
.expand((page) => page.items?.toList() ?? <PlaylistSimple>[]),
|
||||
[playlistsQuery.pages],
|
||||
);
|
||||
final playlistsQuery = ref.watch(favoritePlaylistsProvider);
|
||||
final playlistsQueryNotifier =
|
||||
ref.watch(favoritePlaylistsProvider.notifier);
|
||||
|
||||
final likedTracksPlaylist = useMemoized(
|
||||
() => PlaylistSimple()
|
||||
@ -58,12 +54,12 @@ class UserPlaylists extends HookConsumerWidget {
|
||||
if (searchText.value.isEmpty) {
|
||||
return [
|
||||
likedTracksPlaylist,
|
||||
...pagePlaylists,
|
||||
...?playlistsQuery.value?.items,
|
||||
];
|
||||
}
|
||||
return [
|
||||
likedTracksPlaylist,
|
||||
...pagePlaylists,
|
||||
...?playlistsQuery.value?.items,
|
||||
]
|
||||
.map((e) => (weightedRatio(e.name!, searchText.value), e))
|
||||
.sorted((a, b) => b.$1.compareTo(a.$1))
|
||||
@ -71,7 +67,7 @@ class UserPlaylists extends HookConsumerWidget {
|
||||
.map((e) => e.$2)
|
||||
.toList();
|
||||
},
|
||||
[pagePlaylists, searchText.value],
|
||||
[playlistsQuery, searchText.value],
|
||||
);
|
||||
|
||||
final controller = useScrollController();
|
||||
@ -81,7 +77,9 @@ class UserPlaylists extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: playlistsQuery.refresh,
|
||||
onRefresh: () async {
|
||||
ref.invalidate(favoritePlaylistsProvider);
|
||||
},
|
||||
child: SafeArea(
|
||||
child: InterScrollbar(
|
||||
controller: controller,
|
||||
@ -132,14 +130,14 @@ class UserPlaylists extends HookConsumerWidget {
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
if (playlists.isNotEmpty && index == playlists.length) {
|
||||
if (!playlistsQuery.hasNextPage) {
|
||||
if (playlistsQuery.value?.hasMore != true) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Waypoint(
|
||||
controller: controller,
|
||||
isGrid: true,
|
||||
onTouchEdge: playlistsQuery.fetchNext,
|
||||
onTouchEdge: playlistsQueryNotifier.fetchMore,
|
||||
child: Skeletonizer(
|
||||
enabled: true,
|
||||
child: PlaylistCard(FakeData.playlistSimple),
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
import 'package:spotube/provider/spotify_provider.dart';
|
||||
import 'package:spotube/services/custom_spotify_endpoints/spotify_endpoints.dart';
|
||||
|
||||
final customSpotifyEndpointProvider = Provider<CustomSpotifyEndpoints>((ref) {
|
||||
ref.watch(spotifyProvider);
|
||||
final auth = ref.watch(AuthenticationNotifier.provider);
|
||||
return CustomSpotifyEndpoints(auth?.accessToken ?? "");
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
part of '../spotify.dart';
|
||||
|
||||
class FollowedArtistsState extends CursorPaginatedState<ArtistSimple> {
|
||||
class FollowedArtistsState extends CursorPaginatedState<Artist> {
|
||||
FollowedArtistsState({
|
||||
required super.items,
|
||||
required super.offset,
|
||||
@ -10,7 +10,7 @@ class FollowedArtistsState extends CursorPaginatedState<ArtistSimple> {
|
||||
|
||||
@override
|
||||
FollowedArtistsState copyWith({
|
||||
List<ArtistSimple>? items,
|
||||
List<Artist>? items,
|
||||
String? offset,
|
||||
int? limit,
|
||||
bool? hasMore,
|
||||
@ -25,7 +25,7 @@ class FollowedArtistsState extends CursorPaginatedState<ArtistSimple> {
|
||||
}
|
||||
|
||||
class FollowedArtistsNotifier
|
||||
extends CursorPaginatedAsyncNotifier<ArtistSimple, FollowedArtistsState> {
|
||||
extends CursorPaginatedAsyncNotifier<Artist, FollowedArtistsState> {
|
||||
FollowedArtistsNotifier() : super();
|
||||
|
||||
@override
|
||||
@ -95,7 +95,7 @@ final followedArtistsProvider =
|
||||
() => FollowedArtistsNotifier(),
|
||||
);
|
||||
|
||||
final allFollowedArtistsProvider = FutureProvider<List<ArtistSimple>>(
|
||||
final allFollowedArtistsProvider = FutureProvider<List<Artist>>(
|
||||
(ref) async {
|
||||
final spotify = ref.watch(spotifyProvider);
|
||||
final artists = await spotify.me.following(FollowingType.artist).all();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user