Fix: Keep the progress indicator visible after pausing or scrubbing a voice message. (#1969)

This commit is contained in:
Nicolas Mauri
2023-10-27 17:24:22 +02:00
committed by GitHub
parent 0b31446817
commit a32a7c8f2c
12 changed files with 110 additions and 23 deletions
@@ -38,6 +38,7 @@ class AudioPlayerState: ObservableObject, Identifiable {
let waveform: EstimatedWaveform
@Published private(set) var playbackState: AudioPlayerPlaybackState
@Published private(set) var progress: Double
@Published private(set) var showProgressIndicator: Bool
private weak var audioPlayer: AudioPlayerProtocol?
private var cancellables: Set<AnyCancellable> = []
@@ -60,6 +61,7 @@ class AudioPlayerState: ObservableObject, Identifiable {
self.duration = duration
self.waveform = waveform ?? EstimatedWaveform(data: [])
self.progress = progress
showProgressIndicator = false
playbackState = .stopped
}
@@ -71,8 +73,17 @@ class AudioPlayerState: ObservableObject, Identifiable {
func updateState(progress: Double) async {
let progress = max(0.0, min(progress, 1.0))
self.progress = progress
showProgressIndicator = true
if let audioPlayer {
var shouldResumeProgressPublishing = false
if audioPlayer.state == .playing {
shouldResumeProgressPublishing = true
stopPublishProgress()
}
await audioPlayer.seek(to: progress)
if shouldResumeProgressPublishing, audioPlayer.state == .playing {
startPublishProgress()
}
}
}
@@ -86,12 +97,12 @@ class AudioPlayerState: ObservableObject, Identifiable {
}
func detachAudioPlayer() {
guard audioPlayer != nil else { return }
audioPlayer?.stop()
stopPublishProgress()
cancellables = []
audioPlayer = nil
playbackState = .stopped
showProgressIndicator = false
}
func reportError(_ error: Error) {
@@ -127,14 +138,17 @@ class AudioPlayerState: ObservableObject, Identifiable {
}
startPublishProgress()
playbackState = .playing
showProgressIndicator = true
case .didPausePlaying, .didStopPlaying, .didFinishPlaying:
stopPublishProgress()
playbackState = .stopped
if case .didFinishPlaying = action {
progress = 0.0
showProgressIndicator = false
}
case .didFailWithError:
stopPublishProgress()
playbackState = .error
}
}
@@ -322,6 +322,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
guard let playerState = mediaPlayerProvider.playerState(for: .timelineItemIdentifier(itemID)) else {
return
}
await mediaPlayerProvider.detachAllStates(except: playerState)
await playerState.updateState(progress: progress)
}
@@ -40,10 +40,6 @@ struct VoiceMessageRoomPlaybackView: View {
}
}
var showWaveformCursor: Bool {
playerState.playbackState == .playing || isDragging
}
var body: some View {
HStack {
HStack {
@@ -61,7 +57,7 @@ struct VoiceMessageRoomPlaybackView: View {
waveformView
.waveformInteraction(isDragging: $isDragging,
progress: playerState.progress,
showCursor: showWaveformCursor,
showCursor: playerState.showProgressIndicator,
onSeek: onSeek)
}
.padding(.leading, 2)
@@ -91,12 +91,15 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol {
return .failure(.previewNotAvailable)
}
if await !previewAudioPlayerState.isAttached {
await previewAudioPlayerState.attachAudioPlayer(audioPlayer)
}
if audioPlayer.url == url {
audioPlayer.play()
return .success(())
}
await previewAudioPlayerState.attachAudioPlayer(audioPlayer)
let pendingMediaSource = MediaSourceProxy(url: url, mimeType: mp4accMimeType)
audioPlayer.load(mediaSource: pendingMediaSource, using: url, autoplay: true)
return .success(())