Skip to content
Snippets Groups Projects
RestoreListViewModel.swift 4.41 KiB
Newer Older
import HUD
import UIKit
import Models
import Shared
import Combine
import BackupFeature
import DependencyInjection

import iCloudFeature
import DropboxFeature
import GoogleDriveFeature

final class RestoreListViewModel {
    @Dependency private var icloud: iCloudInterface
    @Dependency private var dropbox: DropboxInterface
    @Dependency private var drive: GoogleDriveInterface

    var hud: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() }
    var didFetchBackup: 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)
        }
    }

    private func didRequestDriveAuthorization(from controller: UIViewController) {
        drive.authorize(presenting: controller) { authResult in
            switch authResult {
            case .success:
Ahmed Shehata's avatar
Ahmed Shehata committed
                self.hudSubject.send(.on(nil))
                self.drive.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 icloud.isAuthorized() {
Ahmed Shehata's avatar
Ahmed Shehata committed
            self.hudSubject.send(.on(nil))

            icloud.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
            ///
            icloud.openSettings()
        }
    }

    private func didRequestDropboxAuthorization(from controller: UIViewController) {
        dropboxAuthCancellable = dropbox.authorize(presenting: controller)
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] authResult in
                switch authResult {
                case .success(let bool):
                    guard bool == true else { return }

Ahmed Shehata's avatar
Ahmed Shehata committed
                    self.hudSubject.send(.on(nil))
                    dropbox.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)))
                }
            }
    }
}