diff --git a/Delta.xcodeproj/project.pbxproj b/Delta.xcodeproj/project.pbxproj index 4f7178d..dff663f 100644 --- a/Delta.xcodeproj/project.pbxproj +++ b/Delta.xcodeproj/project.pbxproj @@ -109,6 +109,7 @@ BF9F4FD01AAD7B87004C9500 /* DeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF9F4FCE1AAD7B87004C9500 /* DeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63BDE91D389EEB00FCB040 /* GameViewController.swift */; }; BFAA1FED1B8AA4FA00495943 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFAA1FEC1B8AA4FA00495943 /* Settings.swift */; }; + BFAB9F7D219A43380080EC7D /* SyncManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFAB9F7C219A43380080EC7D /* SyncManager.swift */; }; BFAB9F88219A4B670080EC7D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = BFAB9F87219A4B670080EC7D /* GoogleService-Info.plist */; }; BFBAB2E31EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBAB2E21EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift */; }; BFC6F7B81F435BC500221B96 /* Input+Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC6F7B71F435BC500221B96 /* Input+Display.swift */; }; @@ -250,6 +251,7 @@ BF99A5961DC2F9C400468E9E /* ControllerSkinTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControllerSkinTableViewCell.swift; sourceTree = ""; }; BF9F4FCE1AAD7B87004C9500 /* DeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BFAA1FEC1B8AA4FA00495943 /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; + BFAB9F7C219A43380080EC7D /* SyncManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncManager.swift; sourceTree = ""; }; BFAB9F87219A4B670080EC7D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; BFBAB2E21EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DeltaCoreProtocol+Delta.swift"; sourceTree = ""; }; BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SNESDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -599,6 +601,14 @@ path = Settings; sourceTree = ""; }; + BFAB9F7B219A43270080EC7D /* Syncing */ = { + isa = PBXGroup; + children = ( + BFAB9F7C219A43380080EC7D /* SyncManager.swift */, + ); + path = Syncing; + sourceTree = ""; + }; BFC9B7371CEFCD08008629BB /* Cheats */ = { isa = PBXGroup; children = ( @@ -677,6 +687,7 @@ BF7AE7FA1C2E851F00B1B5BC /* Pause Menu */, BFAA1FEB1B8AA4E800495943 /* Settings */, BF59426C1E09BC450051894B /* Database */, + BFAB9F7B219A43270080EC7D /* Syncing */, BF59428C1E09BCE50051894B /* Importing */, BF930FFB1EB6D6EC00E8DBA0 /* Systems */, BF525EE61FF5F355004AA849 /* Deep Linking */, @@ -973,6 +984,7 @@ BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */, BF6866171DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift in Sources */, BF59427D1E09BC830051894B /* ControllerSkin.swift in Sources */, + BFAB9F7D219A43380080EC7D /* SyncManager.swift in Sources */, BFCEA67E1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift in Sources */, BF1173501DA32CF600047DF8 /* ControllersSettingsViewController.swift in Sources */, BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */, diff --git a/Delta/Game Selection/GamesViewController.swift b/Delta/Game Selection/GamesViewController.swift index a186c73..0da410d 100644 --- a/Delta/Game Selection/GamesViewController.swift +++ b/Delta/Game Selection/GamesViewController.swift @@ -109,6 +109,8 @@ extension GamesViewController DispatchQueue.global().async { self.activeEmulatorCore?.stop() } + + SyncManager.shared.sync() } override func didReceiveMemoryWarning() diff --git a/Delta/Launch/LaunchViewController.swift b/Delta/Launch/LaunchViewController.swift index d6aa49d..d4b7de3 100644 --- a/Delta/Launch/LaunchViewController.swift +++ b/Delta/Launch/LaunchViewController.swift @@ -18,6 +18,8 @@ class LaunchViewController: RSTLaunchViewController private var applicationLaunchDeepLinkGame: Game? + private var didAttemptStartingSyncManager = false + override var preferredStatusBarStyle: UIStatusBarStyle { return self.gameViewController?.preferredStatusBarStyle ?? .lightContent } @@ -51,8 +53,15 @@ extension LaunchViewController let isDatabaseManagerStarted = RSTLaunchCondition(condition: { DatabaseManager.shared.isStarted }) { (completionHandler) in DatabaseManager.shared.start(completionHandler: completionHandler) } - - return [isDatabaseManagerStarted, isDatabaseManagerStarted] + + let isSyncingManagerStarted = RSTLaunchCondition(condition: { self.didAttemptStartingSyncManager }) { (completionHandler) in + SyncManager.shared.start { (error) in + self.didAttemptStartingSyncManager = true + completionHandler(nil) + } + } + + return [isDatabaseManagerStarted, isSyncingManagerStarted] } override func handleLaunchError(_ error: Error) diff --git a/Delta/Settings/Syncing/SyncingServicesViewController.swift b/Delta/Settings/Syncing/SyncingServicesViewController.swift index 34917e1..f3f972c 100644 --- a/Delta/Settings/Syncing/SyncingServicesViewController.swift +++ b/Delta/Settings/Syncing/SyncingServicesViewController.swift @@ -8,6 +8,8 @@ import UIKit +import Harmony + enum SyncingService: String, CaseIterable { case none @@ -75,6 +77,13 @@ class SyncingServicesViewController: UITableViewController self.tableView.reloadSections(IndexSet(integer: Section.service.rawValue), with: .none) + if Settings.syncingService != .none && !SyncManager.shared.isAuthenticated + { + SyncManager.shared.authenticate(presentingViewController: self) { (error) in + print("Authenticated with error:", error as Any) + } + } + case .account, .signOut: break } } diff --git a/Delta/Syncing/SyncManager.swift b/Delta/Syncing/SyncManager.swift new file mode 100644 index 0000000..0d23887 --- /dev/null +++ b/Delta/Syncing/SyncManager.swift @@ -0,0 +1,87 @@ +// +// SyncManager.swift +// Delta +// +// Created by Riley Testut on 11/12/18. +// Copyright © 2018 Riley Testut. All rights reserved. +// + +import Harmony +import Harmony_Drive + +final class SyncManager +{ + static let shared = SyncManager() + + var service: Service { + return self.syncCoordinator.service + } + + private(set) var isAuthenticated = false + + private let syncCoordinator = SyncCoordinator(service: DriveService.shared, persistentContainer: DatabaseManager.shared) + + private init() + { + DriveService.shared.clientID = "457607414709-5puj6lcv779gpu3ql43e6k3smjj40dmu.apps.googleusercontent.com" + } +} + +extension SyncManager +{ + func start(completionHandler: @escaping (Error?) -> Void) + { + self.syncCoordinator.start { (result) in + do + { + _ = try result.verify() + + self.syncCoordinator.service.authenticateInBackground { (result) in + do + { + _ = try result.verify() + + self.isAuthenticated = true + } + catch let error as AuthenticationError where error.code == .noSavedCredentials + { + // Ignore + } + catch + { + return completionHandler(error) + } + + completionHandler(nil) + } + } + catch + { + completionHandler(error) + } + } + } + + func authenticate(presentingViewController: UIViewController, completionHandler: @escaping (Error?) -> Void) + { + guard !self.isAuthenticated else { return completionHandler(nil) } + + self.service.authenticate(withPresentingViewController: presentingViewController) { (result) in + switch result + { + case .success: + self.isAuthenticated = true + completionHandler(nil) + + case .failure(let error): completionHandler(error) + } + } + } + + func sync() + { + guard self.isAuthenticated else { return } + + self.syncCoordinator.sync() + } +} diff --git a/External/Harmony b/External/Harmony index 49efae9..b6541ab 160000 --- a/External/Harmony +++ b/External/Harmony @@ -1 +1 @@ -Subproject commit 49efae9be0ca1708b471191d45934dadf6278ca1 +Subproject commit b6541ab7931e6b8291387d9e5c46e47fc63cfdca