Skip to content
Snippets Groups Projects

Account recovery/backup feature

1 file
+ 74
14
Compare changes
  • Side-by-side
  • Inline
@@ -2,9 +2,12 @@ import UIKit
import Models
import Combine
import Defaults
import GoogleDriveFeature
import DependencyInjection
import iCloudFeature
import DropboxFeature
import GoogleDriveFeature
public struct BackupService {
var backup: () -> Void
public var setBackupData: (Data) -> Void
@@ -19,14 +22,16 @@ public struct BackupService {
extension BackupService {
public static func live() -> Self {
class Context {
@Dependency var drive: GoogleDriveInterface
@Dependency var icloudService: iCloudInterface
@Dependency var dropboxService: DropboxInterface
@Dependency var driveService: GoogleDriveInterface
@KeyObject(.backupSettings, defaultValue: Data()) var storedSettings: Data
lazy var settings = CurrentValueSubject<BackupSettings, Never>(.init(fromData: storedSettings))
var settingsLastRefreshedDate: Date?
private var cancellables = Set<AnyCancellable>()
var cancellables = Set<AnyCancellable>()
init() {
settings
@@ -37,7 +42,19 @@ extension BackupService {
}
func refreshConnections() {
drive.isAuthorized { [weak settings] isAuthorized in
if icloudService.isAuthorized() && !settings.value.connectedServices.contains(.icloud) {
settings.value.connectedServices.insert(.icloud)
} else if !icloudService.isAuthorized() && settings.value.connectedServices.contains(.icloud) {
settings.value.connectedServices.remove(.icloud)
}
if dropboxService.isAuthorized() && !settings.value.connectedServices.contains(.dropbox) {
settings.value.connectedServices.insert(.dropbox)
} else if !dropboxService.isAuthorized() && settings.value.connectedServices.contains(.dropbox) {
settings.value.connectedServices.remove(.dropbox)
}
driveService.isAuthorized { [weak settings] isAuthorized in
guard let settings = settings else { return }
if isAuthorized && !settings.value.connectedServices.contains(.drive) {
@@ -62,10 +79,7 @@ extension BackupService {
.appendingPathComponent("backup")
.appendingPathExtension("xxm")
guard let data = try? Data(contentsOf: fileUrl) else {
return
}
guard let data = try? Data(contentsOf: fileUrl) else { return }
performBackup(data: data)
}
@@ -86,7 +100,7 @@ extension BackupService {
switch enabledService {
case .drive:
drive.uploadBackup(url) {
driveService.uploadBackup(url) {
switch $0 {
case .success(let metadata):
self.settings.value.backups[.drive] = .init(
@@ -110,11 +124,45 @@ extension BackupService {
}
func refreshBackups() {
drive.isAuthorized { [weak settings] isAuthorized in
if icloudService.isAuthorized() {
icloudService.downloadMetadata { [weak settings] in
guard let settings = settings else { return }
guard let metadata = try? $0.get() else {
settings.value.backups[.icloud] = nil
return
}
settings.value.backups[.icloud] = Backup(
id: metadata.path,
date: metadata.modifiedDate,
size: metadata.size
)
}
}
if dropboxService.isAuthorized() {
dropboxService.downloadMetadata { [weak settings] in
guard let settings = settings else { return }
guard let metadata = try? $0.get() else {
settings.value.backups[.dropbox] = nil
return
}
settings.value.backups[.dropbox] = Backup(
id: metadata.path,
date: metadata.modifiedDate,
size: metadata.size
)
}
}
driveService.isAuthorized { [weak settings] isAuthorized in
guard let settings = settings else { return }
if isAuthorized {
self.drive.downloadMetadata {
self.driveService.downloadMetadata {
guard let metadata = try? $0.get() else { return }
settings.value.backups[.drive] = Backup(
@@ -167,14 +215,26 @@ extension BackupService {
authorize: { cloud, controller in
switch cloud {
case .drive:
context.drive.authorize(presenting: controller) { [weak context] _ in
context.driveService.authorize(presenting: controller) { [weak context] _ in
context?.refreshConnections()
context?.refreshBackups()
}
case .icloud:
print(">>>> 🟥 Backup using iCloud hasn't been implemented yet")
if !context.icloudService.isAuthorized() {
context.icloudService.openSettings()
} else {
context.refreshConnections()
context.refreshBackups()
}
case .dropbox:
print(">>>> 🟥 Backup using Dropbox hasn't been implemented yet")
if !context.dropboxService.isAuthorized() {
context.dropboxService.authorize(presenting: controller)
.sink { [weak context] _ in
guard let context = context else { return }
context.refreshConnections()
context.refreshBackups()
}.store(in: &context.cancellables)
}
}
},
settings: {
Loading