import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../api/endpoints/likes.dart'; import '../library/library_providers.dart'; final likesApiProvider = FutureProvider((ref) async { return LikesApi(await ref.watch(dioProvider.future)); }); class LikedIds { const LikedIds({ required this.artists, required this.albums, required this.tracks, }); final Set artists; final Set albums; final Set tracks; bool has(LikeKind kind, String id) => switch (kind) { LikeKind.artist => artists.contains(id), LikeKind.album => albums.contains(id), LikeKind.track => tracks.contains(id), }; } class LikedIdsController extends AsyncNotifier { @override Future build() async { final api = await ref.watch(likesApiProvider.future); final r = await api.ids(); return LikedIds(artists: r.artists, albums: r.albums, tracks: r.tracks); } Future toggle(LikeKind kind, String id) async { final api = await ref.read(likesApiProvider.future); final current = state.value ?? const LikedIds(artists: {}, albums: {}, tracks: {}); final isLiked = current.has(kind, id); final optimistic = _flip(current, kind, id); state = AsyncData(optimistic); try { if (isLiked) { await api.unlike(kind, id); } else { await api.like(kind, id); } } catch (e, st) { state = AsyncData(current); Error.throwWithStackTrace(e, st); } } LikedIds _flip(LikedIds before, LikeKind kind, String id) { Set swap(Set s) { final next = {...s}; if (s.contains(id)) { next.remove(id); } else { next.add(id); } return next; } return switch (kind) { LikeKind.artist => LikedIds( artists: swap(before.artists), albums: before.albums, tracks: before.tracks, ), LikeKind.album => LikedIds( artists: before.artists, albums: swap(before.albums), tracks: before.tracks, ), LikeKind.track => LikedIds( artists: before.artists, albums: before.albums, tracks: swap(before.tracks), ), }; } } final likedIdsProvider = AsyncNotifierProvider(LikedIdsController.new);