diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/BirthdayInput/BirthdayInputViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/BirthdayInput/BirthdayInputViewController.swift index da97381b80..0c49c8ec7e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/BirthdayInput/BirthdayInputViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/BirthdayInput/BirthdayInputViewController.swift @@ -6,14 +6,11 @@ import SnapKit import MarketKit import SectionsTableView -protocol IBirthdayInputDelegate: AnyObject { - func didEnter(birthdayHeight: Int?) - func didCancelEnterBirthdayHeight() -} - class BirthdayInputViewController: KeyboardAwareViewController { private let token: Token - private weak var delegate: IBirthdayInputDelegate? + + var onEnterBirthdayHeight: ((Int?) -> ())? + var onCancel: (() -> ())? private let iconImageView = UIImageView() private let tableView = SectionsTableView(style: .grouped) @@ -28,9 +25,8 @@ class BirthdayInputViewController: KeyboardAwareViewController { private var walletType: WalletType = .new private var didTapDone = false - init(token: Token, delegate: IBirthdayInputDelegate) { + init(token: Token) { self.token = token - self.delegate = delegate super.init(scrollViews: [tableView], accessoryView: gradientWrapperView) } @@ -83,7 +79,7 @@ class BirthdayInputViewController: KeyboardAwareViewController { super.viewDidDisappear(animated) if !didTapDone { - delegate?.didCancelEnterBirthdayHeight() + onCancel?() } } @@ -128,7 +124,7 @@ class BirthdayInputViewController: KeyboardAwareViewController { } @objc private func onTapCancel() { - delegate?.didCancelEnterBirthdayHeight() + onCancel?() dismiss(animated: true) } @@ -136,10 +132,10 @@ class BirthdayInputViewController: KeyboardAwareViewController { didTapDone = true if walletType == .new { - delegate?.didEnter(birthdayHeight: nil) + onEnterBirthdayHeight?(nil) } else { let birthdayHeight = heightInputCell.inputText.flatMap { Int($0) } ?? 0 - delegate?.didEnter(birthdayHeight: birthdayHeight) + onEnterBirthdayHeight?(birthdayHeight) } dismiss(animated: true) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsService.swift index d219760528..acf1ec5497 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsService.swift @@ -63,7 +63,7 @@ extension RestoreSettingsService { manager.save(settings: settings, account: account, blockchainType: blockchainType) } - func enter(birthdayHeight: Int?, token: Token) { + @discardableResult func enter(birthdayHeight: Int?, token: Token) -> TokenWithSettings { var settings = RestoreSettings() if let birthdayHeight = birthdayHeight?.description ?? RestoreSettingType.birthdayHeight.createdAccountValue(blockchainType: token.blockchainType) { settings[.birthdayHeight] = String(birthdayHeight) @@ -71,6 +71,8 @@ extension RestoreSettingsService { let tokenWithSettings = TokenWithSettings(token: token, settings: settings) approveSettingsRelay.accept(tokenWithSettings) + + return tokenWithSettings } func cancel(token: Token) { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsView.swift index 7562fc9182..e822e92b2e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreSettings/RestoreSettingsView.swift @@ -19,20 +19,14 @@ class RestoreSettingsView { } private func showBirthdayAlert(token: Token) { - let controller = BirthdayInputViewController(token: token, delegate: self) + let controller = BirthdayInputViewController(token: token) + controller.onEnterBirthdayHeight = { [weak self] height in + self?.viewModel.onEnter(birthdayHeight: height) + } + controller.onCancel = { [weak self] in + self?.viewModel.onCancelEnterBirthdayHeight() + } onOpenController?(ThemeNavigationController(rootViewController: controller)) } } - -extension RestoreSettingsView: IBirthdayInputDelegate { - - func didEnter(birthdayHeight: Int?) { - viewModel.onEnter(birthdayHeight: birthdayHeight) - } - - func didCancelEnterBirthdayHeight() { - viewModel.onCancelEnterBirthdayHeight() - } - -} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift index 6e5dccdebd..4c283f0405 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift @@ -12,8 +12,10 @@ struct ReceiveModule { let service = ReceiveService( account: account, walletManager: App.shared.walletManager, - marketKit: App.shared.marketKit + marketKit: App.shared.marketKit, + restoreSettingsService: RestoreSettingsService(manager: App.shared.restoreSettingsManager) ) + let viewModel = ReceiveViewModel(service: service) let coinProvider = CoinProvider( diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift index 7acfc5a478..69cbba67a2 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift @@ -6,17 +6,19 @@ class ReceiveService { private let account: Account private let walletManager: WalletManager private let marketKit: MarketKit.Kit + private let restoreSettingsService: RestoreSettingsService private let showTokenSubject = PassthroughSubject() private let showBlockchainSelectSubject = PassthroughSubject<(FullCoin, AccountType), Never>() private let showDerivationSelectSubject = PassthroughSubject<[Wallet], Never>() private let showBitcoinCashCoinTypeSelectSubject = PassthroughSubject<[Wallet], Never>() - private let showZcashTypeSelectSubject = PassthroughSubject() + private let showZcashRestoreSelectSubject = PassthroughSubject() - init(account: Account, walletManager: WalletManager, marketKit: MarketKit.Kit) { + init(account: Account, walletManager: WalletManager, marketKit: MarketKit.Kit, restoreSettingsService: RestoreSettingsService) { self.account = account self.walletManager = walletManager self.marketKit = marketKit + self.restoreSettingsService = restoreSettingsService } private func showReceive(token: Token) { @@ -42,7 +44,7 @@ class ReceiveService { private func chooseTokenWithSettings(tokens: [Token]) { // all tokens will have same blockchain type - guard let blockchainType = tokens.first?.blockchainType else { + guard let first = tokens.first else { return } @@ -53,22 +55,22 @@ class ReceiveService { switch wallets.count { case 0: // create wallet and show deposit - switch blockchainType { + switch first.blockchainType { case .bitcoin, .litecoin, .bitcoinCash: - guard let defaultToken = try? marketKit.token(query: blockchainType.defaultTokenQuery) else { + guard let defaultToken = try? marketKit.token(query: first.blockchainType.defaultTokenQuery) else { return } let wallet = createWallet(token: defaultToken) showTokenSubject.send(wallet) case .zcash: - showZcashTypeSelectSubject.send() // we must enable zcash wallet and ask for birthday + showZcashRestoreSelectSubject.send(first) // we must enable zcash wallet and ask for birthday default: () } case 1: // just show deposit. When unique token and it's restored showTokenSubject.send(wallets[0]) default: // show choose derivation, addressFormat or other (when token is unique, but many wallets) - chooseTokenType(blockchainType: blockchainType, wallets: wallets) + chooseTokenType(blockchainType: first.blockchainType, wallets: wallets) } } @@ -112,8 +114,8 @@ extension ReceiveService { showBitcoinCashCoinTypeSelectSubject.eraseToAnyPublisher() } - var showZcashTypeSelectPublisher: AnyPublisher { - showZcashTypeSelectSubject.eraseToAnyPublisher() + var showZcashRestoreSelectPublisher: AnyPublisher { + showZcashRestoreSelectSubject.eraseToAnyPublisher() } var showBlockchainSelectPublisher: AnyPublisher<(FullCoin, AccountType), Never> { @@ -122,8 +124,10 @@ extension ReceiveService { func onSelect(fullCoin: FullCoin) { let eligibleTokens = fullCoin.tokens.filter { account.type.supports(token: $0) } + + let avoidSimpleShow = eligibleTokens.first { token in token.blockchainType == .zcash } != nil // For alone token check exists and show address - if eligibleTokens.count == 1 { + if eligibleTokens.count == 1, !avoidSimpleShow { showReceive(token: eligibleTokens[0]) return } @@ -141,6 +145,13 @@ extension ReceiveService { showReceive(token: token) } + func onRestoreZcash(token: Token, height: Int?) { + let tokenWithSettings = restoreSettingsService.enter(birthdayHeight: height, token: token) + + restoreSettingsService.save(settings: tokenWithSettings.settings, account: account, blockchainType: token.blockchainType) + showReceive(token: token) + } + } extension ReceiveService { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewController.swift index b86c9fd222..8bcca87680 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewController.swift @@ -36,6 +36,13 @@ class ReceiveViewController: ThemeNavigationController { } .store(in: &cancellables) + viewModel.showZcashRestoreSelectPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] token in + self?.showZcashRestoreSelect(token: token) + } + .store(in: &cancellables) + viewModel.showBlockchainSelectPublisher .receive(on: DispatchQueue.main) .sink { [weak self] (fullCoin, accountType) in @@ -69,6 +76,26 @@ class ReceiveViewController: ThemeNavigationController { pushViewController(viewController, animated: true) } + private func showZcashRestoreSelect(token: Token) { + let viewController = BottomSheetModule.viewController( + image: .remote(url: token.coin.imageUrl, placeholder: "placeholder_circle_32"), + title: token.coin.code, + subtitle: token.coin.name, + items: [ + .description(text: "deposit.zcash.restore.description".localized) + ], + buttons: [ + .init(style: .yellow, title: "deposit.zcash.restore.already_own".localized, actionType: .afterClose, action: { [weak self] in + self?.showRestoreZcash(token: token) + }), + .init(style: .gray, title: "deposit.zcash.restore.dont_have".localized, actionType: .afterClose, action: { [weak self] in + self?.viewModel.onRestoreZcash(token: token, height: nil) + }), + ]) + + present(viewController, animated: true) + } + private func showBlockchainSelect(fullCoin: FullCoin, accountType: AccountType) { let viewController = ReceiveModule.selectTokenViewController(fullCoin: fullCoin, accountType: accountType) { [weak self] token in self?.onSelectExact(token: token) @@ -76,6 +103,14 @@ class ReceiveViewController: ThemeNavigationController { pushViewController(viewController, animated: true) } + private func showRestoreZcash(token: Token) { + let viewController = BirthdayInputViewController(token: token) + viewController.onEnterBirthdayHeight = { [weak self] height in + self?.viewModel.onRestoreZcash(token: token, height: height) + } + present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + } extension ReceiveViewController { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewModel.swift index f7c3f7ee49..6fb96cb445 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveViewModel.swift @@ -21,6 +21,10 @@ extension ReceiveViewModel { service.onSelectExact(token: token) } + func onRestoreZcash(token: Token, height: Int?) { + service.onRestoreZcash(token: token, height: height) + } + } extension ReceiveViewModel { @@ -37,6 +41,10 @@ extension ReceiveViewModel { service.showBitcoinCashCoinTypeSelectPublisher } + var showZcashRestoreSelectPublisher: AnyPublisher { + service.showZcashRestoreSelectPublisher + } + var showBlockchainSelectPublisher: AnyPublisher<(FullCoin, AccountType), Never> { service.showBlockchainSelectPublisher } diff --git a/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings b/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings index 3136e89566..5e18036265 100644 --- a/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings +++ b/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings @@ -351,6 +351,10 @@ Go to Settings - > %@ and allow access to the camera."; "deposit.not_active.title" = "Not Active Address"; "deposit.not_active.tron_description" = "Newly created accounts on the TRON blockchain are inactive and cannot be queried or explored. They need to be activated.\n\nTransferring TRX or TRC-10 tokens to an inactive account address will activate the account. Activating a new account on the Tron chain requires a fee of 1 TRX"; +"deposit.zcash.restore.description" = "Have you previously owned any ZEC coins?"; +"deposit.zcash.restore.already_own" = "Yes, I already own"; +"deposit.zcash.restore.dont_have" = "No, I don’t have"; + "deposit.warning" = "Send only %@ to this address. Sending other types of tokens to this address will result in their ultimate loss."; "receive_network_select.title" = "Network";