// // OnboardingControllerManual.swift // List // // Created by Igor Danich on 22.07.2020. // Copyright © 2020 Igor Danich. All rights reserved. // import UIKit import EosioSwift class AccountControllerManual: UIViewController { @IBOutlet private weak var textField: CommonTextField! @IBOutlet private weak var submitBtn: UIButton! @IBOutlet weak var tableView: UITableView! @IBOutlet weak var containerView: CommonViewContainer! private let service = Account.Service.Manual() var privateKeyHasBeenProcessed: (() -> Void)? private var accounts = [Account.Model.Add]() private var accountsToShow = [Account.Model.Add]() override func viewDidLoad() { super.viewDidLoad() title = L10n.Account.Manual.title image = Asset.accountManualLogo.image if navigationController != nil { navigationItem.leftBarButtonItem = .pop(self, { self.dismiss(animated: true) }) navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.isTranslucent = true } tableView.showsVerticalScrollIndicator = false tableView.delegate = self tableView.dataSource = self tableView.separatorStyle = .none tableView.register(cell: SearchAccountCell.self) textField.delegate = self submitBtn.isEnabled = false } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(false, animated: true) } private func fetchPrivateKey() { Loader.show(in: self) service.fetch(privateKey: textField.value) { (error) in Loader.hide(in: self) if self.service.accounts.count == 0 { self.containerView.isHidden = true Alert.error(error) } else { self.accounts = self.service.accounts self.accountsToShow = self.accounts self.containerView.isHidden = false self.tableView.reloadData() } } } private func readQrData(string: String) { submitBtn.isEnabled = string.count > 0 textField.value = string fetchPrivateKey() } @IBAction private func onQR(_ : AnyObject?) { guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { let ctrl = ScannerViewController() ctrl.navigationItem.leftBarButtonItem = .close { [unowned self] in dismiss(animated: true) } ctrl.didCapture = { [unowned self] string in dismiss(animated: true) readQrData(string: string) } let navCtrl = UINavigationController(rootViewController: ctrl) navCtrl.modalPresentationStyle = .fullScreen present(navCtrl, animated: true) return } Alert.system( actions: [ .init(title: L10n.Wallet.Send.qrCamera, style: .default) { [unowned self] _ in let ctrl = ScannerViewController() ctrl.navigationItem.leftBarButtonItem = .close(self) ctrl.didCapture = { [unowned self]string in dismiss(animated: true) readQrData(string: string) } let navCtrl = UINavigationController(rootViewController: ctrl) navCtrl.modalPresentationStyle = .fullScreen UIViewController.topController().present(navCtrl, animated: true) }, .init(title: L10n.Wallet.Send.qrLibrary, style: .default) { [unowned self] _ in let ctrl = UIImagePickerController() ctrl.delegate = self ctrl.sourceType = .photoLibrary UIViewController.topController().present(ctrl, animated: true) } ], style: .actionSheet, in: self ) } @IBAction private func onSubmit(_ : AnyObject?) { AccountViewAuthorize.showGetPassword(in: self) { [unowned self] password in let accountsToAdd = Dictionary(grouping: accounts.filter(\.isChecked), by: { Account.KeyType.init(rawValue: $0.permission.permName) }) Loader.show(in: self) DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { for (keyType, accounts) in accountsToAdd.filter({ $0.key != nil }) { Accounts().addAccounts( usernames: accounts.map(\.username), privateKey: self.textField.value, password: password, keyType: keyType! ) { Loader.hide(in: self) Alert.error($0) } } self.dismiss(animated: true) self.privateKeyHasBeenProcessed?() } } } } extension AccountControllerManual: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return accountsToShow.count } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 52 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let header = SearchAccountView() header.parent = self header.onTextChanged = { [unowned self] text in if text.isEmpty { self.accountsToShow = self.accounts } else { self.accountsToShow = self.accounts.filter({ $0.username.starts(with: text) }) } tableView.reloadData() } header.onClearClicked = { [unowned self] in self.accountsToShow = self.accounts } return header } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { submitBtn.isEnabled = accounts.contains(where: { $0.isChecked }) let cell = tableView.dequeueReusableCell(SearchAccountCell.self, indexPath: indexPath) let account = accountsToShow[indexPath.row] cell.configureView(account: account) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let accountToChange = accountsToShow[indexPath.row] guard let index = accounts.firstIndex(where: { $0.username == accountToChange.username && $0.permission.permName == accountToChange.permission.permName }) else { return } accountsToShow[indexPath.row].isChecked = !accountsToShow[indexPath.row].isChecked accounts[index].isChecked = !accounts[index].isChecked tableView.reloadRows(at: [indexPath], with: .automatic) submitBtn.isEnabled = accounts.contains(where: { $0.isChecked }) } } extension AccountControllerManual: CommonTextFieldDelegate { func textFieldDidChange(_ textField: CommonTextField) { if textField.value.count == Constants.maxPrivateKeyTextCount { Loader.show(in: self) fetchPrivateKey() } } func textField(_ textField: CommonTextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let currentText = textField.value guard let stringRange = Range(range, in: currentText) else { return false } let updatedText = currentText.replacingCharacters(in: stringRange, with: string) let shouldChange = updatedText.count <= Constants.maxPrivateKeyTextCount return shouldChange } } extension AccountControllerManual { enum Constants { static let maxPrivateKeyTextCount = 51 } } extension AccountControllerManual: UINavigationControllerDelegate, UIImagePickerControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey:Any]) { picker.dismiss(animated: true) guard let selectedImage = info[.originalImage] as? UIImage, let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]), let ciImage = CIImage(image: selectedImage) else { return } var qrCodeLink = "" for feature in (detector.features(in: ciImage) as? [CIQRCodeFeature]) ?? [] { qrCodeLink += feature.messageString ?? "" } print(qrCodeLink)//Your result from QR Code if !qrCodeLink.isEmpty { readQrData(string: qrCodeLink) } else { Alert.error(L10n.Main.Qr.notValidError) } } }