feat(flutter/likes): LikeButton with optimistic toggle + rollback

LikedIdsController loads /api/likes/ids once and mutates the local set
on toggle. Failed mutations roll the set back so the icon never lies.
Wired into ArtistDetail header, AlbumDetail header, and per-track in
the album track list.
This commit is contained in:
2026-05-02 17:34:59 -04:00
parent 6ec7cea362
commit 44e2623b3c
6 changed files with 238 additions and 3 deletions
+36
View File
@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/endpoints/likes.dart';
import '../theme/theme_extension.dart';
import 'likes_provider.dart';
class LikeButton extends ConsumerWidget {
const LikeButton({
required this.kind,
required this.id,
this.size = 22,
super.key,
});
final LikeKind kind;
final String id;
final double size;
@override
Widget build(BuildContext context, WidgetRef ref) {
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
final state = ref.watch(likedIdsProvider);
final liked = state.maybeWhen(
data: (s) => s.has(kind, id),
orElse: () => false,
);
return IconButton(
icon: Icon(
liked ? Icons.favorite : Icons.favorite_border,
color: liked ? fs.accent : fs.ash,
size: size,
),
onPressed: () => ref.read(likedIdsProvider.notifier).toggle(kind, id),
);
}
}