From 062a2179463f799c21fc37507fff7debbaa4d152 Mon Sep 17 00:00:00 2001 From: ronaldheft Date: Fri, 19 Aug 2022 22:15:06 -0400 Subject: [PATCH] Fix more edge cases on player initialization --- ios/App/App.xcodeproj/project.pbxproj | 4 ++ ios/App/App/plugins/AbsAudioPlayer.swift | 8 +-- ios/App/Shared/player/PlayerHandler.swift | 30 +--------- ios/App/Shared/player/PlayerProgress.swift | 69 ++++++++++++++++++++++ ios/App/Shared/util/ApiClient.swift | 14 +++-- 5 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 ios/App/Shared/player/PlayerProgress.swift diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 1a0f41f2..2b6c149a 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ E9D5507128AC1EC700C746DD /* DownloadItemPart.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D5507028AC1EC700C746DD /* DownloadItemPart.swift */; }; E9D5507328AC218300C746DD /* DaoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D5507228AC218300C746DD /* DaoExtensions.swift */; }; E9D5507528AEF93100C746DD /* PlayerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D5507428AEF93100C746DD /* PlayerSettings.swift */; }; + E9E985F828B02D9400957F23 /* PlayerProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E985F728B02D9400957F23 /* PlayerProgress.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -116,6 +117,7 @@ E9D5507028AC1EC700C746DD /* DownloadItemPart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadItemPart.swift; sourceTree = ""; }; E9D5507228AC218300C746DD /* DaoExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DaoExtensions.swift; sourceTree = ""; }; E9D5507428AEF93100C746DD /* PlayerSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSettings.swift; sourceTree = ""; }; + E9E985F728B02D9400957F23 /* PlayerProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerProgress.swift; sourceTree = ""; }; FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -144,6 +146,7 @@ children = ( 3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */, 3ABF618E2804325C0070250E /* PlayerHandler.swift */, + E9E985F728B02D9400957F23 /* PlayerProgress.swift */, ); path = player; sourceTree = ""; @@ -419,6 +422,7 @@ 3AF1970E2806E3CA0096F747 /* AbsAudioPlayer.swift in Sources */, E9D5506F28AC1E8E00C746DD /* DownloadItem.swift in Sources */, 3AD4FCE928043FD7006DB301 /* ServerConnectionConfig.swift in Sources */, + E9E985F828B02D9400957F23 /* PlayerProgress.swift in Sources */, E9D5505E28AC1C8500C746DD /* MediaProgress.swift in Sources */, 3A200C1527D64D7E00CBF02E /* AudioPlayer.swift in Sources */, E9D5507128AC1EC700C746DD /* DownloadItemPart.swift in Sources */, diff --git a/ios/App/App/plugins/AbsAudioPlayer.swift b/ios/App/App/plugins/AbsAudioPlayer.swift index 7272d3bf..6cd8b2e4 100644 --- a/ios/App/App/plugins/AbsAudioPlayer.swift +++ b/ios/App/App/plugins/AbsAudioPlayer.swift @@ -29,19 +29,19 @@ public class AbsAudioPlayer: CAPPlugin { } @objc func onReady(_ call: CAPPluginCall) { - self.restorePlaybackSession() + Task { await self.restorePlaybackSession() } } - func restorePlaybackSession() { + func restorePlaybackSession() async { // We don't need to restore if we have an active session guard PlayerHandler.getPlaybackSession() == nil else { return } do { // Fetch the most recent active session - let activeSession = try Realm().objects(PlaybackSession.self).where({ $0.isActiveSession == true }).last + let activeSession = try await Realm().objects(PlaybackSession.self).where({ $0.isActiveSession == true }).last if let activeSession = activeSession { + await PlayerProgress.syncLocalFromServer() try self.startPlaybackSession(activeSession, playWhenReady: false, playbackRate: PlayerSettings.main().playbackRate) - //PlayerHandler.syncServerProgressDuringPause() } } catch { NSLog("Failed to restore playback session") diff --git a/ios/App/Shared/player/PlayerHandler.swift b/ios/App/Shared/player/PlayerHandler.swift index 2a0c0395..87752fff 100644 --- a/ios/App/Shared/player/PlayerHandler.swift +++ b/ios/App/Shared/player/PlayerHandler.swift @@ -297,33 +297,7 @@ class PlayerHandler { } } - @objc public static func syncServerProgressDuringPause() { - guard Connectivity.isConnectedToInternet else { return } - DispatchQueue.global(qos: .utility).async { - NSLog("checkCurrentSessionProgress: Checking if local media progress was updated on server") - guard let session = getPlaybackSession() else { return } - let sessionRef = ThreadSafeReference(to: session) - - ApiClient.getMediaProgress(libraryItemId: session.libraryItemId!, episodeId: session.episodeId) { progress in - guard let session = try! Realm().resolve(sessionRef) else { return } - guard let progress = progress else { return } - - let serverLastUpdate = progress.lastUpdate - guard let localLastUpdate = session.updatedAt else { return } - let serverCurrentTime = progress.currentTime - let localCurrentTime = session.currentTime - - let serverIsNewerThanLocal = serverLastUpdate > localLastUpdate - let currentTimeIsDifferent = serverCurrentTime != localCurrentTime - - if serverIsNewerThanLocal && currentTimeIsDifferent { - session.update { - session.currentTime = serverCurrentTime - session.updatedAt = serverLastUpdate - } - self.seek(amount: session.currentTime) - } - } - } + @objc private static func syncServerProgressDuringPause() { + Task { await PlayerProgress.syncLocalFromServer() } } } diff --git a/ios/App/Shared/player/PlayerProgress.swift b/ios/App/Shared/player/PlayerProgress.swift new file mode 100644 index 00000000..9266bf61 --- /dev/null +++ b/ios/App/Shared/player/PlayerProgress.swift @@ -0,0 +1,69 @@ +// +// PlayerProgressSync.swift +// App +// +// Created by Ron Heft on 8/19/22. +// + +import Foundation +import UIKit +import RealmSwift + +class PlayerProgress { + + private init() {} + + public static func syncLocalFromPlayer() async { + + } + + public static func syncServerFromLocal() async { + + } + + public static func syncLocalFromServer() async { + let backgroundToken = await UIApplication.shared.beginBackgroundTask(withName: "ABS:updateLocalSessionFromServerMediaProgress") + await updateLocalSessionFromServerMediaProgress() + await UIApplication.shared.endBackgroundTask(backgroundToken) + } + + private static func updateLocalSessionFromActivePlayer() { + + } + + private static func updateLocalMediaProgressFromLocalSession() { + + } + + private static func updateServerSessionFromLocalSession() { + + } + + private static func updateLocalSessionFromServerMediaProgress() async { + NSLog("checkCurrentSessionProgress: Checking if local media progress was updated on server") + guard let session = PlayerHandler.getPlaybackSession() else { return } + + // Fetch the current progress + let progress = await ApiClient.getMediaProgress(libraryItemId: session.libraryItemId!, episodeId: session.episodeId) + guard let progress = progress else { return } + + // Determine which session is newer + let serverLastUpdate = progress.lastUpdate + guard let localLastUpdate = session.updatedAt else { return } + let serverCurrentTime = progress.currentTime + let localCurrentTime = session.currentTime + + let serverIsNewerThanLocal = serverLastUpdate > localLastUpdate + let currentTimeIsDifferent = serverCurrentTime != localCurrentTime + + // Update the session, if needed + if serverIsNewerThanLocal && currentTimeIsDifferent { + session.update { + session.currentTime = serverCurrentTime + session.updatedAt = serverLastUpdate + } + PlayerHandler.seek(amount: session.currentTime) + } + } + +} diff --git a/ios/App/Shared/util/ApiClient.swift b/ios/App/Shared/util/ApiClient.swift index 143a5f78..ad8be8b0 100644 --- a/ios/App/Shared/util/ApiClient.swift +++ b/ios/App/Shared/util/ApiClient.swift @@ -106,6 +106,14 @@ class ApiClient { } } + public static func getResource(endpoint: String, decodable: T.Type = T.self) async -> T? { + return await withCheckedContinuation { continuation in + getResource(endpoint: endpoint, decodable: decodable) { result in + continuation.resume(returning: result) + } + } + } + public static func getResource(endpoint: String, decodable: T.Type = T.self, callback: ((_ param: T?) -> Void)?) { if (Store.serverConfig == nil) { NSLog("Server config not set") @@ -205,12 +213,10 @@ class ApiClient { } } - public static func getMediaProgress(libraryItemId: String, episodeId: String?, callback: @escaping (_ progress: MediaProgress?) -> Void) { + public static func getMediaProgress(libraryItemId: String, episodeId: String?) async -> MediaProgress? { NSLog("getMediaProgress \(libraryItemId) \(episodeId ?? "NIL")") let endpoint = episodeId?.isEmpty ?? true ? "api/me/progress/\(libraryItemId)" : "api/me/progress/\(libraryItemId)/\(episodeId ?? "")" - getResource(endpoint: endpoint, decodable: MediaProgress.self) { obj in - callback(obj) - } + return await getResource(endpoint: endpoint, decodable: MediaProgress.self) } public static func getLibraryItemWithProgress(libraryItemId:String, episodeId:String?, callback: @escaping (_ param: LibraryItem?) -> Void) {