From 8f770d08f7ec4dce6290325dd107052168b53fad Mon Sep 17 00:00:00 2001 From: Hariharan Mudaliar Date: Sun, 3 Aug 2025 22:41:52 +0530 Subject: [PATCH] Fix: Timeline Playback --- .../components/Notch/NotchHomeView.swift | 26 ++++++++++++++----- DynamicIsland/managers/MusicManager.swift | 12 ++++++++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/DynamicIsland/components/Notch/NotchHomeView.swift b/DynamicIsland/components/Notch/NotchHomeView.swift index 31a88e4..6f54dd7 100644 --- a/DynamicIsland/components/Notch/NotchHomeView.swift +++ b/DynamicIsland/components/Notch/NotchHomeView.swift @@ -137,7 +137,7 @@ struct MusicControlsView: View { } private var musicSlider: some View { - TimelineView(.animation(minimumInterval: musicManager.playbackRate > 0 ? 0.1 : nil)) { timeline in + TimelineView(.animation(minimumInterval: 0.05)) { timeline in MusicSliderView( sliderValue: $sliderValue, duration: $musicManager.songDuration, @@ -277,11 +277,25 @@ struct MusicSliderView: View { var onValueChange: (Double) -> Void var currentElapsedTime: Double { - // A small buffer is needed to ensure a meaningful difference between the two dates - guard !dragging, timestampDate.timeIntervalSince(lastDragged) > -0.0001, (timestampDate > lastUpdated || ignoreLastUpdated) else { return sliderValue } - let timeDifference = isPlaying ? currentDate.timeIntervalSince(timestampDate) : 0 - let elapsed = elapsedTime + (timeDifference * playbackRate) - return min(elapsed, duration) + // Don't update slider while user is dragging + guard !dragging else { return sliderValue } + + // If not playing, use the current elapsed time from controller + guard isPlaying else { return elapsedTime } + + // For playing media, calculate real-time progress + // Use a more permissive approach for web players + let timeDiff = currentDate.timeIntervalSince(timestampDate) + + // Only use timestamp calculation if we have recent data (within 5 seconds) + // This helps with web players that don't update timestamps frequently + if timeDiff >= 0 && timeDiff < 5.0 && playbackRate > 0 { + let projectedTime = elapsedTime + (timeDiff * playbackRate) + return min(projectedTime, duration) + } else { + // Fallback to controller-provided elapsed time for stale or invalid timestamps + return min(elapsedTime, duration) + } } var body: some View { diff --git a/DynamicIsland/managers/MusicManager.swift b/DynamicIsland/managers/MusicManager.swift index cf141ca..16bb793 100644 --- a/DynamicIsland/managers/MusicManager.swift +++ b/DynamicIsland/managers/MusicManager.swift @@ -274,7 +274,17 @@ class MusicManager: ObservableObject { self.repeatMode = state.repeatMode } - self.timestampDate = state.lastUpdated + // Update timestamp - use current time if state doesn't provide recent timestamp + let stateTimestamp = state.lastUpdated + let now = Date() + + // If the state timestamp is very recent (within 1 second), use it + // Otherwise, use current time for better real-time calculation + if abs(stateTimestamp.timeIntervalSince(now)) < 1.0 { + self.timestampDate = stateTimestamp + } else { + self.timestampDate = now + } } // Execute the batch update on the main thread