fix: preload first track to avoid ui freeze
Preload the first track to avoid ui stutter when the play button is first pressed
This commit is contained in:
@@ -20,6 +20,7 @@ struct ContentView: View {
|
|||||||
case .paused: "play"
|
case .paused: "play"
|
||||||
case .playing: "pause"
|
case .playing: "pause"
|
||||||
case .loading: "dot.square"
|
case .loading: "dot.square"
|
||||||
|
default: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
@@ -30,12 +31,14 @@ struct ContentView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
NeuButton(action: {
|
if playbackManager.playbackState != .initializing {
|
||||||
toggleAudioPlayback()
|
NeuButton(action: {
|
||||||
}) {
|
toggleAudioPlayback()
|
||||||
Image(systemName: buttonImageName)
|
}) {
|
||||||
.font(.system(size: 24))
|
Image(systemName: buttonImageName)
|
||||||
.tint(.text)
|
.font(.system(size: 24))
|
||||||
|
.tint(.text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
@@ -5,10 +5,11 @@ enum PlaybackState {
|
|||||||
case playing
|
case playing
|
||||||
case paused
|
case paused
|
||||||
case loading
|
case loading
|
||||||
|
case initializing
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlaybackManager: ObservableObject {
|
class PlaybackManager: ObservableObject {
|
||||||
@Published var playbackState: PlaybackState = .paused
|
@Published var playbackState: PlaybackState = .initializing
|
||||||
@Published var hasError = false
|
@Published var hasError = false
|
||||||
|
|
||||||
private var audioPlayer = AVPlayer()
|
private var audioPlayer = AVPlayer()
|
||||||
@@ -16,10 +17,15 @@ class PlaybackManager: ObservableObject {
|
|||||||
private var fadeOutTimer: Timer?
|
private var fadeOutTimer: Timer?
|
||||||
private var scheduledFadeOutTimer: Timer?
|
private var scheduledFadeOutTimer: Timer?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
Task { try await initialize() }
|
||||||
|
}
|
||||||
|
|
||||||
func nextTrack() {
|
func nextTrack() {
|
||||||
playbackState = .loading
|
playbackState = .loading
|
||||||
Task {
|
Task {
|
||||||
try await loadAndPlayNextTrack()
|
try await loadNextTrack()
|
||||||
|
await playCurrentTrack()
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
playbackState = .playing
|
playbackState = .playing
|
||||||
}
|
}
|
||||||
@@ -37,7 +43,15 @@ class PlaybackManager: ObservableObject {
|
|||||||
audioPlayer.pause()
|
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
|
let now = Date().timeIntervalSince1970
|
||||||
guard let url = URL(string: "https://infinifi.cafe/current.mp3?t=\(now)") else {
|
guard let url = URL(string: "https://infinifi.cafe/current.mp3?t=\(now)") else {
|
||||||
return
|
return
|
||||||
@@ -56,8 +70,10 @@ class PlaybackManager: ObservableObject {
|
|||||||
audioPlayer.volume = 0.0
|
audioPlayer.volume = 0.0
|
||||||
|
|
||||||
audioPlayer.replaceCurrentItem(with: playerItem)
|
audioPlayer.replaceCurrentItem(with: playerItem)
|
||||||
await audioPlayer.play()
|
}
|
||||||
|
|
||||||
|
private nonisolated func playCurrentTrack() async {
|
||||||
|
await audioPlayer.play()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.fadeInAudio()
|
self.fadeInAudio()
|
||||||
self.scheduledFadeOutTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) { _ in
|
self.scheduledFadeOutTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) { _ in
|
||||||
|
Reference in New Issue
Block a user