feat: add playback loading state
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1540"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F138396B2C51BABD00B4814F"
|
||||
BuildableName = "InfinifiIOS.app"
|
||||
BlueprintName = "InfinifiIOS"
|
||||
ReferencedContainer = "container:InfinifiIOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F138396B2C51BABD00B4814F"
|
||||
BuildableName = "InfinifiIOS.app"
|
||||
BlueprintName = "InfinifiIOS"
|
||||
ReferencedContainer = "container:InfinifiIOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F138396B2C51BABD00B4814F"
|
||||
BuildableName = "InfinifiIOS.app"
|
||||
BlueprintName = "InfinifiIOS"
|
||||
ReferencedContainer = "container:InfinifiIOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>InfinifiIOS.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@@ -10,6 +10,8 @@ struct ContentView: View {
|
||||
playbackManager.stop()
|
||||
case .paused:
|
||||
playbackManager.nextTrack()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +19,7 @@ struct ContentView: View {
|
||||
let buttonImageName = switch playbackManager.playbackState {
|
||||
case .paused: "play"
|
||||
case .playing: "pause"
|
||||
case .loading: "dot.square"
|
||||
}
|
||||
|
||||
VStack(alignment: .center) {
|
||||
|
@@ -4,8 +4,10 @@ import Foundation
|
||||
enum PlaybackState {
|
||||
case playing
|
||||
case paused
|
||||
case loading
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class PlaybackManager: ObservableObject {
|
||||
@Published var playbackState: PlaybackState = .paused
|
||||
@Published var hasError = false
|
||||
@@ -13,20 +15,37 @@ class PlaybackManager: ObservableObject {
|
||||
private var audioPlayer = AVPlayer()
|
||||
|
||||
func nextTrack() {
|
||||
let now = Date().timeIntervalSince1970
|
||||
// add timestamp to the url to prevent caching
|
||||
let playerItem = AVPlayerItem(url: URL(string: "https://infinifi.cafe/current.mp3?t=\(now)")!)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(playbackFinished), name: AVPlayerItem.didPlayToEndTimeNotification, object: playerItem)
|
||||
|
||||
audioPlayer.replaceCurrentItem(with: playerItem)
|
||||
audioPlayer.play()
|
||||
|
||||
playbackState = .loading
|
||||
Task {
|
||||
try await loadCurrentTrack()
|
||||
playbackState = .playing
|
||||
}
|
||||
}
|
||||
|
||||
func stop() {
|
||||
audioPlayer.pause()
|
||||
playbackState = .paused
|
||||
audioPlayer.pause()
|
||||
}
|
||||
|
||||
private nonisolated func loadCurrentTrack() async throws {
|
||||
let now = Date().timeIntervalSince1970
|
||||
guard let url = URL(string: "https://infinifi.cafe/current.mp3?t=\(now)") else {
|
||||
return
|
||||
}
|
||||
|
||||
// add timestamp to the url to prevent caching
|
||||
let asset = AVAsset(url: url)
|
||||
let isPlayable = try await asset.load(.isPlayable)
|
||||
guard isPlayable else {
|
||||
return
|
||||
}
|
||||
|
||||
let playerItem = AVPlayerItem(asset: asset)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(playbackFinished), name: AVPlayerItem.didPlayToEndTimeNotification, object: playerItem)
|
||||
|
||||
await audioPlayer.replaceCurrentItem(with: playerItem)
|
||||
await audioPlayer.play()
|
||||
}
|
||||
|
||||
@objc
|
||||
|
Reference in New Issue
Block a user