Mitsuha pause fixes and other bugs

This commit is contained in:
Dallas Groot 2026-04-05 08:33:00 -07:00
parent a61b6776ce
commit 2b879fd153
3 changed files with 20 additions and 7 deletions

View file

@ -553,6 +553,7 @@ struct MiniPlayerBar: View {
if VisualizerSettings.shared.enabled && VisualizerSettings.shared.miniPlayerEnabled && !showNowPlaying {
CompactVisualizerView(
isPlaying: audioPlayer.isPlaying,
isSongLoaded: audioPlayer.currentSong != nil,
accentColor: colorExtractor.isLoaded ? colorExtractor.primaryColor : accentPink,
height: VisualizerSettings.shared.miniPlayerHeight
)
@ -694,6 +695,7 @@ struct DynamicIslandView: View {
if VisualizerSettings.shared.enabled {
CompactVisualizerView(
isPlaying: audioPlayer.isPlaying,
isSongLoaded: audioPlayer.currentSong != nil,
accentColor: themeColor,
height: 32
)

View file

@ -382,7 +382,6 @@ struct NowPlayingView: View {
// MARK: - Visualizer Layer
@ViewBuilder
private func visualizerLayer(geo: GeometryProxy) -> some View {
let height = isLandscape
@ -392,7 +391,7 @@ struct NowPlayingView: View {
if visSettings.enabled && visSettings.nowPlayingEnabled {
VStack {
Spacer()
MitsuhaVisualizerView(isPlaying: audioPlayer.isPlaying, accentColor: accentPink)
MitsuhaVisualizerView(isPlaying: audioPlayer.isPlaying, isSongLoaded: audioPlayer.currentSong != nil, accentColor: accentPink)
.frame(maxWidth: .infinity)
.frame(height: height)
.allowsHitTesting(false)

View file

@ -159,6 +159,9 @@ fileprivate final class VisualizerLevelBox: ObservableObject {
struct MitsuhaVisualizerView: View {
var previewLevels: [Float]? = nil
let isPlaying: Bool
/// When false (song gap between tracks), hold the wave steady at its current
/// opacity so it doesn't snap to idle amplitude and create a visible "lift".
var isSongLoaded: Bool = true
let accentColor: Color
var compact: Bool = false
@ -203,8 +206,13 @@ struct MitsuhaVisualizerView: View {
}
}
}
.opacity(isPlaying ? 1.0 : 0.35)
.animation(.easeInOut(duration: 0.6), value: isPlaying)
// Only animate opacity changes when a song is loaded.
// During a song transition, isPlaying briefly flips falsetrue which
// would fade the wave to 0.35, snap it to idle, then fade back up
// producing the visible "lift". Holding opacity steady during the gap
// prevents this.
.opacity(isPlaying ? 1.0 : (isSongLoaded ? 0.35 : 1.0))
.animation(isSongLoaded ? .easeInOut(duration: 0.6) : nil, value: isPlaying)
.onAppear {
let cached = compact ? WaveStateCache.shared.compactLevels : []
box.displayLevels = cached.isEmpty
@ -229,9 +237,10 @@ struct MitsuhaVisualizerView: View {
// MARK: - Temporal Smoothing & Log Binning
private func updateDisplayLevels(newRawLevels: [Float]) {
@discardableResult
private func updateDisplayLevels(newRawLevels: [Float]) -> Bool {
let count = settings.numberOfPoints
guard count > 0, !newRawLevels.isEmpty else { return }
guard count > 0, !newRawLevels.isEmpty else { return false }
let sens = Float(settings.sensitivity)
let isPreProcessed = AudioPlayer.shared.isUsingOfflineVis
@ -318,6 +327,7 @@ struct MitsuhaVisualizerView: View {
// Cache compact levels so DI morph picks up current wave shape
if compact { WaveStateCache.shared.compactLevels = box.displayLevels }
return true
}
// MARK: - Colors
@ -574,12 +584,14 @@ struct MitsuhaVisualizerView: View {
// MARK: - Compact Visualizer (for mini player)
struct CompactVisualizerView: View {
let isPlaying: Bool
var isSongLoaded: Bool = true
let accentColor: Color
let height: CGFloat
var body: some View {
MitsuhaVisualizerView(
isPlaying: isPlaying,
isSongLoaded: isSongLoaded,
accentColor: accentColor,
compact: true
)