import HUD import UIKit import Models import Shared import Combine import BackupFeature import DependencyInjection import SFTPFeature import iCloudFeature import DropboxFeature import GoogleDriveFeature final class RestoreListViewModel { @Dependency private var sftpService: SFTPService @Dependency private var icloudService: iCloudInterface @Dependency private var dropboxService: DropboxInterface @Dependency private var googleDriveService: GoogleDriveInterface var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() } var backupPublisher: AnyPublisher<RestoreSettings, Never> { backupSubject.eraseToAnyPublisher() } private var dropboxAuthCancellable: AnyCancellable? private let hudSubject = PassthroughSubject<HUDStatus, Never>() private let backupSubject = PassthroughSubject<RestoreSettings, Never>() func didTapCloud(_ cloudService: CloudService, from parent: UIViewController) { switch cloudService { case .drive: didRequestDriveAuthorization(from: parent) case .icloud: didRequestICloudAuthorization() case .dropbox: didRequestDropboxAuthorization(from: parent) case .sftp: didRequestSFTPAuthorization(from: parent) } } private func didRequestSFTPAuthorization(from controller: UIViewController) { let params = SFTPAuthorizationParams(controller, { [weak self] in guard let self = self else { return } controller.navigationController?.popViewController(animated: true) self.hudSubject.send(.on(nil)) self.sftpService.fetchMetadata{ result in switch result { case .success(let settings): self.hudSubject.send(.none) if let settings = settings { self.backupSubject.send(settings) } else { self.backupSubject.send(.init(cloudService: .sftp)) } case .failure(let error): self.hudSubject.send(.error(.init(with: error))) } } }) sftpService.authorizeFlow(params) } private func didRequestDriveAuthorization(from controller: UIViewController) { googleDriveService.authorize(presenting: controller) { authResult in switch authResult { case .success: self.hudSubject.send(.on(nil)) self.googleDriveService.downloadMetadata { downloadResult in switch downloadResult { case .success(let metadata): var backup: Backup? if let metadata = metadata { backup = .init(id: metadata.identifier, date: metadata.modifiedDate, size: metadata.size) } self.hudSubject.send(.none) self.backupSubject.send(RestoreSettings(backup: backup, cloudService: .drive)) case .failure(let error): self.hudSubject.send(.error(.init(with: error))) } } case .failure(let error): self.hudSubject.send(.error(.init(with: error))) } } } private func didRequestICloudAuthorization() { if icloudService.isAuthorized() { self.hudSubject.send(.on(nil)) icloudService.downloadMetadata { result in switch result { case .success(let metadata): var backup: Backup? if let metadata = metadata { backup = .init(id: metadata.path, date: metadata.modifiedDate, size: metadata.size) } self.hudSubject.send(.none) self.backupSubject.send(RestoreSettings(backup: backup, cloudService: .icloud)) case .failure(let error): self.hudSubject.send(.error(.init(with: error))) } } } else { /// This could be an alert controller asking if user wants to enable/deeplink /// icloudService.openSettings() } } private func didRequestDropboxAuthorization(from controller: UIViewController) { dropboxAuthCancellable = dropboxService.authorize(presenting: controller) .receive(on: DispatchQueue.main) .sink { [unowned self] authResult in switch authResult { case .success(let bool): guard bool == true else { return } self.hudSubject.send(.on(nil)) dropboxService.downloadMetadata { metadataResult in switch metadataResult { case .success(let metadata): var backup: Backup? if let metadata = metadata { backup = .init(id: metadata.path, date: metadata.modifiedDate, size: metadata.size) } self.hudSubject.send(.none) self.backupSubject.send(RestoreSettings(backup: backup, cloudService: .dropbox)) case .failure(let error): self.hudSubject.send(.error(.init(with: error))) } } case .failure(let error): self.hudSubject.send(.error(.init(with: error))) } } } }