From 535f29a49c9af0c27fd191f6e1d45306846efa10 Mon Sep 17 00:00:00 2001 From: StephenHeaps <5314553+StephenHeaps@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:20:16 -0500 Subject: [PATCH] Fix brave/brave-ios#8357: Disable button to create wallet when wallet is already being created (brave/brave-ios#8358) Disable `Continue` button when already creating/restoring a wallet during create wallet / restore wallet to prevent double taps. --- .../Crypto/Onboarding/CreateWalletView.swift | 9 ++++-- .../Crypto/Onboarding/RestoreWalletView.swift | 2 +- .../Crypto/Stores/KeyringStore.swift | 30 ++++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Sources/BraveWallet/Crypto/Onboarding/CreateWalletView.swift b/Sources/BraveWallet/Crypto/Onboarding/CreateWalletView.swift index 06013ace4622..88c4fc48f16e 100644 --- a/Sources/BraveWallet/Crypto/Onboarding/CreateWalletView.swift +++ b/Sources/BraveWallet/Crypto/Onboarding/CreateWalletView.swift @@ -78,7 +78,7 @@ private struct CreateWalletView: View { } } else { keyringStore.createWallet(password: password) { mnemonic in - if !mnemonic.isEmpty { + if let mnemonic, !mnemonic.isEmpty { isNewWalletCreated = true } } @@ -144,6 +144,11 @@ private struct CreateWalletView: View { ) .hidden(isHidden: error == nil) } + + private var isContinueDisabled: Bool { + validationError != nil || password.isEmpty || repeatedPassword.isEmpty || + keyringStore.isCreatingWallet || keyringStore.isRestoringWallet + } var body: some View { VStack(spacing: 16) { @@ -200,7 +205,7 @@ private struct CreateWalletView: View { .frame(maxWidth: .infinity) } .buttonStyle(BraveFilledButtonStyle(size: .large)) - .disabled(validationError != nil || password.isEmpty || repeatedPassword.isEmpty) + .disabled(isContinueDisabled) .padding(.top, 60) } .padding(.horizontal, 20) diff --git a/Sources/BraveWallet/Crypto/Onboarding/RestoreWalletView.swift b/Sources/BraveWallet/Crypto/Onboarding/RestoreWalletView.swift index fbd12b2d6713..7f20c43f5807 100644 --- a/Sources/BraveWallet/Crypto/Onboarding/RestoreWalletView.swift +++ b/Sources/BraveWallet/Crypto/Onboarding/RestoreWalletView.swift @@ -46,7 +46,7 @@ private struct RestoreWalletView: View { } private var isContinueDisabled: Bool { - !recoveryWords.allSatisfy({ !$0.isEmpty }) + !recoveryWords.allSatisfy({ !$0.isEmpty }) || keyringStore.isRestoringWallet } private var errorLabel: some View { diff --git a/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift b/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift index 3892de1abb49..ff9fe66e9bc1 100644 --- a/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift +++ b/Sources/BraveWallet/Crypto/Stores/KeyringStore.swift @@ -164,11 +164,14 @@ public class KeyringStore: ObservableObject, WalletObserverStore { public var origin: URLOrigin? /// If this KeyringStore instance is creating a wallet. - /// This flag is used to know when to dismiss onboarding when multiple windows are visible. - private var isCreatingWallet = false + /// Note: Flag is reset prior to onboarding completion step. + @Published var isCreatingWallet = false /// If this KeyringStore instance is restoring a wallet. + /// Note: Flag is reset prior to onboarding completion step. + @Published var isRestoringWallet = false + /// If this KeyringStore instance is creating a wallet or restoring a wallet. /// This flag is used to know when to dismiss onboarding when multiple windows are visible. - private var isRestoringWallet = false + private var isOnboarding: Bool = false private let keyringService: BraveWalletKeyringService private let walletService: BraveWalletBraveWalletService @@ -224,7 +227,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { }, _keyringCreated: { [weak self] keyringId in guard let self else { return } - if self.isOnboardingVisible, !self.isCreatingWallet, keyringId == BraveWallet.KeyringId.default { + if self.isOnboardingVisible, !self.isOnboarding, keyringId == BraveWallet.KeyringId.default { // Another window has created a wallet. We should dismiss onboarding on this // window and allow the other window to continue with it's onboarding flow. self.isOnboardingVisible = false @@ -242,7 +245,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { }, _walletRestored: { [weak self] in guard let self else { return } - if self.isOnboardingVisible && !self.isRestoringWallet { + if self.isOnboardingVisible && !self.isOnboarding { // Another window has restored a wallet. We should dismiss onboarding on this // window and allow the other window to continue with it's onboarding flow. self.isOnboardingVisible = false @@ -328,8 +331,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } func markOnboardingCompleted() { - self.isCreatingWallet = false - self.isRestoringWallet = false + self.isOnboarding = false self.isOnboardingVisible = false } @@ -387,9 +389,15 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } } - func createWallet(password: String, completion: ((String) -> Void)? = nil) { + func createWallet(password: String, completion: ((String?) -> Void)? = nil) { + guard !isCreatingWallet else { + completion?(nil) + return + } + isOnboarding = true isCreatingWallet = true keyringService.createWallet(password) { [weak self] mnemonic in + self?.isCreatingWallet = false self?.updateKeyringInfo() if !mnemonic.isEmpty { self?.passwordToSaveInBiometric = password @@ -413,6 +421,11 @@ public class KeyringStore: ObservableObject, WalletObserverStore { } func restoreWallet(phrase: String, password: String, isLegacyBraveWallet: Bool, completion: ((Bool) -> Void)? = nil) { + guard !isRestoringWallet else { // wallet is already being restored. + completion?(false) + return + } + isOnboarding = true isRestoringWallet = true keyringService.restoreWallet( phrase, @@ -420,6 +433,7 @@ public class KeyringStore: ObservableObject, WalletObserverStore { isLegacyBraveWallet: isLegacyBraveWallet ) { [weak self] isMnemonicValid in guard let self = self else { return } + self.isRestoringWallet = false if isMnemonicValid { // Restoring from wallet means you already have your phrase backed up self.passwordToSaveInBiometric = password