// // OnBoardingWalletController.swift // Malinka // // Created by Juraldinio on 11/29/22. // Copyright © 2022 NUT.Tech. All rights reserved. // import Foundation import UIKit import WalletKit import WalletFoundation final class OnBoardingWalletController: UIViewController { typealias Completion = () -> Void private let group = DispatchGroup() private let loadingGroup = DispatchGroup() private var causeVersion: String? private var causeRequiredLinks: String? private let service = OnBoardingService(environment: ApplicationEnvironment.shared()) private let loader = CommonViewLoading() override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = .systemBackground self.group.notify(queue: DispatchQueue.main) { self.loader.hide() } Task { self.loadingGroup.enter() if ApplicationEnvironment.shared().current.hyperions.count == 0 { defer { self.loadingGroup.leave() } do { try await self.service.loadNodes() try await self.service.loadVersion() await self.service.loadAppSettings(nodes: ApplicationEnvironment.shared().current.nodes) try await self.service.loadHyperions() } catch let OnBoardingService.ServiceError.nodes(cause: cause) { self.causeRequiredLinks = cause } catch let OnBoardingService.ServiceError.version(cause: cause) { self.causeVersion = cause } catch let OnBoardingService.ServiceError.hyperions(cause: cause) { self.causeRequiredLinks = cause } } } } func showPin(completion: @escaping Completion) { self.showEnvironmentAlert { [weak self] in guard let self else { return } let isPinPwdMode = UserDefaults.standard.bool(forKey: "isPinPwdMode") if !Account.Service.isPasswordExists || !isPinPwdMode { Account.Service.isAccountMigrated = true self.showPinController(completion: completion) } else if Account.Service.isPasswordExists, isPinPwdMode { if (Account.Service.Authorize.shared.password ?? "").isEmpty { if self.presentedViewController != nil { self.dismiss(animated: false, completion: { AccountViewAuthorize.showGetPassword(in: self, viewModel: self.createPinViewModel(completion: completion), showPinBackButton: false, { self.initVillage(with: $0) // Accounts().migrateAccountIfNeeded(password: $0) self.group.notify(queue: DispatchQueue.main) { completion() } }) }) } else { AccountViewAuthorize.showGetPassword(in: self, viewModel: self.createPinViewModel(completion: completion), showPinBackButton: false, { self.initVillage(with: $0) // Accounts().migrateAccountIfNeeded(password: $0) self.group.notify(queue: DispatchQueue.main) { completion() } }) } } else { AccountViewAuthorize.showGetPassword(in: self, viewModel: self.createPinViewModel(completion: completion), showPinBackButton: false, { self.initVillage(with: $0) // Accounts().migrateAccountIfNeeded(password: $0) self.group.notify(queue: DispatchQueue.main) { completion() } }) } } } } // MARK: - Private private func showPinController(completion: @escaping Completion) { let controller = WalletPinController.instantiate(viewModel: self.createPinViewModel(completion: completion)) controller.modalPresentationStyle = .fullScreen controller.isModalInPresentation = true self.present(controller, animated: false) } private func createPinViewModel(completion: @escaping Completion) -> OnBoardingWalletPinViewModel { let viewModel = OnBoardingWalletPinViewModel() viewModel.updatePasswordHandler = { [weak self] in self?.initVillage(with: $0) } viewModel.dismissControllerHandler = { [weak self] controller, isPinCleared in controller.dismiss(animated: true) { if !isPinCleared { self?.group.notify(queue: DispatchQueue.main) { completion() } } else { self?.showPinController(completion: completion) } } } return viewModel } private func initVillage(with password: String) { self.loader.show(in: self.view) self.group.enter() Task { let record = ApplicationEnvironment.shared().current let village = try Village.get(with: record.networkEnvironment()) guard let device = try? await village.device() else { throw NSError() } let bank = try village.getBank(with: password, on: device) Account.Service.shared = Account.Service(using: bank) self.loadingGroup.notify(queue: DispatchQueue.main) { if let cause = self.causeRequiredLinks { Alert.error(text: cause, delay: 1.0) } else if let cause = self.causeVersion { let action = UIAlertAction(title: L10n.Main.WrongVersion.updateButton, style: .default) { _ in URL(string: "itms-apps://apple.com/app/id\(Bundle.main.appId)") >>- { UIApplication.shared.open($0) } } self.loader.hide() Alert.system(text: cause, actions: [action]) } Wallet.Service.Tokens.shared.balances.fetch { _ in P2P.Service.fetch { [weak self] in self?.loader.hide() self?.group.leave() } } } } } private func showEnvironmentAlert(_ completion: @escaping () -> Void) { let current = ApplicationEnvironment.shared().current if !current.isProduction { let version = "\(Bundle.main.major).\(Bundle.main.minor).\(Bundle.main.patch) (\(Bundle.main.buildNumber))" let alert = UIAlertController(title: "Environment \(version)", message: "Usernames: \(current.usernames.name)\nBackend: \(current.backend.name)\nOther: \(current.other.name)\nSmarts: \(current.smarts.name)", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Ok", style: .destructive, handler: {(_: UIAlertAction!) in alert.dismiss(animated: true) completion() })) self.present(alert, animated: true) } else { completion() } } }