diff --git a/ZWallet/Infrastructure/IocContainer.swift b/ZWallet/Infrastructure/IocContainer.swift index 9943340..dc37c5e 100644 --- a/ZWallet/Infrastructure/IocContainer.swift +++ b/ZWallet/Infrastructure/IocContainer.swift @@ -14,6 +14,7 @@ internal protocol IocContainerProtocol { var localizer: Localizable { get } var viewFactory: ViewFactoryProtocol { get } var trxHistoryProvider: TrxHistoryProviderProtocol { get } + var paymentParser: PaymentParserProtocol { get } } @@ -32,4 +33,8 @@ internal class IocContainer: IocContainerProtocol { public lazy var trxHistoryProvider: TrxHistoryProviderProtocol = { return TrxHistoryProvider() }() + + public lazy var paymentParser: PaymentParserProtocol = { + return PaymentParser() + }() } diff --git a/ZWallet/Infrastructure/de.lproj/InfoPlist.strings b/ZWallet/Infrastructure/de.lproj/InfoPlist.strings index 6e1bd8b..775fb10 100644 --- a/ZWallet/Infrastructure/de.lproj/InfoPlist.strings +++ b/ZWallet/Infrastructure/de.lproj/InfoPlist.strings @@ -104,3 +104,19 @@ "global.yesterday" = "Gestern"; +"recipientAddress.pasteboard.empty.title" = "Pasteboard"; + +"recipientAddress.pasteboard.empty.message" = "Das Pasteboard ist leer."; + +"global.targetAddress" = "Ziel-Adresse"; + +"global.amount" = "Betrag"; + +"global.memo" = "Memo"; + +"recipientAddress.pasteboard.correct.title" = "Pasteboard"; + +"recipientAddress.pasteboard.correct.take" = "Übernehmen"; + +"global.cancel" = "Abbrechen"; + diff --git a/ZWallet/Infrastructure/en.lproj/InfoPlist.strings b/ZWallet/Infrastructure/en.lproj/InfoPlist.strings index f3f09ee..2ebd595 100644 --- a/ZWallet/Infrastructure/en.lproj/InfoPlist.strings +++ b/ZWallet/Infrastructure/en.lproj/InfoPlist.strings @@ -104,3 +104,19 @@ "global.yesterday" = "Yesterday"; +"recipientAddress.pasteboard.empty.title" = "Pasteboard"; + +"recipientAddress.pasteboard.empty.message" = "The pasteboard is empty."; + +"global.targetAddress" = "Target Address"; + +"global.amount" = "Amount"; + +"global.memo" = "Memo"; + +"recipientAddress.pasteboard.correct.title" = "Pasteboard"; + +"recipientAddress.pasteboard.correct.take" = "Take"; + +"global.cancel" = "Cancel"; + diff --git a/ZWallet/Services/PaymentParser.swift b/ZWallet/Services/PaymentParser.swift new file mode 100644 index 0000000..4adcc41 --- /dev/null +++ b/ZWallet/Services/PaymentParser.swift @@ -0,0 +1,30 @@ +// +// PaymentParser.swift +// ZWallet +// +// Created by loj on 12.04.19. +// Copyright © 2019 XMR Systems LLC. All rights reserved. +// + +import Foundation + + +internal protocol PaymentParserProtocol { + func process(uri: String) -> Result +} + + +internal class PaymentParser: PaymentParserProtocol { + + func process(uri: String) -> Result { + #warning("implement parsing of ZEC URI") + + let payment = Payment() + payment.amount = 2208_000_000_000 + payment.targetAddress = "target.22of8.ch" + payment.memo = uri + return .success(payment) + +// return .failure(.badUri) + } +} diff --git a/ZWallet/Types/InvalidPaymentUri.swift b/ZWallet/Types/InvalidPaymentUri.swift new file mode 100644 index 0000000..ffd151e --- /dev/null +++ b/ZWallet/Types/InvalidPaymentUri.swift @@ -0,0 +1,14 @@ +// +// InvalidPaymentUri.swift +// ZWallet +// +// Created by loj on 12.04.19. +// Copyright © 2019 XMR Systems LLC. All rights reserved. +// + +import Foundation + + +internal enum InvalidPaymentError: Error { + case badUri +} diff --git a/ZWallet/ViewCoordinators/SendCoordinator.swift b/ZWallet/ViewCoordinators/SendCoordinator.swift index 8f7e78f..d0d1ee2 100644 --- a/ZWallet/ViewCoordinators/SendCoordinator.swift +++ b/ZWallet/ViewCoordinators/SendCoordinator.swift @@ -18,6 +18,7 @@ internal class SendCoordinator: BaseCoordinator { private var viewFactory: ViewFactoryProtocol private var localizer: Localizable + private var paymentParser: PaymentParserProtocol private var payment: PaymentProtocol @@ -28,6 +29,7 @@ internal class SendCoordinator: BaseCoordinator { self.viewFactory = self.iocContainer.viewFactory self.localizer = self.iocContainer.localizer + self.paymentParser = self.iocContainer.paymentParser self.payment = Payment() @@ -50,13 +52,30 @@ extension SendCoordinator: RecipientAddressDelegate { } func recipientAddressVCPasteFromClipboardButtonTouched(sender: RecipientAddressVC) { + guard let pasteboardContent = UIPasteboard.general.string else { + let alert = UIAlertController(title: self.localizer.localized("recipientAddress.pasteboard.empty.title"), + message: self.localizer.localized("recipientAddress.pasteboard.empty.message"), + preferredStyle: .alert) + alert.addAction(UIAlertAction(title: self.localizer.localized("global.Ok"), style: .default, handler: nil)) + sender.present(alert, animated: true, completion: nil) + return + } + + let result = self.paymentParser.process(uri: pasteboardContent) + switch result { + case .success(let payment): + self.showPasteboardResult(payment: payment, on: sender) + case .failure: + self.showPasteboardError(on: sender) + } + #warning("implement check and store") } func recipientAddressVCEnterManuallyButtonTouched(sender: RecipientAddressVC) { #warning("implement check and store") - let viewModel = AmountVCViewModel(mode: .new, + let viewModel = AmountVCViewModel(mode: .new(initialAmount: self.payment.amount ?? 0), availableAmount: 2208_000_000_000) #warning("set correct available amount") self.showAmountView(with: viewModel) @@ -76,6 +95,37 @@ extension SendCoordinator: RecipientAddressDelegate { vc.localizer = self.localizer self.navigationController.pushViewController(vc, animated: true) } + + private func showPasteboardResult(payment: PaymentProtocol, on viewController: UIViewController) { + guard let walletAddress = payment.targetAddress else { return } + var message = "\(self.localizer.localized("global.targetAddress")): \(walletAddress)" + + if let amount = payment.amount { + message.append("\n\n\(self.localizer.localized("global.amount")): \(amount.formatted())") + } + + if let memo = payment.memo { + message.append("\n\n\(self.localizer.localized("global.memo")): \(memo)") + } + + let alert = UIAlertController(title: self.localizer.localized("recipientAddress.pasteboard.correct.title"), + message: message, + preferredStyle: .alert) + alert.addAction(UIAlertAction(title: self.localizer.localized("recipientAddress.pasteboard.correct.take"), + style: .default, handler: { _ in + self.payment = payment + let viewModel = AmountVCViewModel(mode: .new(initialAmount: self.payment.amount ?? 0), + availableAmount: 2208_000_000_000) + #warning("set correct available amount") + self.showAmountView(with: viewModel) + })) + alert.addAction(UIAlertAction(title: self.localizer.localized("global.cancel"), style: .cancel, handler: nil)) + viewController.present(alert, animated: true, completion: nil) + } + + private func showPasteboardError(on viewController: UIViewController) { + + } } @@ -84,7 +134,7 @@ extension SendCoordinator: ScanVCDelegate { func scanVCDelegateUriDetected(uri: String, sender: ScanVC) { #warning("implement check and store") - let viewModel = AmountVCViewModel(mode: .new, + let viewModel = AmountVCViewModel(mode: .new(initialAmount: self.payment.amount ?? 0), availableAmount: 2208_000_000_000) #warning("set correct available amount") self.showAmountView(with: viewModel) @@ -104,7 +154,7 @@ extension SendCoordinator: AmountVCDelegate { func amountVCDelegateNextButtonTouched(sender: AmountVC, amount: ZecInAtomicUnits) { self.payment.amount = amount - let viewModel = MemoVCViewModel(mode: .new) + let viewModel = MemoVCViewModel(mode: .new(initialMemo: self.payment.memo)) self.showMemoView(with: viewModel) } diff --git a/ZWallet/Views/Amount/AmountVC.swift b/ZWallet/Views/Amount/AmountVC.swift index 7492bb1..2d7be25 100644 --- a/ZWallet/Views/Amount/AmountVC.swift +++ b/ZWallet/Views/Amount/AmountVC.swift @@ -34,6 +34,7 @@ class AmountVC: UIViewController { guard let zec = ZecInAtomicUnits(from: s) else { return } guard let mode = self.viewModel?.mode else { return } + #warning("have only one callback method, provide mode, coordinator must decide") switch mode { case .new: self.delegate?.amountVCDelegateNextButtonTouched(sender: self, amount: zec) @@ -81,9 +82,9 @@ class AmountVC: UIViewController { if let mode = self.viewModel?.mode { switch mode { - case .new: + case .new(let initialAmount): self.titleLabel.text = localizer.localized("amount.title") - self.amountTextField.text = "0" + self.amountTextField.text = self.formatted(amount: initialAmount) self.nextButton.setTitle(localizer.localized("amount.next"), for: .normal) self.backButton.isHidden = false self.progressBar.isHidden = false diff --git a/ZWallet/Views/Amount/AmountVCViewModel.swift b/ZWallet/Views/Amount/AmountVCViewModel.swift index ac53d63..39318af 100644 --- a/ZWallet/Views/Amount/AmountVCViewModel.swift +++ b/ZWallet/Views/Amount/AmountVCViewModel.swift @@ -10,7 +10,7 @@ import Foundation internal enum AmountVCMode { - case new + case new(initialAmount: ZecInAtomicUnits) case edit(amount: ZecInAtomicUnits) } diff --git a/ZWallet/Views/Memo/MemoVC.swift b/ZWallet/Views/Memo/MemoVC.swift index 1e44700..b2a239a 100644 --- a/ZWallet/Views/Memo/MemoVC.swift +++ b/ZWallet/Views/Memo/MemoVC.swift @@ -25,7 +25,8 @@ class MemoVC: UIViewController { let memo = self.memoTextField.text guard let mode = self.viewModel?.mode else { return } - switch mode { + #warning("have only one callback method, provide mode, coordinator must decide") + switch mode { case .new: self.delegate?.memoVCDelegateNextButtonTouched(sender: self, memo: memo) case .edit(_): @@ -71,9 +72,9 @@ class MemoVC: UIViewController { if let mode = self.viewModel?.mode { switch mode { - case .new: + case .new(let initialMemo): self.titleLabel.text = localizer.localized("memo.title") - self.memoTextField.text = "" + self.memoTextField.text = initialMemo self.nextButton.setTitle(localizer.localized("memo.next"), for: .normal) self.backButton.isHidden = false self.progressBar.isHidden = false diff --git a/ZWallet/Views/Memo/MemoVCViewModel.swift b/ZWallet/Views/Memo/MemoVCViewModel.swift index c29c5f0..2ed6b4a 100644 --- a/ZWallet/Views/Memo/MemoVCViewModel.swift +++ b/ZWallet/Views/Memo/MemoVCViewModel.swift @@ -10,7 +10,7 @@ import Foundation internal enum MemoVCMode { - case new + case new(initialMemo: String?) case edit(memo: String?) }