From 352f5f01cfe1404a6df91d9c44272c3e4c2ef352 Mon Sep 17 00:00:00 2001 From: Kenneth Date: Sun, 28 Jul 2024 17:31:05 +0100 Subject: [PATCH] fix: preload first track to avoid ui freeze Preload the first track to avoid ui stutter when the play button is first pressed --- InfinifiIOS/ContentView.swift | 15 +++++++++------ InfinifiIOS/PlaybackManager.swift | 24 ++++++++++++++++++++---- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/InfinifiIOS/ContentView.swift b/InfinifiIOS/ContentView.swift index 1b15073..6833add 100644 --- a/InfinifiIOS/ContentView.swift +++ b/InfinifiIOS/ContentView.swift @@ -20,6 +20,7 @@ struct ContentView: View { case .paused: "play" case .playing: "pause" case .loading: "dot.square" + default: "" } VStack(alignment: .center) { @@ -30,12 +31,14 @@ struct ContentView: View { Spacer() - NeuButton(action: { - toggleAudioPlayback() - }) { - Image(systemName: buttonImageName) - .font(.system(size: 24)) - .tint(.text) + if playbackManager.playbackState != .initializing { + NeuButton(action: { + toggleAudioPlayback() + }) { + Image(systemName: buttonImageName) + .font(.system(size: 24)) + .tint(.text) + } } Spacer() diff --git a/InfinifiIOS/PlaybackManager.swift b/InfinifiIOS/PlaybackManager.swift index 12d7fd9..24abbf4 100644 --- a/InfinifiIOS/PlaybackManager.swift +++ b/InfinifiIOS/PlaybackManager.swift @@ -5,10 +5,11 @@ enum PlaybackState { case playing case paused case loading + case initializing } class PlaybackManager: ObservableObject { - @Published var playbackState: PlaybackState = .paused + @Published var playbackState: PlaybackState = .initializing @Published var hasError = false private var audioPlayer = AVPlayer() @@ -16,10 +17,15 @@ class PlaybackManager: ObservableObject { private var fadeOutTimer: Timer? private var scheduledFadeOutTimer: Timer? + init() { + Task { try await initialize() } + } + func nextTrack() { playbackState = .loading Task { - try await loadAndPlayNextTrack() + try await loadNextTrack() + await playCurrentTrack() await MainActor.run { playbackState = .playing } @@ -37,7 +43,15 @@ class PlaybackManager: ObservableObject { audioPlayer.pause() } - private nonisolated func loadAndPlayNextTrack() async throws { + private func initialize() async throws { + try await loadNextTrack() + + await MainActor.run { + playbackState = .paused + } + } + + private nonisolated func loadNextTrack() async throws { let now = Date().timeIntervalSince1970 guard let url = URL(string: "https://infinifi.cafe/current.mp3?t=\(now)") else { return @@ -56,8 +70,10 @@ class PlaybackManager: ObservableObject { audioPlayer.volume = 0.0 audioPlayer.replaceCurrentItem(with: playerItem) - await audioPlayer.play() + } + private nonisolated func playCurrentTrack() async { + await audioPlayer.play() DispatchQueue.main.async { self.fadeInAudio() self.scheduledFadeOutTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) { _ in