Newer
Older
import UIKit
import Models
import Shared
import Combine
import DependencyInjection
final class BackupConfigController: UIViewController {
@Dependency private var coordinator: BackupCoordinating
lazy private var screenView = BackupConfigView()
private let viewModel: BackupConfigViewModel
private var cancellables = Set<AnyCancellable>()
private var drawerCancellables = Set<AnyCancellable>()
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
private var wifiOnly = false
private var manualBackups = false
private var serviceName: String = ""
override func loadView() {
view = screenView
}
init(_ viewModel: BackupConfigViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) { nil }
override func viewDidLoad() {
super.viewDidLoad()
setupBindings()
}
private func setupBindings() {
viewModel.actionState()
.receive(on: DispatchQueue.main)
.sink { [unowned self] in screenView.actionView.setState($0) }
.store(in: &cancellables)
viewModel.connectedServices()
.receive(on: DispatchQueue.main)
.sink { [unowned self] in decorate(connectedServices: $0) }
.store(in: &cancellables)
viewModel.enabledService()
.receive(on: DispatchQueue.main)
.sink { [unowned self] in decorate(enabledService: $0) }
.store(in: &cancellables)
viewModel.automatic()
.receive(on: DispatchQueue.main)
.sink { [unowned self] in
screenView.frequencyDetailView.subtitleLabel.text = $0 ? "Automatic" : "Manual"
manualBackups = !$0
}.store(in: &cancellables)
viewModel.wifiOnly()
.receive(on: DispatchQueue.main)
.sink { [unowned self] in
screenView.infrastructureDetailView.subtitleLabel.text = $0 ? "Wi-Fi Only" : "Wi-Fi and Cellular"
wifiOnly = $0
}.store(in: &cancellables)
viewModel.lastBackup()
.receive(on: DispatchQueue.main)
.sink { [unowned self] in
guard let backup = $0 else {
screenView.latestBackupDetailView.subtitleLabel.text = "Never"
return
}
screenView.latestBackupDetailView.subtitleLabel.text = backup.date.backupStyle()
}.store(in: &cancellables)
screenView.actionView.backupNowButton
.publisher(for: .touchUpInside)
.sink { [unowned self] in viewModel.didTapBackupNow() }
.store(in: &cancellables)
screenView.frequencyDetailView
.publisher(for: .touchUpInside)
.sink { [unowned self] in presentFrequencyDrawer(manual: manualBackups) }
.store(in: &cancellables)
screenView.infrastructureDetailView
.publisher(for: .touchUpInside)
.sink { [unowned self] in presentInfrastructureDrawer(wifiOnly: wifiOnly) }
.store(in: &cancellables)
screenView.googleDriveButton
.publisher(for: .touchUpInside)
.sink { [unowned self] in viewModel.didTapService(.drive, self) }
.store(in: &cancellables)
screenView.googleDriveButton.switcherView
.publisher(for: .valueChanged)
.sink { [unowned self] in viewModel.didToggleService(self, .drive, screenView.googleDriveButton.switcherView.isOn) }
.store(in: &cancellables)
screenView.dropboxButton.switcherView
.publisher(for: .valueChanged)
.sink { [unowned self] in viewModel.didToggleService(self, .dropbox, screenView.dropboxButton.switcherView.isOn) }
screenView.sftpButton.switcherView
.publisher(for: .valueChanged)
.sink { [unowned self] in viewModel.didToggleService(self, .sftp, screenView.sftpButton.switcherView.isOn) }
.store(in: &cancellables)
screenView.iCloudButton.switcherView
.publisher(for: .valueChanged)
.sink { [unowned self] in viewModel.didToggleService(self, .icloud, screenView.iCloudButton.switcherView.isOn) }
.store(in: &cancellables)
screenView.dropboxButton
.publisher(for: .touchUpInside)
.sink { [unowned self] in viewModel.didTapService(.dropbox, self) }
.store(in: &cancellables)
screenView.sftpButton
.publisher(for: .touchUpInside)
.sink { [unowned self] in viewModel.didTapService(.sftp, self) }
screenView.iCloudButton
.publisher(for: .touchUpInside)
.sink { [unowned self] in viewModel.didTapService(.icloud, self) }
.store(in: &cancellables)
}
private func decorate(enabledService: CloudService?) {
var button: BackupSwitcherButton?
switch enabledService {
case .none:
break
case .icloud:
button = screenView.iCloudButton
case .dropbox:
button = screenView.dropboxButton
case .drive:
case .sftp:
serviceName = Localized.Backup.sftp
button = screenView.sftpButton
}
screenView.enabledSubtitleLabel.text
= Localized.Backup.Config.disclaimer(serviceName)
screenView.frequencyDetailView.titleLabel.text
= Localized.Backup.Config.frequency(serviceName).uppercased()
guard let button = button else {
screenView.iCloudButton.isHidden = false
screenView.dropboxButton.isHidden = false
screenView.googleDriveButton.isHidden = false
screenView.iCloudButton.switcherView.isOn = false
screenView.dropboxButton.switcherView.isOn = false
screenView.googleDriveButton.switcherView.isOn = false
screenView.frequencyDetailView.isHidden = true
screenView.enabledSubtitleView.isHidden = true
screenView.latestBackupDetailView.isHidden = true
screenView.infrastructureDetailView.isHidden = true
return
}
screenView.frequencyDetailView.isHidden = false
screenView.enabledSubtitleView.isHidden = false
screenView.latestBackupDetailView.isHidden = false
screenView.infrastructureDetailView.isHidden = false
[screenView.iCloudButton,
screenView.dropboxButton,
screenView.googleDriveButton,
screenView.sftpButton].forEach {
$0.isHidden = $0 != button
$0.switcherView.isOn = $0 == button
}
}
private func decorate(connectedServices: Set<CloudService>) {
if connectedServices.contains(.icloud) {
screenView.iCloudButton.showSwitcher(enabled: false)
} else {
screenView.iCloudButton.showChevron()
}
if connectedServices.contains(.dropbox) {
screenView.dropboxButton.showSwitcher(enabled: false)
} else {
screenView.dropboxButton.showChevron()
}
if connectedServices.contains(.drive) {
screenView.googleDriveButton.showSwitcher(enabled: false)
} else {
screenView.googleDriveButton.showChevron()
}
if connectedServices.contains(.sftp) {
screenView.sftpButton.showSwitcher(enabled: false)
} else {
screenView.sftpButton.showChevron()
}
private func presentInfrastructureDrawer(wifiOnly: Bool) {
let cancelButton = DrawerCapsuleButton(model: .init(
title: Localized.ChatList.Dashboard.cancel,
style: .seeThrough
))
let wifiOnlyButton = DrawerRadio(
title: "Wi-Fi Only",
isSelected: wifiOnly
)
let wifiAndCellularButton = DrawerRadio(
title: "Wi-Fi and Cellular",
isSelected: !wifiOnly,
spacingAfter: 40
)
let drawer = DrawerController(with: [
DrawerText(
font: Fonts.Mulish.extraBold.font(size: 28.0),
text: Localized.Backup.Config.infrastructure,
color: Asset.neutralActive.color,
alignment: .left,
spacingAfter: 30
),
wifiOnlyButton,
wifiAndCellularButton,
])
wifiOnlyButton.action
.sink { [unowned self] in
viewModel.didChooseWifiOnly(true)
drawer.dismiss(animated: true) { [weak self] in
self?.drawerCancellables.removeAll()
wifiAndCellularButton.action
.sink { [unowned self] in
viewModel.didChooseWifiOnly(false)
drawer.dismiss(animated: true) { [weak self] in
self?.drawerCancellables.removeAll()
drawer.dismiss(animated: true) { [weak self] in
self?.drawerCancellables.removeAll()
coordinator.toDrawer(drawer, from: self)
private func presentFrequencyDrawer(manual: Bool) {
let cancelButton = DrawerCapsuleButton(model: .init(
title: Localized.ChatList.Dashboard.cancel,
style: .seeThrough
))
let manualButton = DrawerRadio(
title: "Manual",
isSelected: manual
)
let automaticButton = DrawerRadio(
title: "Automatic",
isSelected: !manual,
spacingAfter: 40
)
let drawer = DrawerController(with: [
DrawerText(
font: Fonts.Mulish.extraBold.font(size: 28.0),
text: Localized.Backup.Config.frequency(serviceName),
color: Asset.neutralActive.color,
alignment: .left,
spacingAfter: 30
),
manualButton,
automaticButton,
])
manualButton.action
.sink { [unowned self] in
viewModel.didChooseAutomatic(false)
drawer.dismiss(animated: true) { [weak self] in
self?.drawerCancellables.removeAll()
automaticButton.action
.sink { [unowned self] in
viewModel.didChooseAutomatic(true)
drawer.dismiss(animated: true) { [weak self] in
self?.drawerCancellables.removeAll()
drawer.dismiss(animated: true) { [weak self] in
self?.drawerCancellables.removeAll()
coordinator.toDrawer(drawer, from: self)