Skip to content

Commit

Permalink
Fix cloud restore logic.
Browse files Browse the repository at this point in the history
_ Add alerts for disabled icloud
  • Loading branch information
ant013 authored and ealymbaev committed Jun 1, 2023
1 parent ee38c4a commit 646ac3a
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,8 @@ extension CloudAccountBackupManager {

extension CloudAccountBackupManager {

func checkAvailable() async throws {
if iCloudUrl == nil {
throw BackupError.urlNotAvailable
}
var isAvailable: Bool {
iCloudUrl != nil
}

func save(accountType: AccountType, passphrase: String, name: String) async throws {
Expand Down
25 changes: 14 additions & 11 deletions UnstoppableWallet/UnstoppableWallet/Models/AccountType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,23 +208,26 @@ enum AccountType {

extension AccountType {

private static func split(_ string: String, separator: String) -> (String, String) {
if let index = string.firstIndex(of: Character(separator)) {
let left = String(string.prefix(upTo: index))
let right = String(string.suffix(from: string.index(after: index)))
return (left, right)
}

return (string, "")
}

static func decode(uniqueId: Data, type: Abstract) -> AccountType? {
let string = String(decoding: uniqueId, as: UTF8.self)

switch type {
case .mnemonic:
guard let index = string.firstIndex(of: Character("@")) else {
let words = string.split(separator: " ").map(String.init)
return AccountType.mnemonic(words: words, salt: "", bip39Compliant: true)
}
var words = string.prefix(upTo: index).split(separator: "&").map(String.init)
let salt = String(string.suffix(from: string.index(after: index)))
var bip39Compliant = true
let (wordsWithCompliant, salt) = split(string, separator: "@")
let (wordList, bip39CompliantString) = split(wordsWithCompliant, separator: "&")
let words = wordList.split(separator: " ").map(String.init)

if words.count == 2 {
words = words[0].split(separator: " ").map(String.init)
bip39Compliant = false
}
let bip39Compliant = bip39CompliantString.isEmpty
return AccountType.mnemonic(words: words, salt: salt, bip39Compliant: bip39Compliant)
case .evmPrivateKey:
return AccountType.evmPrivateKey(data: uniqueId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct BackupModule {
}

static func cloudViewController(account: Account) -> UIViewController {
let service = ICloudBackupTermsService(account: account)
let service = ICloudBackupTermsService(cloudAccountBackupManager: App.shared.cloudAccountBackupManager, account: account)
let viewModel = ICloudBackupTermsViewModel(service: service)
let viewController = ICloudBackupTermsViewController(viewModel: viewModel)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class BackupCloudModule {
static let minimumPassphraseLength = 8

static func backupTerms(account: Account) -> UIViewController {
let service = ICloudBackupTermsService(account: account)
let service = ICloudBackupTermsService(cloudAccountBackupManager: App.shared.cloudAccountBackupManager, account: account)
let viewModel = ICloudBackupTermsViewModel(service: service)
let controller = ICloudBackupTermsViewController(viewModel: viewModel)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import HsExtensions

class ICloudBackupTermsService {
let account: Account
let termCount = 2
let termCount = 1

private let cloudAccountBackupManager: CloudAccountBackupManager

@PostPublished private(set) var state: State = .selectedTerms(Set())

init(account: Account) {
init(cloudAccountBackupManager: CloudAccountBackupManager, account: Account) {
self.account = account
self.cloudAccountBackupManager = cloudAccountBackupManager
}

}

extension ICloudBackupTermsService {

// 1. Terms Screen
var cloudIsAvailable: Bool {
cloudAccountBackupManager.isAvailable
}

func toggleTerm(at index: Int) {
guard case .selectedTerms(var checkedIndices) = state,
index < termCount else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ class ICloudBackupTermsViewController: ThemeViewController {
}
.store(in: &cancellables)

viewModel.showModulePublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.showModule()
}
.store(in: &cancellables)

viewModel.showCloudNotAvailablePublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.showNotCloudAvailable()
}
.store(in: &cancellables)


loaded = true
reloadTable()
}
Expand All @@ -87,12 +102,19 @@ class ICloudBackupTermsViewController: ThemeViewController {
}

@objc private func onTapContinue() {
viewModel.onContinue()
}

private func showNotCloudAvailable() {
let viewController = BottomSheetModule.cloudNotAvailableController()
present(viewController, animated: true)
}

private func showModule() {
let controller = BackupCloudModule.backupName(account: viewModel.account)
navigationController?.pushViewController(controller, animated: true)
}

private func openModuleIfRequired() {}

private func reloadTable() {
if loaded {
tableView.reload(animated: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ class ICloudBackupTermsViewModel {
@Published public var viewItems = [ViewItem]()
@Published public var buttonEnabled: Bool = false

private let showCloudNotAvailableSubject = PassthroughSubject<Void, Never>()
private let showModuleSubject = PassthroughSubject<Void, Never>()

init(service: ICloudBackupTermsService) {
self.service = service

Expand Down Expand Up @@ -38,12 +41,24 @@ extension ICloudBackupTermsViewModel {
service.account
}

var showCloudNotAvailablePublisher: AnyPublisher<Void, Never> {
showCloudNotAvailableSubject.eraseToAnyPublisher()
}

var showModulePublisher: AnyPublisher<Void, Never> {
showModuleSubject.eraseToAnyPublisher()
}

func onToggle(index: Int) {
service.toggleTerm(at: index)
}

func onTapAgree() {
// service.setTermsAccepted()
func onContinue() {
if service.cloudIsAvailable {
showModuleSubject.send(())
} else {
showCloudNotAvailableSubject.send(())
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ extension BottomSheetModule {
)
}

static func cloudNotAvailableController() -> UIViewController {
BottomSheetModule.viewController(
image: .local(image: UIImage(named: "no_internet_24")?.withTintColor(.themeJacob)),
title: "settings.icloud_sync.alert.title".localized,
items: [
.highlightedDescription(text: "settings.icloud_sync.alert.description".localized)
],
buttons: [
.init(style: .yellow, title: "button.continue".localized, actionType: .afterClose),
]
)
}

}

extension BottomSheetModule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,13 @@ class RestoreCloudViewController: ThemeViewController {
self?.restore(item: $0)
}.store(in: &cancellables)

// subscribe(disposeBag, viewModel.successSignal) { [weak self] in
// HudHelper.instance.show(banner: .imported)
// (self?.returnViewController ?? self)?.dismiss(animated: true)
// }

tableView.buildSections()
}

override func viewWillAppear(_ animated: Bool) {
tableView.deselectCell(withCoordinator: transitionCoordinator, animated: animated)
}

@objc private func onCancel() {
(returnViewController ?? self)?.dismiss(animated: true)
}
Expand Down Expand Up @@ -139,8 +138,12 @@ extension RestoreCloudViewController: SectionsDataSource {

var sections = [
descriptionSection,
section(id: "not_imported", viewItems: viewModel.viewItem.notImported),
]
if !viewItem.notImported.isEmpty {
sections.append(
section(id: "not_imported", viewItems: viewModel.viewItem.notImported)
)
}

if !viewItem.imported.isEmpty {
sections.append(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ThemeKit
struct RestoreTypeModule {

static func viewController(sourceViewController: UIViewController? = nil, returnViewController: UIViewController? = nil) -> UIViewController {
let viewModel = RestoreTypeViewModel()
let viewModel = RestoreTypeViewModel(cloudAccountBackupManager: App.shared.cloudAccountBackupManager)
let viewController = RestoreTypeViewController(viewModel: viewModel, returnViewController: returnViewController)
let module = ThemeNavigationController(rootViewController: viewController)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Combine
import UIKit
import ThemeKit
import SnapKit
Expand All @@ -6,6 +7,7 @@ import ComponentKit

class RestoreTypeViewController: ThemeViewController {
private let viewModel: RestoreTypeViewModel
private var cancellables = Set<AnyCancellable>()

private let tableView = SectionsTableView(style: .grouped)
private weak var returnViewController: UIViewController?
Expand Down Expand Up @@ -42,6 +44,20 @@ class RestoreTypeViewController: ThemeViewController {

tableView.sectionDataSource = self

viewModel.showModulePublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.show(type: $0)
}
.store(in: &cancellables)

viewModel.showCloudNotAvailablePublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.showNotCloudAvailable()
}
.store(in: &cancellables)

tableView.buildSections()
}

Expand Down Expand Up @@ -102,12 +118,12 @@ class RestoreTypeViewController: ThemeViewController {
cell.set(backgroundStyle: backgroundStyle, isFirst: true, isLast: true)
},
action: { [weak self] in
self?.onTap(type: item)
self?.viewModel.onTap(type: item)
}
)
}

private func onTap(type: RestoreTypeViewModel.RestoreType) {
private func show(type: RestoreTypeViewModel.RestoreType) {
switch type {
case .cloudRestore:
let viewController = RestoreCloudModule.viewController(returnViewController: returnViewController)
Expand All @@ -118,6 +134,11 @@ class RestoreTypeViewController: ThemeViewController {
}
}

private func showNotCloudAvailable() {
let viewController = BottomSheetModule.cloudNotAvailableController()
present(viewController, animated: true)
}

}

extension RestoreTypeViewController: SectionsDataSource {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
import UIKit
import Combine

class RestoreTypeViewModel {
private let cloudAccountBackupManager: CloudAccountBackupManager

private let showCloudNotAvailableSubject = PassthroughSubject<Void, Never>()
private let showModuleSubject = PassthroughSubject<RestoreType, Never>()

init(cloudAccountBackupManager: CloudAccountBackupManager) {
self.cloudAccountBackupManager = cloudAccountBackupManager
}

}

extension RestoreTypeViewModel {

var items: [RestoreType] { RestoreType.allCases }

var showCloudNotAvailablePublisher: AnyPublisher<Void, Never> {
showCloudNotAvailableSubject.eraseToAnyPublisher()
}

var showModulePublisher: AnyPublisher<RestoreType, Never> {
showModuleSubject.eraseToAnyPublisher()
}

func onTap(type: RestoreType) {
switch type {
case .recoveryOrPrivateKey: showModuleSubject.send(type)
case .cloudRestore:
if cloudAccountBackupManager.isAvailable {
showModuleSubject.send(type)
} else {
showCloudNotAvailableSubject.send(())
}
}
}

}

extension RestoreTypeViewModel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,7 @@ Go to Settings - > Unstoppable and allow access to the camera.";
"backup.cloud.title" = "Backup to iCloud";
"backup.cloud.description" = "iCloud storage is a third-party cloud storage service provided by Apple. It's important to know that your data will be stored on Apple's servers, not on your personal devices. This means that you are entrusting your data and handing over the security of your information to a third-party service.";

"backup.cloud.terms.item.1" = "I understand that by using iCloud backup, I am transferring my data to third party storage";
"backup.cloud.terms.item.2" = "I understand that if I lose access to my iCloud, I will lose access to my wallet backup copy ";
"backup.cloud.terms.item.1" = "I understand that loosing access to my iCloud, will result in loosing access to the backup of a respective wallet.";

"backup.cloud.name.title" = "Backup Name";
"backup.cloud.name.description" = "Add a name for the recovery phrase backup to distinguish it from other backups";
Expand Down

0 comments on commit 646ac3a

Please sign in to comment.