Skip to content
Snippets Groups Projects
BackupConfigViewModel.swift 3.91 KiB
Newer Older
import UIKit
import Models
import Shared
import Combine
import Foundation
import DependencyInjection
import HUD

enum BackupActionState {
    case backupFinished
    case backupAllowed(Bool)
    case backupInProgress(Float, Float)
}

struct BackupConfigViewModel {
    var didTapBackupNow: () -> Void
    var didChooseWifiOnly: (Bool) -> Void
    var didChooseAutomatic: (Bool) -> Void
Ahmed Shehata's avatar
Ahmed Shehata committed
    var didToggleService: (UIViewController, CloudService, Bool) -> Void
    var didTapService: (CloudService, UIViewController) -> Void

    var wifiOnly: () -> AnyPublisher<Bool, Never>
    var automatic: () -> AnyPublisher<Bool, Never>
    var lastBackup: () -> AnyPublisher<Backup?, Never>
    var actionState: () -> AnyPublisher<BackupActionState, Never>
    var enabledService: () -> AnyPublisher<CloudService?, Never>
    var connectedServices: () -> AnyPublisher<Set<CloudService>, Never>
}

extension BackupConfigViewModel {
    static func live() -> Self {
        class Context {
Bruno Muniz's avatar
Bruno Muniz committed
            @Dependency var hud: HUD
            @Dependency var service: BackupService
Ahmed Shehata's avatar
Ahmed Shehata committed
            @Dependency var coordinator: BackupCoordinating
        }

        let context = Context()

        return .init(
            didTapBackupNow: {
                context.service.performBackup()
Bruno Muniz's avatar
Bruno Muniz committed
                context.hud.update(with: .on)
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
                    context.hud.update(with: .none)
                }
            },
            didChooseWifiOnly: context.service.setBackupOnlyOnWifi(_:),
            didChooseAutomatic: context.service.setBackupAutomatically(_:),
Ahmed Shehata's avatar
Ahmed Shehata committed
            didToggleService: { controller, service, enabling in
                guard enabling == true else {
                    context.service.toggle(service: service, enabling: enabling)
                    return
                }

                context.coordinator.toPassphrase(from: controller, cancelClosure: {
                    context.service.toggle(service: service, enabling: false)
                }, passphraseClosure: { passphrase in
                    context.service.passphrase = passphrase
Bruno Muniz's avatar
Bruno Muniz committed
                    context.hud.update(with: .onTitle("Initializing and securing your backup file will take few seconds, please keep the app open."))
Ahmed Shehata's avatar
Ahmed Shehata committed
                    DispatchQueue.global().async {
                        context.service.toggle(service: service, enabling: enabling)

                        DispatchQueue.main.async {
                            context.hud.update(with: .none)
                        }
                    }
                })
            },
            didTapService: context.service.authorize,
            wifiOnly: {
                context.service.settingsPublisher
                    .map(\.wifiOnlyBackup)
                    .eraseToAnyPublisher()
            },
            automatic: {
                context.service.settingsPublisher
                    .map(\.automaticBackups)
                    .eraseToAnyPublisher()
            },
            lastBackup: {
                context.service.settingsPublisher
                    .map {
                        guard let enabledService = $0.enabledService else { return nil }
                        return $0.backups[enabledService]
                    }.eraseToAnyPublisher()
            },
            actionState: {
                context.service.settingsPublisher
                    .map(\.enabledService)
                    .map { BackupActionState.backupAllowed($0 != nil) }
                    .eraseToAnyPublisher()
            },
            enabledService: {
                context.service.settingsPublisher
                    .map(\.enabledService)
                    .eraseToAnyPublisher()
            },
            connectedServices: {
                context.service.settingsPublisher
                    .map(\.connectedServices)
                    .removeDuplicates()
                    .eraseToAnyPublisher()
            }
        )
    }
}