v2.50.4 — Glow-Pulsation rebuildet + Cover-Crossfade beim Songwechsel
## Fix 1 (MED): Glow-Pulsation rebuildet jetzt wirklich
- now_playing_screen.dart: Cover-Container mit AnimatedBuilder(animation: _glowController) gewrappt — BoxShadow (blur 50–70 / spread 6–12) wird jetzt pro Animations-Tick neu gebaut statt nur bei fremden setStates (Pulsation war vorher nur zufällig über positionStream sichtbar und fror bei Pause/Pufferung ein)
## Fix 2 (MED): Echter Crossfade beim Songwechsel
- _songSub-Listener setzt _hatCover/_coverPfad jetzt SYNCHRON auf false/null (im selben setState) — Hintergrund und Front-Cover zeigen beim Songwechsel kein altes Cover mehr, bis die async Existenz-Prüfung durch ist
- _hintergrundBlur-Key auf den tatsächlichen Cover-Pfad gelegt ('cover-$pfad' statt song.id) — Switcher wechselt erst bei geladenem neuem Cover (Crossfade Gradient→Cover), kein Fade alt→alt + harter Cut mehr
flutter analyze: 0 Issues, Tests 98/98 grün, keine neuen Packages
This commit is contained in:
@@ -91,6 +91,12 @@ class _NowPlayingScreenState extends State<NowPlayingScreen>
|
|||||||
_zeigeLyrics = false;
|
_zeigeLyrics = false;
|
||||||
_lyrics = null;
|
_lyrics = null;
|
||||||
_lyricsLaden = true;
|
_lyricsLaden = true;
|
||||||
|
// Cover-Zustand SYNCHRON zurücksetzen: Sonst rendern Hintergrund
|
||||||
|
// (und Front-Cover) beim Songwechsel kurz das ALTE Cover, bis die
|
||||||
|
// async Existenz-Prüfung durch ist — der Switcher-Key (song.id)
|
||||||
|
// wechselt sofort → Fade alt→alt, dann harter Cut aufs neue Cover.
|
||||||
|
_hatCover = false;
|
||||||
|
_coverPfad = null;
|
||||||
});
|
});
|
||||||
_ladeLyricsFuer(song, _ladeGeneration);
|
_ladeLyricsFuer(song, _ladeGeneration);
|
||||||
_ladeFavoritStatus(song);
|
_ladeFavoritStatus(song);
|
||||||
@@ -567,7 +573,11 @@ class _NowPlayingScreenState extends State<NowPlayingScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ImageFiltered(
|
return ImageFiltered(
|
||||||
key: ValueKey('cover-${song?.id ?? pfad}'),
|
// Key auf den tatsächlichen Cover-Pfad statt song.id: Der Switcher
|
||||||
|
// wechselt erst, wenn das NEUE Cover wirklich geladen ist (echter
|
||||||
|
// Crossfade) — nie vorher (altes Bild unter neuem Key = unsichtbarer
|
||||||
|
// Fade + harter Cut beim Nachladen).
|
||||||
|
key: ValueKey('cover-$pfad'),
|
||||||
imageFilter: ImageFilter.blur(sigmaX: 45, sigmaY: 45),
|
imageFilter: ImageFilter.blur(sigmaX: 45, sigmaY: 45),
|
||||||
child: Image.file(File(pfad), fit: BoxFit.cover),
|
child: Image.file(File(pfad), fit: BoxFit.cover),
|
||||||
);
|
);
|
||||||
@@ -636,30 +646,35 @@ class _NowPlayingScreenState extends State<NowPlayingScreen>
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// Cover mit Glow
|
// Cover mit Glow — AnimatedBuilder um den Container: Ohne Listener/
|
||||||
Container(
|
// Builder würde der BoxShadow nur bei fremden setStates neu gebaut
|
||||||
width: coverGroesse,
|
// (Pulsation zufällig sichtbar, friert bei Pause/Pufferung ein).
|
||||||
height: coverGroesse,
|
AnimatedBuilder(
|
||||||
decoration: BoxDecoration(
|
animation: _glowController,
|
||||||
borderRadius: BorderRadius.circular(20),
|
builder: (context, _) => Container(
|
||||||
boxShadow: [
|
width: coverGroesse,
|
||||||
BoxShadow(
|
height: coverGroesse,
|
||||||
// Glow in der Akzentfarbe des Users, pulsierend bei Wiedergabe
|
decoration: BoxDecoration(
|
||||||
color: MeloTheme.akzent.withValues(alpha: 0.45),
|
borderRadius: BorderRadius.circular(20),
|
||||||
blurRadius: 50 + 20 * _glowController.value, // 50–70
|
boxShadow: [
|
||||||
spreadRadius: 6 + 6 * _glowController.value, // 6–12
|
BoxShadow(
|
||||||
),
|
// Glow in der Akzentfarbe des Users, pulsierend bei Wiedergabe
|
||||||
],
|
color: MeloTheme.akzent.withValues(alpha: 0.45),
|
||||||
),
|
blurRadius: 50 + 20 * _glowController.value, // 50–70
|
||||||
child: ClipRRect(
|
spreadRadius: 6 + 6 * _glowController.value, // 6–12
|
||||||
borderRadius: BorderRadius.circular(20),
|
),
|
||||||
child: hatCover
|
],
|
||||||
? Image.file(File(_coverPfad!), fit: BoxFit.cover)
|
),
|
||||||
: Container(
|
child: ClipRRect(
|
||||||
color: MeloTheme.rotHell,
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: const Icon(Icons.music_note,
|
child: hatCover
|
||||||
size: 90, color: MeloTheme.rot),
|
? Image.file(File(_coverPfad!), fit: BoxFit.cover)
|
||||||
),
|
: Container(
|
||||||
|
color: MeloTheme.rotHell,
|
||||||
|
child: const Icon(Icons.music_note,
|
||||||
|
size: 90, color: MeloTheme.rot),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
|
|||||||
Reference in New Issue
Block a user