fix(@desktop/wallet): review comments applied for keypair rename feature

- labels changed in Figma, updated in the app
- `Show encrypted QR of keypairs on device` is displayed only if needed now,
for this I had to add account/keypair `operability` feature, so far it handles only
displaying a context menu option, later in a separate issue a proper functionality
will be added
- wallet related toast notifications moved to the proper place (`AppMain.qml`, where
actually all notifications should be handled), not in the place where they occurs, we
need to review other notifications as well and move them there
This commit is contained in:
Sale Djenic 2023-07-17 22:06:34 +02:00 committed by saledjenic
parent 6d25a888d3
commit 4b6066c955
19 changed files with 166 additions and 71 deletions

View File

@ -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()

View File

@ -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

View File

@ -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,

View File

@ -270,3 +270,7 @@ QtObject:
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.}

View File

@ -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)

View File

@ -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.} =

View File

@ -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:

View File

@ -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,

View File

@ -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

View File

@ -124,6 +124,11 @@ 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:

View File

@ -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())

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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"

View File

@ -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,
""
)
}
}
}

View File

@ -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 {

View File

@ -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 {