Merge pull request #1201 from omnivore-app/fix/ios-tts-player-feedback

Update UI after seeking, dont try to detect end of stream using currentTime
This commit is contained in:
Jackson Harper 2022-09-16 16:14:03 +08:00 committed by GitHub
commit 9059d6d500
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 24 deletions

View file

@ -402,15 +402,24 @@ public struct MiniPlayer: View {
}
}
var scrubbing: Bool {
switch audioController.scrubState {
case .scrubStarted:
return true
default:
return false
}
}
func onDragChanged(value: DragGesture.Value) {
if value.translation.height > 0, expanded {
if value.translation.height > 0, expanded, !scrubbing {
offset = value.translation.height
}
}
func onDragEnded(value: DragGesture.Value) {
withAnimation(.interactiveSpring()) {
if value.translation.height > minExpandedHeight {
if value.translation.height > minExpandedHeight, !scrubbing {
expanded = false
}
offset = 0

View file

@ -204,15 +204,17 @@ public class AudioController: NSObject, ObservableObject, AVAudioPlayerDelegate
if let playerItem = player?.currentItem as? SpeechPlayerItem {
if playerItem.speechItem.audioIdx == foundIdx {
playerItem.seek(to: CMTimeMakeWithSeconds(remainder, preferredTimescale: 600), completionHandler: nil)
scrubState = .reset
fireTimer()
return
}
}
// Move the playback to the found index, we should also seek a bit
// within this index, but this is probably accurate enough for now.
// Move the playback to the found index, we also seek by the remainder amount
// before moving we pause the player so playback doesnt jump to a previous spot
player?.pause()
player?.removeAllItems()
synthesizeFrom(start: foundIdx, playWhenReady: state == .playing, atOffset: remainder)
return
} else {
// There was no foundIdx, so we are probably trying to seek past the end, so
// just seek to the last possible duration.
@ -221,6 +223,9 @@ public class AudioController: NSObject, ObservableObject, AVAudioPlayerDelegate
synthesizeFrom(start: durations.count - 1, playWhenReady: state == .playing, atOffset: last)
}
}
scrubState = .reset
fireTimer()
}
@AppStorage(UserDefaultKey.textToSpeechPlaybackRate.rawValue) public var playbackRate = 1.0 {
@ -299,8 +304,7 @@ public class AudioController: NSObject, ObservableObject, AVAudioPlayerDelegate
if state == .reachedEnd {
return false
}
return
itemAudioProperties?.itemID == itemID &&
return itemAudioProperties?.itemID == itemID &&
(state == .loading || player?.currentItem == nil || player?.currentItem?.status == .unknown)
}
@ -431,7 +435,6 @@ public class AudioController: NSObject, ObservableObject, AVAudioPlayerDelegate
func startTimer() {
if timer == nil {
// Update every 100ms
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: true)
timer?.fire()
}
@ -445,13 +448,6 @@ public class AudioController: NSObject, ObservableObject, AVAudioPlayerDelegate
stop()
}
if player.items().count == 1, let currentTime = player.currentItem?.currentTime(), let duration = player.currentItem?.duration {
if currentTime >= duration {
pause()
state = .reachedEnd
}
}
if let durations = durations {
duration = durations.reduce(0, +)
durationString = formatTimeInterval(duration)
@ -465,17 +461,23 @@ public class AudioController: NSObject, ObservableObject, AVAudioPlayerDelegate
let itemElapsed = playerItem.status == .readyToPlay ? CMTimeGetSeconds(playerItem.currentTime()) : 0
timeElapsed = durationBefore(playerIndex: playerItem.speechItem.audioIdx) + itemElapsed
timeElapsedString = formatTimeInterval(timeElapsed)
if var nowPlaying = MPNowPlayingInfoCenter.default().nowPlayingInfo {
nowPlaying[MPMediaItemPropertyPlaybackDuration] = NSNumber(value: duration)
nowPlaying[MPNowPlayingInfoPropertyElapsedPlaybackTime] = NSNumber(value: timeElapsed)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlaying
}
}
case .scrubStarted:
break
case let .scrubEnded(seekTime):
timeElapsed = seekTime
timeElapsedString = formatTimeInterval(timeElapsed)
if var nowPlaying = MPNowPlayingInfoCenter.default().nowPlayingInfo {
nowPlaying[MPMediaItemPropertyPlaybackDuration] = NSNumber(value: duration)
nowPlaying[MPNowPlayingInfoPropertyElapsedPlaybackTime] = NSNumber(value: timeElapsed)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlaying
}
case .scrubStarted:
break
case let .scrubEnded(seekTime):
scrubState = .reset
timeElapsed = seekTime
}
}

View file

@ -187,7 +187,6 @@ func fetchUtterance(appEnvironment: AppEnvironment,
if let ssml = try utterance.toSSML(document: document) {
request.httpBody = ssml
print("FETCHING: ", String(decoding: ssml, as: UTF8.self))
}
for (header, value) in networker.defaultHeaders {
@ -219,7 +218,6 @@ func fetchUtterance(appEnvironment: AppEnvironment,
try audioData.write(to: tempPath)
try? FileManager.default.removeItem(at: audioPath)
try FileManager.default.moveItem(at: tempPath, to: audioPath)
print("wrote", audioData.count, "bytes to", audioPath)
} catch {
let errorMessage = "audioFetch failed. could not write MP3 data to disk"
throw BasicError.message(messageText: errorMessage)

View file

@ -74,10 +74,10 @@ public struct FeedCard: View {
Spacer()
}
}
.padding(.top, 8)
.padding(.top, 0)
}
}
.padding(.top, 10)
.padding(.top, 0)
.padding(.bottom, 8)
.frame(
minWidth: nil,