From 758d7a5ebd8493393dd955d551132901bdea68de Mon Sep 17 00:00:00 2001 From: Dallas Groot Date: Sat, 11 Apr 2026 16:31:24 -0700 Subject: [PATCH] quick fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NowPlayingView.swift — The _radioProgressBarImpl stub I left as a “reference” comment block was still compiled by Swift and referenced isDraggingSlider, dragPosition, and playbackTime which no longer exist on NowPlayingView. Removed the entire stub. Also transportControls had one remaining playbackTime reference — replaced with audioPlayer.currentTime directly since transport controls genuinely need the current position for the timeshift enable/disable logic and don’t cause a body re-eval issue there. NavidromeWatchApp.swift — syncLibrary() is declared async not async throws, so try? was redundant. Removed it. --- iOS/Views/NowPlaying/NowPlayingView.swift | 100 +--------------------- watchOS/App/NavidromeWatchApp.swift | 2 +- 2 files changed, 2 insertions(+), 100 deletions(-) diff --git a/iOS/Views/NowPlaying/NowPlayingView.swift b/iOS/Views/NowPlaying/NowPlayingView.swift index cc29de7..cdca188 100644 --- a/iOS/Views/NowPlaying/NowPlayingView.swift +++ b/iOS/Views/NowPlaying/NowPlayingView.swift @@ -821,104 +821,6 @@ struct NowPlayingView: View { NowPlayingSeekBar(audioPlayer: audioPlayer, radioBuffer: radioBuffer, accentColor: accentPink) } - // Radio progress bar implementation moved into NowPlayingSeekBar to keep - // currentTime reads scoped to the child view. This stub preserved for reference. - private var _radioProgressBarImpl: some View { - VStack(spacing: 6) { - if radioBuffer.isHLSStream { - // HLS: fully greyed, no scrubber thumb, no time labels - Capsule() - .fill(Color.white.opacity(0.08)) - .frame(height: 4) - HStack { - Text("--:--") - .font(.system(size: 11, weight: .medium)) - .foregroundColor(.gray.opacity(0.35)) - Spacer() - Text("--:--") - .font(.system(size: 11)) - .foregroundColor(.gray.opacity(0.35)) - } - } else if radioBuffer.isBuffering { - GeometryReader { geo in - let bufferSec = radioBuffer.estimatedBufferSeconds - let maxSec = radioBuffer.maxBufferDuration - let fillPct = min(max(bufferSec / maxSec, 0), 1.0) - - let playheadPct: CGFloat = { - if isDraggingSlider { return dragPosition } - if audioPlayer.isPlayingFromBuffer { - return CGFloat(min(playbackTime / maxSec, fillPct)) - } - return fillPct - }() - - ZStack(alignment: .leading) { - Capsule().fill(Color.white.opacity(0.1)).frame(height: 4) - Capsule().fill(accentPink.opacity(0.3)) - .frame(width: geo.size.width * fillPct, height: 4) - Circle() - .fill(radioBuffer.isLive ? accentPink : Color.white) - .frame(width: isDraggingSlider ? 16 : 12, - height: isDraggingSlider ? 16 : 12) - .offset(x: geo.size.width * playheadPct - (isDraggingSlider ? 8 : 6)) - .animation(.interactiveSpring(), value: isDraggingSlider) - } - .contentShape(Rectangle()) - .gesture( - DragGesture(minimumDistance: 8) - .onChanged { v in - isDraggingSlider = true - let pct = min(max(v.location.x / geo.size.width, 0), fillPct) - dragPosition = pct - } - .onEnded { v in - isDraggingSlider = false - let pct = min(max(v.location.x / geo.size.width, 0), fillPct) - let seekPos = pct * maxSec - audioPlayer.radioSeekBack(to: seekPos) - } - ) - } - .frame(height: 24) - - HStack { - if isDraggingSlider { - let dragPosSec = dragPosition * radioBuffer.maxBufferDuration - let behindLive = max(0, radioBuffer.estimatedBufferSeconds - dragPosSec) - Text(behindLive < 1 ? "LIVE" : "-" + formatTime(behindLive)) - .font(.system(size: 11, weight: .medium)) - .foregroundColor(behindLive < 1 ? accentPink : .gray) - } else if radioBuffer.isLive { - Text("LIVE") - .font(.system(size: 11, weight: .semibold)) - .foregroundColor(accentPink) - } else { - let behindLive = max(0, radioBuffer.estimatedBufferSeconds - playbackTime) - Text("-" + formatTime(behindLive)) - .font(.system(size: 11, weight: .medium)) - .foregroundColor(.gray) - } - Spacer() - Text(formatTime(radioBuffer.bufferedDuration)) - .font(.system(size: 11)) - .foregroundColor(.gray) - } - } else { - // Buffer not yet ready — greyed static bar (brief state on auto-start) - Capsule() - .fill(Color.white.opacity(0.1)) - .frame(height: 4) - HStack { - Text("Buffering...") - .font(.system(size: 11, weight: .medium)) - .foregroundColor(.gray.opacity(0.5)) - Spacer() - } - } - } - } - // MARK: - Transport Controls private var transportControls: some View { @@ -927,7 +829,7 @@ struct NowPlayingView: View { // Dynamic disable states (Feature 2) let bufferSec = radioBuffer.estimatedBufferSeconds - let currentPos: TimeInterval = audioPlayer.isPlayingFromBuffer ? playbackTime : bufferSec + let currentPos: TimeInterval = audioPlayer.isPlayingFromBuffer ? audioPlayer.currentTime : bufferSec let secondsBehindLive = bufferSec - currentPos let canRewind30 = !radioBuffer.isHLSStream && bufferSec >= 30 let canForward15 = !radioBuffer.isHLSStream && secondsBehindLive >= 15 diff --git a/watchOS/App/NavidromeWatchApp.swift b/watchOS/App/NavidromeWatchApp.swift index 4c33f84..8b35de7 100644 --- a/watchOS/App/NavidromeWatchApp.swift +++ b/watchOS/App/NavidromeWatchApp.swift @@ -48,7 +48,7 @@ class NavidromeWatchDelegate: NSObject, WKApplicationDelegate { // Opportunity for a lightweight library metadata refresh. Task { if WatchSessionManager.shared.activeServer != nil { - try? await WatchSessionManager.shared.syncLibrary() + await WatchSessionManager.shared.syncLibrary() } refreshTask.setTaskCompletedWithSnapshot(false) }