feat: add playlist create and update and favorite handlers

This commit is contained in:
Kingkor Roy Tirtho 2024-03-16 20:13:17 +06:00
parent f8550ae3d6
commit f83d6e08e1
5 changed files with 166 additions and 12 deletions

View File

@ -41,12 +41,11 @@ class FavoriteAlbumNotifier
);
}
Future<void> saveAlbums(List<String> ids) async {
Future<void> addFavorites(List<String> ids) async {
if (state.value == null) return;
await spotify.me.saveAlbums(ids);
state = await AsyncValue.guard(() async {
await spotify.me.saveAlbums(ids);
final albums = await spotify.albums.list(ids);
return state.value!.copyWith(
@ -57,6 +56,20 @@ class FavoriteAlbumNotifier
);
});
}
Future<void> removeFavorites(List<String> ids) async {
if (state.value == null) return;
state = await AsyncValue.guard(() async {
await spotify.me.removeAlbums(ids);
return state.value!.copyWith(
items: state.value!.items
.where((element) => !ids.contains(element.id))
.toList(),
);
});
}
}
final favoriteAlbumsProvider =

View File

@ -50,6 +50,24 @@ class FavoritePlaylistsNotifier
hasMore: playlists.length == 20,
);
}
Future<void> addFavorite(PlaylistSimple playlist) async {
update((state) async {
await spotify.playlists.followPlaylist(playlist.id!);
return state.copyWith(
items: [...state.items, playlist],
);
});
}
Future<void> removeFavorite(PlaylistSimple playlist) async {
update((state) async {
await spotify.playlists.unfollowPlaylist(playlist.id!);
return state.copyWith(
items: state.items.where((e) => e.id != playlist.id).toList(),
);
});
}
}
final favoritePlaylistsProvider =

View File

@ -1,8 +1,49 @@
part of '../spotify.dart';
final likedTracksProvider = FutureProvider<List<Track>>((ref) async {
final spotify = ref.watch(spotifyProvider);
final savedTracked = await spotify.tracks.me.saved.all();
class LikedTracksNotifier extends AsyncNotifier<List<Track>> with Persistence {
LikedTracksNotifier() {
load();
}
return savedTracked.map((e) => e.track!).toList();
});
@override
FutureOr<List<Track>> build() async {
final spotify = ref.watch(spotifyProvider);
final savedTracked = await spotify.tracks.me.saved.all();
return savedTracked.map((e) => e.track!).toList();
}
Future<void> toggleFavorite(Track track) async {
if (state.value == null) return;
final spotify = ref.read(spotifyProvider);
await update((tracks) async {
final isLiked = tracks.map((e) => e.id).contains(track.id);
if (isLiked) {
await spotify.tracks.me.removeOne(track.id!);
return tracks.where((e) => e.id != track.id).toList();
} else {
await spotify.tracks.me.saveOne(track.id!);
return [...tracks, track];
}
});
}
@override
FutureOr<List<Track>> fromJson(Map<String, dynamic> json) {
return (json['tracks'] as List).map((e) => Track.fromJson(e)).toList();
}
@override
Map<String, dynamic> toJson(List<Track> data) {
return {
'tracks': data.map((e) => e.toJson()).toList(),
};
}
}
final likedTracksProvider =
AsyncNotifierProvider<LikedTracksNotifier, List<Track>>(
() => LikedTracksNotifier(),
);

View File

@ -1,8 +1,89 @@
part of '../spotify.dart';
final playlistProvider = FutureProvider.family<Playlist, String>(
(ref, playlistId) async {
typedef PlaylistInput = ({
String playlistName,
bool? public,
bool? collaborative,
String? description,
String? base64Image,
});
class PlaylistNotifier extends FamilyAsyncNotifier<Playlist, String> {
@override
FutureOr<Playlist> build(String arg) {
final spotify = ref.watch(spotifyProvider);
return spotify.playlists.get(playlistId);
},
return spotify.playlists.get(arg);
}
Future<void> create(PlaylistInput input) async {
if (state is AsyncData || state is AsyncLoading) return;
state = const AsyncLoading();
final spotify = ref.read(spotifyProvider);
final me = ref.read(meProvider);
if (me.value == null) return;
state = await AsyncValue.guard(() async {
final playlist = await spotify.playlists.createPlaylist(
me.value!.id!,
input.playlistName,
collaborative: input.collaborative,
description: input.description,
public: input.public,
);
if (input.base64Image != null) {
await spotify.playlists.updatePlaylistImage(
playlist.id!,
input.base64Image!,
);
}
return playlist;
});
}
Future<void> addTracks(List<String> trackIds) async {
if (state.value == null) return;
final spotify = ref.read(spotifyProvider);
await spotify.playlists.addTracks(
trackIds.map((id) => 'spotify:track:$id').toList(),
state.value!.id!,
);
ref.refresh(playlistTracksProvider(state.value!.id!));
}
Future<void> modify(PlaylistInput input) async {
if (state.value == null) return;
final spotify = ref.read(spotifyProvider);
await update((state) async {
await spotify.playlists.updatePlaylist(
state.id!,
input.playlistName,
collaborative: input.collaborative,
description: input.description,
public: input.public,
);
if (input.base64Image != null) {
await spotify.playlists.updatePlaylistImage(
state.id!,
input.base64Image!,
);
}
return spotify.playlists.get(state.id!);
});
}
}
final playlistProvider =
AsyncNotifierProvider.family<PlaylistNotifier, String, PlaylistNotifier>(
() => PlaylistNotifier(),
);

View File

@ -11,6 +11,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
// ignore: depend_on_referenced_packages, implementation_imports
import 'package:riverpod/src/async_notifier.dart';
import 'package:spotube/extensions/map.dart';
import 'package:spotube/extensions/track.dart';
import 'package:spotube/models/lyrics.dart';
import 'package:spotube/models/spotify/recommendation_seeds.dart';
import 'package:spotube/models/spotify_friends.dart';