experiment(PodcastPlayerView): add playbackSpeed control (0.75×/1×/1.25×/1.5×/2×) with menu

This commit is contained in:
Krishna Kumar
2026-05-23 00:51:23 -05:00
parent be4a4c3a5f
commit f7d5c129fc

View File

@@ -42,6 +42,9 @@ final class PodcastPlayerViewModel {
var duration: Double = 1 var duration: Double = 1
var currentArticleUrl: String = "" var currentArticleUrl: String = ""
var currentArticleTitle: String = "" var currentArticleTitle: String = ""
var playbackSpeed: Float = 1.0
static let availableSpeeds: [Float] = [0.75, 1.0, 1.25, 1.5, 2.0]
var isGenerating: Bool { var isGenerating: Bool {
switch phase { switch phase {
@@ -135,7 +138,11 @@ final class PodcastPlayerViewModel {
func togglePlayPause() { func togglePlayPause() {
guard let player else { return } guard let player else { return }
if isPlaying { player.pause() } else { player.play() } if isPlaying {
player.pause()
} else {
player.rate = playbackSpeed
}
isPlaying.toggle() isPlaying.toggle()
updateNowPlaying() updateNowPlaying()
} }
@@ -154,6 +161,12 @@ final class PodcastPlayerViewModel {
seek(to: max(currentTime - 15, 0)) seek(to: max(currentTime - 15, 0))
} }
func setPlaybackSpeed(_ speed: Float) {
playbackSpeed = speed
if isPlaying { player?.rate = speed }
updateNowPlaying()
}
private func setupPlayer(url: URL, title: String) { private func setupPlayer(url: URL, title: String) {
currentPodcastTitle = title currentPodcastTitle = title
@@ -205,7 +218,7 @@ final class PodcastPlayerViewModel {
setupRemoteCommands() setupRemoteCommands()
phase = .ready(title: title) phase = .ready(title: title)
updateNowPlaying() updateNowPlaying()
p.play() p.rate = playbackSpeed
isPlaying = true isPlaying = true
} }
@@ -384,6 +397,29 @@ struct PodcastPlayerView: View {
.foregroundStyle(.primary) .foregroundStyle(.primary)
} }
} }
Menu {
ForEach(PodcastPlayerViewModel.availableSpeeds, id: \.self) { speed in
Button {
vm.setPlaybackSpeed(speed)
} label: {
let label = speed == 1.0 ? "1× (Normal)" : "\(String(format: "%g", speed))×"
if speed == vm.playbackSpeed {
Label(label, systemImage: "checkmark")
} else {
Text(label)
}
}
}
} label: {
Text(vm.playbackSpeed == 1.0 ? "1× Speed" : "\(String(format: "%g", vm.playbackSpeed))×")
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(.secondary)
.padding(.horizontal, 14)
.padding(.vertical, 7)
.background(Color(.systemGray5))
.clipShape(Capsule())
}
} }
} }