From bf46c46fc09509e94845a5a1a6fde92dd7b2052d Mon Sep 17 00:00:00 2001 From: ronaldheft Date: Thu, 18 Aug 2022 19:31:32 -0400 Subject: [PATCH] Fix race conditions on first launch --- ios/App/App/plugins/AbsAudioPlayer.swift | 15 +++++++++++---- ios/App/App/plugins/AbsDatabase.swift | 4 ++++ ios/App/Shared/player/AudioPlayer.swift | 6 ++++++ ios/App/Shared/util/PlayerEvents.swift | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/ios/App/App/plugins/AbsAudioPlayer.swift b/ios/App/App/plugins/AbsAudioPlayer.swift index 814f39a6..9ffa975e 100644 --- a/ios/App/App/plugins/AbsAudioPlayer.swift +++ b/ios/App/App/plugins/AbsAudioPlayer.swift @@ -12,6 +12,7 @@ import RealmSwift @objc(AbsAudioPlayer) public class AbsAudioPlayer: CAPPlugin { private var initialPlayWhenReady = false + private var isUIReady = false override public func load() { NotificationCenter.default.addObserver(self, selector: #selector(sendMetadata), name: NSNotification.Name(PlayerEvents.update.rawValue), object: nil) @@ -22,15 +23,21 @@ public class AbsAudioPlayer: CAPPlugin { NotificationCenter.default.addObserver(self, selector: #selector(sendSleepTimerEnded), name: NSNotification.Name(PlayerEvents.sleepEnded.rawValue), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(onPlaybackFailed), name: NSNotification.Name(PlayerEvents.failed.rawValue), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(onLocalMediaProgressUpdate), name: NSNotification.Name(PlayerEvents.localProgress.rawValue), object: nil) - - // Restore the playack session when plugin loads - Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(restorePlaybackSession), userInfo: nil, repeats: false) + NotificationCenter.default.addObserver(self, selector: #selector(userInterfaceReady), name: NSNotification.Name(PlayerEvents.playerUserInterfaceReady.rawValue), object: nil) self.bridge?.webView?.allowsBackForwardNavigationGestures = true; } - @objc func restorePlaybackSession() { + @objc func userInterfaceReady() { + if !self.isUIReady { + NSLog("User interface is ready. Performing state restore...") + self.restorePlaybackSession() + self.isUIReady = true + } + } + + func restorePlaybackSession() { // We don't need to restore if we have an active session guard PlayerHandler.getPlaybackSession() == nil else { return } diff --git a/ios/App/App/plugins/AbsDatabase.swift b/ios/App/App/plugins/AbsDatabase.swift index a78619df..4c5cf2a4 100644 --- a/ios/App/App/plugins/AbsDatabase.swift +++ b/ios/App/App/plugins/AbsDatabase.swift @@ -155,6 +155,10 @@ public class AbsDatabase: CAPPlugin { call.reject("Failed to report synced media progress") } } + + // If we're syncing progress with the server, we also have the UI ready + // This will restore the player to the last playback session + NotificationCenter.default.post(name: NSNotification.Name(PlayerEvents.playerUserInterfaceReady.rawValue), object: nil) } @objc func syncServerMediaProgressWithLocalMediaProgress(_ call: CAPPluginCall) { diff --git a/ios/App/Shared/player/AudioPlayer.swift b/ios/App/Shared/player/AudioPlayer.swift index 3ba2da62..857fa140 100644 --- a/ios/App/Shared/player/AudioPlayer.swift +++ b/ios/App/Shared/player/AudioPlayer.swift @@ -261,6 +261,12 @@ class AudioPlayer: NSObject { } public func setPlaybackRate(_ rate: Float, observed: Bool = false) { + // Handle a race condition on first launch + guard self.status != -1 else { + NSLog("Did not set playback rate as player is not initialized") + return + } + if self.audioPlayer.rate != rate { NSLog("setPlaybakRate rate changed from \(self.audioPlayer.rate) to \(rate)") self.audioPlayer.rate = rate diff --git a/ios/App/Shared/util/PlayerEvents.swift b/ios/App/Shared/util/PlayerEvents.swift index 4b225a9e..d8bfa0d1 100644 --- a/ios/App/Shared/util/PlayerEvents.swift +++ b/ios/App/Shared/util/PlayerEvents.swift @@ -14,4 +14,5 @@ enum PlayerEvents: String { case sleepEnded = "com.audiobookshelf.app.player.sleep.ended" case failed = "com.audiobookshelf.app.player.failed" case localProgress = "com.audiobookshelf.app.player.localProgress" + case playerUserInterfaceReady = "com.audiobookshelf.app.player.playerUserInterfaceReady" }