diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index 1aa372befc..444473ef5c 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -372,6 +372,15 @@ proc createChannelGroupItem[T](self: Module[T], channelGroup: ChannelGroupDto): communityTokensItems, ) +proc connectForNotificationsOnly[T](self: Module[T]) = + self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e:Args): + let args = AccountArgs(e) + self.view.showToastAccountAdded(args.account.name) + + self.events.on(SIGNAL_KEYPAIR_NAME_CHANGED) do(e: Args): + let args = KeypairArgs(e) + self.view.showToastKeypairRenamed(args.oldKeypairName, args.keypair.name) + method load*[T]( self: Module[T], events: EventEmitter, @@ -387,6 +396,7 @@ method load*[T]( singletonInstance.engine.setRootContextProperty("mainModule", self.viewVariant) self.controller.init() self.view.load() + self.connectForNotificationsOnly() var activeSection: SectionItem var activeSectionId = singletonInstance.localAccountSensitiveSettings.getActiveSection() diff --git a/src/app/modules/main/profile_section/wallet/accounts/item.nim b/src/app/modules/main/profile_section/wallet/accounts/item.nim index 0181914011..77d7d205f5 100644 --- a/src/app/modules/main/profile_section/wallet/accounts/item.nim +++ b/src/app/modules/main/profile_section/wallet/accounts/item.nim @@ -20,6 +20,7 @@ proc initItem*( keyUid: string = "", keycardAccount: bool = false, position: int = 0, + operability: string = "" ): Item = result = Item() result.WalletAccountItem.setup(name, @@ -29,7 +30,8 @@ proc initItem*( walletType, path, keyUid, - keycardAccount) + keycardAccount, + operability) result.position = position result.relatedAccounts = relatedAccounts diff --git a/src/app/modules/main/profile_section/wallet/accounts/module.nim b/src/app/modules/main/profile_section/wallet/accounts/module.nim index 9290c2dfe7..8f032d94b9 100644 --- a/src/app/modules/main/profile_section/wallet/accounts/module.nim +++ b/src/app/modules/main/profile_section/wallet/accounts/module.nim @@ -60,7 +60,8 @@ method convertWalletAccountDtoToKeyPairAccountItem(self: Module, account: Wallet colorId = account.colorId, icon = "", balance = 0, - balanceFetched = false) + balanceFetched = false, + operability = account.operable) method createKeypairItems*(self: Module, walletAccounts: seq[WalletAccountDto]): seq[KeyPairItem] = var keyPairItems = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = false, diff --git a/src/app/modules/main/view.nim b/src/app/modules/main/view.nim index 72f54ce03c..741b6ec259 100644 --- a/src/app/modules/main/view.nim +++ b/src/app/modules/main/view.nim @@ -101,7 +101,7 @@ QtObject: read = getEphemeralNotificationModel notify = ephemeralNotificationModelChanged - proc displayEphemeralNotification*(self: View, title: string, subTitle: string, icon: string, loading: bool, + proc displayEphemeralNotification*(self: View, title: string, subTitle: string, icon: string, loading: bool, ephNotifType: int, url: string) {.slot.} = self.delegate.displayEphemeralNotification(title, subTitle, icon, loading, ephNotifType, url) @@ -253,7 +253,7 @@ QtObject: proc activateStatusDeepLink*(self: View, statusDeepLink: string) {.slot.} = self.delegate.activateStatusDeepLink(statusDeepLink) - + proc displayKeycardSharedModuleFlow*(self: View) {.signal.} proc emitDisplayKeycardSharedModuleFlow*(self: View) = self.displayKeycardSharedModuleFlow() @@ -262,11 +262,15 @@ QtObject: proc emitDestroyKeycardSharedModuleFlow*(self: View) = self.destroyKeycardSharedModuleFlow() - proc windowActivated*(self: View) {.slot.} = + proc windowActivated*(self: View) {.slot.} = self.delegate.windowActivated() - proc windowDeactivated*(self: View) {.slot.} = + proc windowDeactivated*(self: View) {.slot.} = self.delegate.windowDeactivated() - proc setCommunityIdToSpectate*(self: View, communityId: string) {.slot.} = + proc setCommunityIdToSpectate*(self: View, communityId: string) {.slot.} = self.delegate.setCommunityIdToSpectate(communityId) + + ## Signals for in app (ephemeral) notifications + proc showToastAccountAdded*(self: View, name: string) {.signal.} + proc showToastKeypairRenamed*(self: View, oldName: string, newName: string) {.signal.} \ No newline at end of file diff --git a/src/app/modules/main/wallet_section/module.nim b/src/app/modules/main/wallet_section/module.nim index 413b3490c5..241176f58d 100644 --- a/src/app/modules/main/wallet_section/module.nim +++ b/src/app/modules/main/wallet_section/module.nim @@ -181,7 +181,6 @@ method load*(self: Module) = let args = AccountArgs(e) self.setTotalCurrencyBalance() self.filter.setAddress(args.account.address) - self.view.showToastAccountAdded(args.account.name) self.notifyFilterChanged() self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e:Args): let args = AccountArgs(e) diff --git a/src/app/modules/main/wallet_section/view.nim b/src/app/modules/main/wallet_section/view.nim index 3414362dd8..1e942e7da4 100644 --- a/src/app/modules/main/wallet_section/view.nim +++ b/src/app/modules/main/wallet_section/view.nim @@ -30,8 +30,6 @@ QtObject: proc load*(self: View) = self.delegate.viewDidLoad() - proc showToastAccountAdded*(self: View, name: string) {.signal.} - proc updateCurrency*(self: View, currency: string) {.slot.} = self.delegate.updateCurrency(currency) proc getCurrentCurrency(self: View): string {.slot.} = diff --git a/src/app/modules/shared/keypairs.nim b/src/app/modules/shared/keypairs.nim index 8fcd3e5a80..5eaf633b46 100644 --- a/src/app/modules/shared/keypairs.nim +++ b/src/app/modules/shared/keypairs.nim @@ -39,7 +39,8 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs: var icon = "" if acc.emoji.len == 0: icon = "wallet" - item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, icon, balance = 0.0)) + item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, + icon, balance = 0.0, balanceFetched = true, operability = acc.operable)) items.insert(item, 0) # Status Account must be at first place continue if kp.keypairType == KeypairTypeSeed: @@ -57,7 +58,8 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs: var icon = "" if acc.emoji.len == 0: icon = "wallet" - item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, icon, balance = 0.0)) + item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, + icon, balance = 0.0, balanceFetched = true, operability = acc.operable)) items.add(item) continue if kp.keypairType == KeypairTypeKey: @@ -77,7 +79,8 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs: var icon = "" if acc.emoji.len == 0: icon = "wallet" - item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, icon, balance = 0.0)) + item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, + icon, balance = 0.0, balanceFetched = true, operability = acc.operable)) items.add(item) continue if items.len == 0: diff --git a/src/app/modules/shared/wallet_utils.nim b/src/app/modules/shared/wallet_utils.nim index ae457ea5d7..3435c8e1f6 100644 --- a/src/app/modules/shared/wallet_utils.nim +++ b/src/app/modules/shared/wallet_utils.nim @@ -34,7 +34,6 @@ proc walletAccountToRelatedAccountItem*(w: WalletAccountDto) : related_account_i ) proc walletAccountToWalletSettingsAccountsItem*(w: WalletAccountDto, keycardAccount: bool): wallet_settings_accounts_item.Item = - discard let relatedAccounts = related_accounts_model.newModel() if w.isNil: return wallet_settings_accounts_item.initItem() @@ -52,6 +51,7 @@ proc walletAccountToWalletSettingsAccountsItem*(w: WalletAccountDto, keycardAcco w.keyUid, keycardAccount, w.position, + w.operable ) proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, keycardAccount: bool, enabledChainIds: seq[int], currency: string, diff --git a/src/app/modules/shared_models/keypair_account_item.nim b/src/app/modules/shared_models/keypair_account_item.nim index 3f4b10828e..cf29735e04 100644 --- a/src/app/modules/shared_models/keypair_account_item.nim +++ b/src/app/modules/shared_models/keypair_account_item.nim @@ -1,4 +1,7 @@ import NimQml, strformat +import app_service/service/wallet_account/dto as wa_dto + +export wa_dto QtObject: type KeyPairAccountItem* = ref object of QObject @@ -6,6 +9,7 @@ QtObject: path: string address: string pubKey: string + operability: string emoji: string colorId: string icon: string @@ -16,7 +20,7 @@ QtObject: self.QObject.delete proc newKeyPairAccountItem*(name = "", path = "", address = "", pubKey = "", emoji = "", colorId = "", icon = "", - balance = 0.0, balanceFetched = true): KeyPairAccountItem = + balance = 0.0, balanceFetched = true, operability = wa_dto.AccountFullyOperable): KeyPairAccountItem = new(result, delete) result.QObject.setup result.name = name @@ -28,6 +32,7 @@ QtObject: result.icon = icon result.balance = balance result.balanceFetched = balanceFetched + result.operability = operability proc `$`*(self: KeyPairAccountItem): string = result = fmt"""KeyPairAccountItem[ @@ -86,6 +91,17 @@ QtObject: write = setPubKey notify = pubKeyChanged + proc operabilityChanged*(self: KeyPairAccountItem) {.signal.} + proc getOperability*(self: KeyPairAccountItem): string {.slot.} = + return self.operability + proc setOperability*(self: KeyPairAccountItem, value: string) {.slot.} = + self.operability = value + self.operabilityChanged() + QtProperty[string] operability: + read = getOperability + write = setOperability + notify = operabilityChanged + proc emojiChanged*(self: KeyPairAccountItem) {.signal.} proc getEmoji*(self: KeyPairAccountItem): string {.slot.} = return self.emoji diff --git a/src/app/modules/shared_models/keypair_account_model.nim b/src/app/modules/shared_models/keypair_account_model.nim index f6ec4fd361..eda88dd69c 100644 --- a/src/app/modules/shared_models/keypair_account_model.nim +++ b/src/app/modules/shared_models/keypair_account_model.nim @@ -124,8 +124,13 @@ QtObject: self.items[i].setEmoji(emoji) return + proc updateOperabilityForAddress*(self: KeyPairAccountModel, address: string, operability: string) = + for i in 0 ..< self.items.len: + if cmpIgnoreCase(self.items[i].getAddress(), address) == 0: + self.items[i].setOperability(operability) + proc setBalanceForAddress*(self: KeyPairAccountModel, address: string, balance: float) = for i in 0 ..< self.items.len: if cmpIgnoreCase(self.items[i].getAddress(), address) == 0: self.items[i].setBalance(balance) - + diff --git a/src/app/modules/shared_models/keypair_item.nim b/src/app/modules/shared_models/keypair_item.nim index de32037d44..e11d0ab576 100644 --- a/src/app/modules/shared_models/keypair_item.nim +++ b/src/app/modules/shared_models/keypair_item.nim @@ -1,4 +1,4 @@ -import NimQml, strformat +import NimQml, strformat, sequtils, sugar import keypair_account_model export keypair_account_model @@ -23,6 +23,7 @@ QtObject: derivedFrom: string lastUsedDerivationIndex: int migratedToKeycard: bool + operability: string accounts: KeyPairAccountModel observedAccount: KeyPairAccountItem @@ -79,6 +80,7 @@ QtObject: derivedFrom: {self.derivedFrom}, lastUsedDerivationIndex: {self.lastUsedDerivationIndex}, migratedToKeycard: {self.migratedToKeycard}, + operability: {self.operability}, accounts: {$self.accounts} ]""" @@ -192,6 +194,19 @@ QtObject: write = setMigratedToKeycard notify = migratedToKeycardChanged + proc operabilityChanged*(self: KeyPairItem) {.signal.} + proc getOperability*(self: KeyPairItem): string {.slot.} = + let items = self.accounts.getItems() + if items.any(x => x.getOperability() == AccountNonOperable): + return AccountNonOperable + if items.any(x => x.getOperability() == AccountPartiallyOperable): + return AccountPartiallyOperable + return AccountFullyOperable + + QtProperty[string] operability: + read = getOperability + notify = operabilityChanged + proc observedAccountChanged*(self: KeyPairItem) {.signal.} proc getObservedAccountAsVariant*(self: KeyPairItem): QVariant {.slot.} = return newQVariant(self.observedAccount) @@ -204,7 +219,6 @@ QtObject: proc setLastAccountAsObservedAccount(self: KeyPairItem) = let index = self.accounts.getCount() - 1 self.setAccountAtIndexAsObservedAccount(index) - proc getAccountsModel*(self: KeyPairItem): KeyPairAccountModel = return self.accounts proc getAccountsAsVariant*(self: KeyPairItem): QVariant {.slot.} = @@ -214,15 +228,19 @@ QtObject: proc removeAccountAtIndex*(self: KeyPairItem, index: int) {.slot.} = self.accounts.removeItemAtIndex(index) self.setLastAccountAsObservedAccount() + self.operabilityChanged() proc removeAccountByAddress*(self: KeyPairItem, address: string) {.slot.} = self.accounts.removeItemByAddress(address) self.setLastAccountAsObservedAccount() + self.operabilityChanged() proc addAccount*(self: KeyPairItem, item: KeyPairAccountItem) = self.accounts.addItem(item) self.setLastAccountAsObservedAccount() + self.operabilityChanged() proc setAccounts*(self: KeyPairItem, items: seq[KeyPairAccountItem]) = self.accounts.setItems(items) self.setLastAccountAsObservedAccount() + self.operabilityChanged() proc containsAccountAddress*(self: KeyPairItem, address: string): bool = return self.accounts.containsAccountAddress(address) proc containsAccountPath*(self: KeyPairItem, path: string): bool = @@ -233,6 +251,9 @@ QtObject: self.accounts.updateDetailsForAddressIfTheyAreSet(address, name, colorId, emoji) proc setBalanceForAddress*(self: KeyPairItem, address: string, balance: float) = self.accounts.setBalanceForAddress(address, balance) + proc updateOperabilityForAccountWithAddress*(self: KeyPairItem, address: string, operability: string) = + self.accounts.updateOperabilityForAddress(address, operability) + self.operabilityChanged() proc setItem*(self: KeyPairItem, item: KeyPairItem) = self.setKeyUid(item.getKeyUid()) diff --git a/src/app/modules/shared_models/wallet_account_item.nim b/src/app/modules/shared_models/wallet_account_item.nim index 539a3a08bc..f7a8927570 100644 --- a/src/app/modules/shared_models/wallet_account_item.nim +++ b/src/app/modules/shared_models/wallet_account_item.nim @@ -1,4 +1,7 @@ import NimQml, strformat +import app_service/service/wallet_account/dto as wa_dto + +export wa_dto QtObject: type WalletAccountItem* = ref object of QObject @@ -10,6 +13,7 @@ QtObject: path: string keyUid: string keycardAccount: bool + operability: string proc setup*(self: WalletAccountItem, name: string = "", @@ -19,7 +23,8 @@ QtObject: walletType: string = "", path: string = "", keyUid: string = "", - keycardAccount: bool = false + keycardAccount: bool = false, + operability: string = wa_dto.AccountFullyOperable ) = self.QObject.setup self.name = name @@ -115,3 +120,13 @@ QtObject: notify = keycardAccountChanged + proc operabilityChanged*(self: WalletAccountItem) {.signal.} + proc getOperability*(self: WalletAccountItem): string {.slot.} = + return self.operability + proc setOperability*(self: WalletAccountItem, value: string) {.slot.} = + self.operability = value + self.operabilityChanged() + QtProperty[string] operability: + read = getOperability + write = setOperability + notify = operabilityChanged \ No newline at end of file diff --git a/src/app/modules/shared_modules/keycard_popup/internal/wrong_pin_state.nim b/src/app/modules/shared_modules/keycard_popup/internal/wrong_pin_state.nim index cecfbe13dc..9dd20a4798 100644 --- a/src/app/modules/shared_modules/keycard_popup/internal/wrong_pin_state.nim +++ b/src/app/modules/shared_modules/keycard_popup/internal/wrong_pin_state.nim @@ -41,7 +41,7 @@ method executePreSecondaryStateCommand*(self: WrongPinState, controller: Control self.flowType == FlowType.ChangePairingCode or self.flowType == FlowType.CreateCopyOfAKeycard: if controller.getPin().len == PINLengthForStatusApp: - controller.enterKeycardPin(controller.getPin()) + controller.enterKeycardPin(controller.getPin()) if self.flowType == FlowType.Authentication: controller.setUsePinFromBiometrics(false) controller.tryToObtainDataFromKeychain() @@ -61,13 +61,13 @@ method executeCancelCommand*(self: WrongPinState, controller: Controller) = self.flowType == FlowType.CreateCopyOfAKeycard: controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false) -method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent, +method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State = let state = ensureReaderAndCardPresence(self, keycardFlowType, keycardEvent, controller) if not state.isNil: return state if self.flowType == FlowType.FactoryReset: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -75,7 +75,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -84,7 +84,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.SetupNewKeycard: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -92,7 +92,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -101,7 +101,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.SetupNewKeycardNewSeedPhrase: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -109,7 +109,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -118,7 +118,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.SetupNewKeycardOldSeedPhrase: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -126,7 +126,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -135,7 +135,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.ImportFromKeycard: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -143,7 +143,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -160,22 +160,22 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke item.setName(keycardEvent.cardMetadata.name) item.setIcon("keycard") item.setPairType(KeyPairType.SeedImport.int) - item.addAccount(newKeyPairAccountItem(name = "", - path = accountItem.getPath(), + item.addAccount(newKeyPairAccountItem(name = "", + path = accountItem.getPath(), address = accountItem.getAddress(), pubKey = accountItem.getPubKey() )) # name and other params will be set by the user during the flow - controller.setKeyPairForProcessing(item) + controller.setKeyPairForProcessing(item) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.Authentication: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) if keycardEvent.pinRetries > 0: return self return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: return createState(StateType.MaxPinRetriesReached, self.flowType, nil) @@ -184,7 +184,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true) return nil if self.flowType == FlowType.DisplayKeycardContent: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -192,7 +192,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -201,7 +201,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.RenameKeycard: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -209,7 +209,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) @@ -218,7 +218,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.ChangeKeycardPin: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -226,7 +226,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) @@ -235,7 +235,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke if keycardEvent.error == ErrorChangingCredentials: return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.ChangeKeycardPuk: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -243,7 +243,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) @@ -252,7 +252,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke if keycardEvent.error == ErrorChangingCredentials: return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.ChangePairingCode: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -260,7 +260,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true)) @@ -270,7 +270,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return createState(StateType.PinVerified, self.flowType, nil) if self.flowType == FlowType.CreateCopyOfAKeycard: if isPredefinedKeycardDataFlagSet(controller.getKeycardData(), PredefinedKeycardData.CopyFromAKeycardPartDone): - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) @@ -278,7 +278,7 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke return self controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.DisableSeedPhraseForUnlock, add = true)) @@ -287,14 +287,14 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke controller.setMetadataFromKeycard(keycardEvent.cardMetadata) return createState(StateType.PinVerified, self.flowType, nil) else: - if keycardFlowType == ResponseTypeValueEnterPIN and + if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorPIN: controller.setRemainingAttempts(keycardEvent.pinRetries) if keycardEvent.pinRetries > 0: return self return createState(StateType.MaxPinRetriesReached, self.flowType, nil) - if keycardFlowType == ResponseTypeValueEnterPUK and + if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: return createState(StateType.MaxPinRetriesReached, self.flowType, nil) diff --git a/src/app/modules/shared_modules/keycard_popup/module.nim b/src/app/modules/shared_modules/keycard_popup/module.nim index 6dab69ffe3..d4d9e8df7e 100644 --- a/src/app/modules/shared_modules/keycard_popup/module.nim +++ b/src/app/modules/shared_modules/keycard_popup/module.nim @@ -567,7 +567,7 @@ proc buildKeyPairItemBasedOnCardMetadata[T](self: Module[T], cardMetadata: CardM if acc.emoji.len == 0: icon = "wallet" result.item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, icon, - balance = 0.0, balanceFetched = true)) + balance = 0.0, balanceFetched = true, operability = acc.operable)) # handle unknown accounts var unknownAccountNumber = 0 for cardAcc in cardMetadata.walletAccounts: diff --git a/src/app_service/service/wallet_account/service.nim b/src/app_service/service/wallet_account/service.nim index 7b59ef6b3c..5acfe1da1a 100644 --- a/src/app_service/service/wallet_account/service.nim +++ b/src/app_service/service/wallet_account/service.nim @@ -79,6 +79,7 @@ type AccountArgs* = ref object of Args type KeypairArgs* = ref object of Args keypair*: KeypairDto + oldKeypairName*: string type KeycardArgs* = ref object of Args success*: bool @@ -578,6 +579,9 @@ QtObject: proc updateKeypairName*(self: Service, keyUid: string, name: string) = try: + let keypair = self.getKeypairByKeyUid(keyUid) + if keypair.isNil: + return let response = backend.updateKeypairName(keyUid, name) if not response.error.isNil: error "status-go error", procName="updateKeypairName", errCode=response.error.code, errDesription=response.error.message @@ -588,7 +592,8 @@ QtObject: keypair: KeypairDto( keyUid: keyUid, name: name - ) + ), + oldKeypairName: keypair.name ) ) except Exception as e: diff --git a/ui/app/AppLayouts/Profile/controls/WalletKeyPairDelegate.qml b/ui/app/AppLayouts/Profile/controls/WalletKeyPairDelegate.qml index 73bd200c79..896e0857e0 100644 --- a/ui/app/AppLayouts/Profile/controls/WalletKeyPairDelegate.qml +++ b/ui/app/AppLayouts/Profile/controls/WalletKeyPairDelegate.qml @@ -39,7 +39,7 @@ Rectangle { width: parent.width StatusListItem { Layout.fillWidth: true - title: d.isWatchOnly ? qsTr("Watch only") : model.keyPair.name + title: d.isWatchOnly ? qsTr("Watched addresses") : model.keyPair.name statusListItemSubTitle.textFormat: Qt.RichText titleTextIcon: model.keyPair.migratedToKeycard ? "keycard": "" subTitle: d.isWatchOnly ? "" : d.isProfileKeypair ? @@ -79,8 +79,10 @@ Rectangle { } StatusAction { - text: enabled? qsTr("Show encrypted QR of keys on device") : "" - enabled: !d.isProfileKeypair + text: enabled? qsTr("Show encrypted QR of keypairs on device") : "" + enabled: !d.isProfileKeypair && + !model.keyPair.migratedToKeycard && + !model.keyPair.operability === Constants.keypair.operability.nonOperable icon.name: "qr" icon.color: Theme.palette.primaryColor1 onTriggered: { @@ -116,7 +118,7 @@ Rectangle { } StatusAction { - text: enabled? qsTr("Remove master keys and associated accounts") : "" + text: enabled? qsTr("Remove keypair and associated accounts") : "" enabled: !d.isProfileKeypair type: StatusAction.Type.Danger icon.name: "delete" diff --git a/ui/app/AppLayouts/Wallet/WalletLayout.qml b/ui/app/AppLayouts/Wallet/WalletLayout.qml index 9fe46e3f51..f33cb8d1f8 100644 --- a/ui/app/AppLayouts/Wallet/WalletLayout.qml +++ b/ui/app/AppLayouts/Wallet/WalletLayout.qml @@ -77,7 +77,7 @@ Item { backButtonName: RootStore.backButtonName notificationCount: activityCenterStore.unreadNotificationsCount hasUnseenNotifications: activityCenterStore.hasUnseenNotifications - + onNotificationButtonClicked: Global.openActivityCenterPopup() onBackButtonClicked: { rightPanelStackView.currentItem.resetStack(); @@ -146,18 +146,4 @@ Item { anchors.centerIn: parent } } - - Connections { - target: RootStore.walletSectionInst - function onShowToastAccountAdded(name: string) { - Global.displayToastMessage( - qsTr("\"%1\" successfuly added").arg(name), - "", - "check-circle", - false, - Constants.ephemeralNotificationType.success, - "" - ) - } - } } diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index 84bedbc776..036d5c4752 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -94,6 +94,28 @@ Item { function onOpenActivityCenter() { d.openActivityCenterPopup() } + + function onShowToastAccountAdded(name: string) { + Global.displayToastMessage( + qsTr("\"%1\" successfuly added").arg(name), + "", + "check-circle", + false, + Constants.ephemeralNotificationType.success, + "" + ) + } + + function onShowToastKeypairRenamed(oldName: string, newName: string) { + Global.displayToastMessage( + qsTr("You successfully renamed your keypair\nfrom \"%1\" to \"%2\"").arg(oldName).arg(newName), + "", + "check-circle", + false, + Constants.ephemeralNotificationType.success, + "" + ) + } } QtObject { diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 9a48b871d2..5fb43dd69a 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -469,6 +469,12 @@ QtObject { readonly property QtObject keypair: QtObject { readonly property int nameLengthMax: 20 readonly property int nameLengthMin: 5 + + readonly property QtObject operability: QtObject { + readonly property string nonOperable: "no" // an account is non operable it is not a keycard account and there is no keystore file for it and no keystore file for the address it is derived from + readonly property string partiallyOperable: "partially" // an account is partially operable if it is not a keycard account and there is created keystore file for the address it is derived from + readonly property string fullyOperable: "fully" // an account is fully operable if it is not a keycard account and there is a keystore file for it + } } readonly property QtObject validators: QtObject {