fix(favorites): heart button works in tracks tab, animate out on unfavorite

Remove isFavoriteOverride={true} that forced all hearts filled,
preventing the toggle from having any visible effect. Subscribe to
favoritesStore so unfavorited tracks animate out (slide+fade) and
are removed from the list after 300ms without requiring a refresh.
This commit is contained in:
vicrodh committed 2026-02-25 20:11:31 -06:00
1 parent e829c5dc7f
commit 6c3f7e8d40
1 file changed
+54 -2
+54 -2
View File
@@ -19,7 +19,7 @@
import { type OfflineCacheStatus } from '$lib/stores/offlineCacheState';
import { consumeContextTrackFocus, setPlaybackContext } from '$lib/stores/playbackContextStore';
import { normalizeFavoritesTabOrder } from '$lib/utils/favorites';
import { syncCache as syncTrackCache } from '$lib/stores/favoritesStore';
import { syncCache as syncTrackCache, subscribe as subscribeFavorites, isTrackFavorite } from '$lib/stores/favoritesStore';
import { syncCache as syncAlbumCache } from '$lib/stores/albumFavoritesStore';
import { syncCache as syncArtistCache } from '$lib/stores/artistFavoritesStore';
import { categorizeAlbum, getQobuzImage, formatQuality } from '$lib/adapters/qobuzAdapters';
@@ -622,6 +622,30 @@
}
});
});
// Listen for favorite changes — animate out unfavorited tracks
const unsubFavorites = subscribeFavorites(() => {
if (activeTab !== 'tracks' || favoriteTracks.length === 0) return;
const unfavorited = favoriteTracks.filter(track => !isTrackFavorite(track.id));
if (unfavorited.length === 0) return;
// Add exit animation class via DOM (virtualized list doesn't support per-item props)
for (const track of unfavorited) {
const el = scrollContainer?.querySelector<HTMLElement>(`[data-track-id="${track.id}"]`);
if (el) {
el.classList.add('track-removing');
}
}
// After animation completes, remove from data array
setTimeout(() => {
favoriteTracks = favoriteTracks.filter(track => isTrackFavorite(track.id));
}, 300);
});
return () => {
unsubFavorites();
};
});
function handleFavoritesScroll(e: Event) {
@@ -1638,7 +1662,6 @@
isLocal={false}
hideDownload={false}
hideFavorite={false}
isFavoriteOverride={true}
getOfflineCacheStatus={getTrackOfflineCacheStatus}
onDownload={onTrackDownload ? (trk) => onTrackDownload(buildDisplayTrackFromFavorite(trk)) : undefined}
onRemoveDownload={onTrackRemoveDownload}
@@ -2041,6 +2064,35 @@
/>
<style>
/* Exit animation for unfavorited tracks */
:global(.track-removing) {
animation: track-fade-out 300ms ease forwards;
pointer-events: none;
}
@keyframes track-fade-out {
0% {
opacity: 1;
transform: translateX(0);
max-height: 60px;
}
60% {
opacity: 0;
transform: translateX(-30px);
max-height: 60px;
}
100% {
opacity: 0;
transform: translateX(-30px);
max-height: 0;
padding-top: 0;
padding-bottom: 0;
margin-top: 0;
margin-bottom: 0;
overflow: hidden;
}
}
.favorites-view {
padding: 24px;
padding-left: 18px;