fix: v1.26.1 — hero/album/playlist background flickering

Background of Hero carousel, Album Detail and Playlist Detail was
flickering for up to 20 seconds on first visit. useCachedUrl with
fallbackToFetch=true returned the raw server URL immediately, causing
a double render — once with the HTTP URL and again when the blob was
ready. Fixed by passing fallbackToFetch=false in all three locations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-01 21:20:15 +02:00
parent 434ee0ecf1
commit d8da511a8f
9 changed files with 16 additions and 8 deletions
+8
View File
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.26.1] - 2026-04-01
### Fixed
- **Background flickering in Hero, Album Detail and Playlist Detail**: Blurred hero backgrounds were flickering for up to 20 seconds on first visit. Root cause: `useCachedUrl` with the default `fallbackToFetch = true` immediately returned the raw server URL, causing the background to render twice — once with the HTTP URL (triggering a server fetch) and again when the IndexedDB blob was ready. Fixed by passing `fallbackToFetch = false` in all three locations so the background only renders once the blob is cached.
---
## [1.26.0] - 2026-04-01
### Added
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "psysonic",
"version": "1.26.0",
"version": "1.26.1",
"private": true,
"scripts": {
"dev": "vite",
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Psychotoxic <psychotoxic@gmx.de>
pkgname=psysonic
pkgver=1.26.0
pkgver=1.26.1
pkgrel=1
pkgdesc="Desktop music player for Subsonic API-compatible servers (Navidrome, Gonic, etc.)"
arch=('x86_64')
+1 -1
View File
@@ -3397,7 +3397,7 @@ dependencies = [
[[package]]
name = "psysonic"
version = "1.25.1"
version = "1.26.1"
dependencies = [
"biquad",
"md5",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "psysonic"
version = "1.26.0"
version = "1.26.1"
description = "Psysonic Desktop Music Player"
authors = []
license = ""
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Psysonic",
"version": "1.26.0",
"version": "1.26.1",
"identifier": "dev.psysonic.player",
"build": {
"beforeDevCommand": "npm run dev",
+1 -1
View File
@@ -95,7 +95,7 @@ export default function Hero({ albums: albumsProp }: HeroProps = {}) {
// buildCoverArtUrl generates a new salt on every call — must be memoized.
const bgRawUrl = useMemo(() => album?.coverArt ? buildCoverArtUrl(album.coverArt, 800) : '', [album?.coverArt]);
const bgCacheKey = useMemo(() => album?.coverArt ? coverArtCacheKey(album.coverArt, 800) : '', [album?.coverArt]);
const resolvedBgUrl = useCachedUrl(bgRawUrl, bgCacheKey);
const resolvedBgUrl = useCachedUrl(bgRawUrl, bgCacheKey, false);
// Keep the last known good URL so HeroBg never receives '' during a cache-miss
// transition (which would cause the background to flash empty before fading in).
+1 -1
View File
@@ -234,7 +234,7 @@ const handleEnqueueAll = () => {
// Hooks must be called unconditionally — derive from nullable album state
const coverUrl = album?.album.coverArt ? buildCoverArtUrl(album.album.coverArt, 400) : '';
const coverKey = album?.album.coverArt ? coverArtCacheKey(album.album.coverArt, 400) : '';
const resolvedCoverUrl = useCachedUrl(coverUrl, coverKey);
const resolvedCoverUrl = useCachedUrl(coverUrl, coverKey, false);
if (loading) return <div className="loading-center"><div className="spinner" /></div>;
if (!album) return <div className="empty-state">{t('albumDetail.notFound')}</div>;
+1 -1
View File
@@ -136,7 +136,7 @@ export default function PlaylistDetail() {
const bgFetchUrl = useMemo(() => buildCoverArtUrl(coverQuad[0] ?? '', 300), [coverQuad]);
const bgCacheKey = useMemo(() => coverArtCacheKey(coverQuad[0] ?? '', 300), [coverQuad]);
const resolvedBgUrl = useCachedUrl(bgFetchUrl, bgCacheKey);
const resolvedBgUrl = useCachedUrl(bgFetchUrl, bgCacheKey, false);
// Song search
const [searchOpen, setSearchOpen] = useState(false);