feat: heart button animation

This commit is contained in:
Kingkor Roy Tirtho 2023-04-28 22:21:17 +06:00
parent af278d8fea
commit 8432dc6286
2 changed files with 42 additions and 19 deletions

View File

@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/hooks/use_palette_color.dart'; import 'package:spotube/hooks/use_palette_color.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/services/mutations/mutations.dart'; import 'package:spotube/services/mutations/mutations.dart';
@ -13,7 +12,7 @@ import 'package:spotube/services/queries/queries.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
class HeartButton extends ConsumerWidget { class HeartButton extends HookConsumerWidget {
final bool isLiked; final bool isLiked;
final void Function()? onPressed; final void Function()? onPressed;
final IconData? icon; final IconData? icon;
@ -36,9 +35,24 @@ class HeartButton extends ConsumerWidget {
return IconButton( return IconButton(
tooltip: tooltip, tooltip: tooltip,
icon: Icon( icon: AnimatedSwitcher(
icon ?? (!isLiked ? SpotubeIcons.heart : SpotubeIcons.heartFilled), switchInCurve: Curves.fastOutSlowIn,
color: isLiked ? Colors.pink : color, switchOutCurve: Curves.fastOutSlowIn,
duration: const Duration(milliseconds: 300),
transitionBuilder: (child, animation) {
return ScaleTransition(
scale: animation,
child: child,
);
},
child: Icon(
icon ??
(isLiked
? Icons.favorite_rounded
: Icons.favorite_outline_rounded),
key: ValueKey(isLiked),
color: color ?? (isLiked ? color ?? Colors.red : null),
),
), ),
onPressed: onPressed, onPressed: onPressed,
); );
@ -53,29 +67,36 @@ Tuple3<bool, Mutation<bool, dynamic, bool>, Query<User, dynamic>>
useQueries.playlist.tracksOfQuery(ref, "user-liked-tracks"); useQueries.playlist.tracksOfQuery(ref, "user-liked-tracks");
final isLiked = final isLiked =
savedTracks.data?.map((track) => track.id).contains(track.id) ?? false; savedTracks.data?.any((element) => element.id == track.id) ?? false;
final mounted = useIsMounted(); final mounted = useIsMounted();
final toggleTrackLike = useMutations.track.toggleFavorite( final toggleTrackLike = useMutations.track.toggleFavorite(
ref, ref,
track.id!, track.id!,
onMutate: (variables) { onMutate: (isLiked) {
return variables; savedTracks.setData(
[
if (isLiked == true)
...?savedTracks.data?.where((element) => element.id != track.id)
else
...?savedTracks.data?..add(track)
],
);
return isLiked;
},
onData: (data, recoveryData) async {
await savedTracks.refresh();
}, },
onError: (payload, isLiked) { onError: (payload, isLiked) {
if (!mounted()) return; if (!mounted()) return;
savedTracks.setData( savedTracks.setData([
isLiked == true if (isLiked != true)
? [...(savedTracks.data ?? []), track] ...?savedTracks.data?.where((element) => element.id != track.id)
: savedTracks.data else
?.where( ...?savedTracks.data?..add(track),
(element) => element.id != track.id, ]);
)
.toList() ??
[],
);
}, },
); );

View File

@ -377,7 +377,9 @@ class TrackTile extends HookConsumerWidget {
color: Colors.pink, color: Colors.pink,
) )
: const Icon(SpotubeIcons.heart), : const Icon(SpotubeIcons.heart),
title: const Text("Save as favorite"), title: Text(
"${toggler.item1 ? "Remove from" : "Save as "} favorite",
),
), ),
), ),
if (auth != null) if (auth != null)