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

Bruno Muniz's avatar
Bruno Muniz committed
import SFTPFeature
import iCloudFeature
import DropboxFeature
import GoogleDriveFeature

final class RestoreListViewModel {
Bruno Muniz's avatar
Bruno Muniz committed
    @Dependency private var sftpService: SFTPService
Bruno Muniz's avatar
Bruno Muniz committed
    @Dependency private var icloudService: iCloudInterface
    @Dependency private var dropboxService: DropboxInterface
    @Dependency private var googleDriveService: GoogleDriveInterface
Bruno Muniz's avatar
Bruno Muniz committed
    var hudPublisher: AnyPublisher<HUDStatus, Never> {
        hudSubject.eraseToAnyPublisher()
    }
Bruno Muniz's avatar
Bruno Muniz committed
    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)
Bruno Muniz's avatar
Bruno Muniz committed
        case .sftp:
Bruno Muniz's avatar
Bruno Muniz committed
            didRequestSFTPAuthorization(from: parent)
Bruno Muniz's avatar
Bruno Muniz committed
    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) {
Bruno Muniz's avatar
Bruno Muniz committed
        googleDriveService.authorize(presenting: controller) { authResult in
            switch authResult {
            case .success:
Ahmed Shehata's avatar
Ahmed Shehata committed
                self.hudSubject.send(.on(nil))
Bruno Muniz's avatar
Bruno Muniz committed
                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() {
Bruno Muniz's avatar
Bruno Muniz committed
        if icloudService.isAuthorized() {
Ahmed Shehata's avatar
Ahmed Shehata committed
            self.hudSubject.send(.on(nil))
Bruno Muniz's avatar
Bruno Muniz committed
            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
            ///
Bruno Muniz's avatar
Bruno Muniz committed
            icloudService.openSettings()
        }
    }

    private func didRequestDropboxAuthorization(from controller: UIViewController) {
Bruno Muniz's avatar
Bruno Muniz committed
        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 }

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