chore(@desktop/wallet): sorting out keypair/account menu

This commit is contained in:
Sale Djenic 2023-08-04 12:29:04 +02:00 committed by saledjenic
parent f8dd1dc811
commit 6e5469f5aa
16 changed files with 254 additions and 132 deletions

View File

@ -32,7 +32,8 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs:
pairType = KeyPairType.Profile,
derivedFrom = kp.derivedFrom,
lastUsedDerivationIndex = kp.lastUsedDerivationIndex,
migratedToKeycard = kpMigrated)
migratedToKeycard = kpMigrated,
syncedFrom = kp.syncedFrom)
for acc in kp.accounts:
if acc.isChat:
continue
@ -53,7 +54,8 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs:
pairType = KeyPairType.SeedImport,
derivedFrom = kp.derivedFrom,
lastUsedDerivationIndex = kp.lastUsedDerivationIndex,
migratedToKeycard = kpMigrated)
migratedToKeycard = kpMigrated,
syncedFrom = kp.syncedFrom)
for acc in kp.accounts:
var icon = ""
if acc.emoji.len == 0:
@ -74,7 +76,8 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs:
pairType = KeyPairType.PrivateKeyImport,
derivedFrom = kp.derivedFrom,
lastUsedDerivationIndex = kp.lastUsedDerivationIndex,
migratedToKeycard = kpMigrated)
migratedToKeycard = kpMigrated,
syncedFrom = kp.syncedFrom)
for acc in kp.accounts:
var icon = ""
if acc.emoji.len == 0:

View File

@ -55,6 +55,7 @@ QtObject:
icon: {self.icon},
balance: {self.balance},
balanceFetched: {self.balanceFetched},
operability: {self.operability},
isDefaultAccount: {self.isDefaultAccount},
areTestNetworksEnabled: {self.areTestNetworksEnabled},
prodPreferredChainIds: {self.prodPreferredChainIds},

View File

@ -25,6 +25,7 @@ QtObject:
lastUsedDerivationIndex: int
migratedToKeycard: bool
operability: string
syncedFrom: string
accounts: KeyPairAccountModel
observedAccount: KeyPairAccountItem
@ -38,7 +39,8 @@ QtObject:
pairType: KeyPairType,
derivedFrom: string,
lastUsedDerivationIndex: int,
migratedToKeycard: bool
migratedToKeycard: bool,
syncedFrom: string
) =
self.QObject.setup
self.keyUid = keyUid
@ -51,6 +53,7 @@ QtObject:
self.derivedFrom = derivedFrom
self.lastUsedDerivationIndex = lastUsedDerivationIndex
self.migratedToKeycard = migratedToKeycard
self.syncedFrom = syncedFrom
self.accounts = newKeyPairAccountModel()
proc delete*(self: KeyPairItem) =
@ -65,9 +68,11 @@ QtObject:
pairType = KeyPairType.Unknown,
derivedFrom = "",
lastUsedDerivationIndex = 0,
migratedToKeycard = false): KeyPairItem =
migratedToKeycard = false,
syncedFrom = ""): KeyPairItem =
new(result, delete)
result.setup(keyUid, pubKey, locked, name, image, icon, pairType, derivedFrom, lastUsedDerivationIndex, migratedToKeycard)
result.setup(keyUid, pubKey, locked, name, image, icon, pairType, derivedFrom, lastUsedDerivationIndex,
migratedToKeycard, syncedFrom)
proc `$`*(self: KeyPairItem): string =
result = fmt"""KeyPairItem[
@ -82,6 +87,7 @@ QtObject:
lastUsedDerivationIndex: {self.lastUsedDerivationIndex},
migratedToKeycard: {self.migratedToKeycard},
operability: {self.operability},
syncedFrom: {self.syncedFrom},
accounts: {$self.accounts}
]"""
@ -203,11 +209,21 @@ QtObject:
if items.any(x => x.getOperability() == AccountPartiallyOperable):
return AccountPartiallyOperable
return AccountFullyOperable
QtProperty[string] operability:
read = getOperability
notify = operabilityChanged
proc syncedFromChanged*(self: KeyPairItem) {.signal.}
proc getSyncedFrom*(self: KeyPairItem): string {.slot.} =
return self.syncedFrom
proc setSyncedFrom*(self: KeyPairItem, value: string) {.slot.} =
self.syncedFrom = value
self.syncedFromChanged()
QtProperty[string] syncedFrom:
read = getSyncedFrom
write = setSyncedFrom
notify = syncedFromChanged
proc observedAccountChanged*(self: KeyPairItem) {.signal.}
proc getObservedAccountAsVariant*(self: KeyPairItem): QVariant {.slot.} =
return newQVariant(self.observedAccount)

View File

@ -25,7 +25,7 @@ QtObject:
): KeycardItem =
new(result, delete)
result.KeyPairItem.setup(keyUid, pubKey, locked, name, image, icon, pairType, derivedFrom,lastUsedDerivationIndex,
migratedToKeycard)
migratedToKeycard, syncedFrom = "")
result.keycardUid = keycardUid
proc `$`*(self: KeycardItem): string =

View File

@ -10,6 +10,9 @@ const KeypairTypeProfile* = "profile"
const KeypairTypeSeed* = "seed"
const KeypairTypeKey* = "key"
const SyncedFromBackup* = "backup" # means a account is coming from backed up data
const SyncedFromLocalPairing* = "local-pairing" # means a account is coming from another device when user is reocovering Status account
type
KeypairDto* = ref object of RootObj
keyUid*: string

View File

@ -106,4 +106,11 @@ proc getEnsName(address: string, chainId: int): string =
return response.result.getStr
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
error "error: ", errDesription
proc hasPairedDevices(): bool =
try:
let response = backend.hasPairedDevices()
return response.result.getBool
except Exception as e:
error "error: ", errDesription=e.msg

View File

@ -299,3 +299,6 @@ rpc(getCachedCurrencyFormats, "wallet"):
rpc(fetchAllCurrencyFormats, "wallet"):
discard
rpc(hasPairedDevices, "accounts"):
discard

View File

@ -1,7 +1,7 @@
<svg width="24" height="20" viewBox="0 0 24 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.754547 10C0.754547 9.58579 1.09033 9.25 1.50455 9.25H22.4954C22.9096 9.25 23.2454 9.58579 23.2454 10C23.2454 10.4142 22.9096 10.75 22.4954 10.75H1.50455C1.09033 10.75 0.754547 10.4142 0.754547 10Z" fill="#939BA1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4.75317C2 2.12982 4.12665 0.00317383 6.75 0.00317383H8.75C9.16421 0.00317383 9.5 0.33896 9.5 0.753174C9.5 1.16739 9.16421 1.50317 8.75 1.50317H6.75C4.95507 1.50317 3.5 2.95825 3.5 4.75317V6.54037C3.5 6.95458 3.16421 7.29037 2.75 7.29037C2.33579 7.29037 2 6.95458 2 6.54037V4.75317Z" fill="#939BA1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 15.25C2 17.8734 4.12665 20 6.75 20H8.75C9.16421 20 9.5 19.6642 9.5 19.25C9.5 18.8358 9.16421 18.5 8.75 18.5H6.75C4.95507 18.5 3.5 17.0449 3.5 15.25V13.4628C3.5 13.0486 3.16421 12.7128 2.75 12.7128C2.33579 12.7128 2 13.0486 2 13.4628V15.25Z" fill="#939BA1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 4.75317C22 2.12982 19.8734 0.00317383 17.25 0.00317383H15.25C14.8358 0.00317383 14.5 0.33896 14.5 0.753174C14.5 1.16739 14.8358 1.50317 15.25 1.50317H17.25C19.0449 1.50317 20.5 2.95825 20.5 4.75317V6.54037C20.5 6.95458 20.8358 7.29037 21.25 7.29037C21.6642 7.29037 22 6.95458 22 6.54037V4.75317Z" fill="#939BA1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 15.25C22 17.8734 19.8734 20 17.25 20H15.25C14.8358 20 14.5 19.6642 14.5 19.25C14.5 18.8358 14.8358 18.5 15.25 18.5H17.25C19.0449 18.5 20.5 17.0449 20.5 15.25V13.4628C20.5 13.0486 20.8358 12.7128 21.25 12.7128C21.6642 12.7128 22 13.0486 22 13.4628V15.25Z" fill="#939BA1"/>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M0.50293 8.00049C0.50293 7.72435 0.726787 7.50049 1.00293 7.50049H14.9969C15.273 7.50049 15.4969 7.72435 15.4969 8.00049C15.4969 8.27663 15.273 8.50049 14.9969 8.50049H1.00293C0.726787 8.50049 0.50293 8.27663 0.50293 8.00049Z" fill="#4360DF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.33323 4.5026C1.33323 2.7537 2.751 1.33594 4.4999 1.33594H5.83323C6.10937 1.33594 6.33323 1.5598 6.33323 1.83594C6.33323 2.11208 6.10937 2.33594 5.83323 2.33594H4.4999C3.30328 2.33594 2.33323 3.30599 2.33323 4.5026V5.69407C2.33323 5.97021 2.10937 6.19407 1.83323 6.19407C1.55709 6.19407 1.33323 5.97021 1.33323 5.69407V4.5026Z" fill="#4360DF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.33323 11.5005C1.33323 13.2494 2.751 14.6672 4.4999 14.6672H5.83323C6.10937 14.6672 6.33323 14.4433 6.33323 14.1672C6.33323 13.891 6.10937 13.6672 5.83323 13.6672H4.4999C3.30328 13.6672 2.33323 12.6971 2.33323 11.5005V10.309C2.33323 10.0329 2.10937 9.80902 1.83323 9.80902C1.55709 9.80902 1.33323 10.0329 1.33323 10.309V11.5005Z" fill="#4360DF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.6666 4.5026C14.6666 2.7537 13.2488 1.33594 11.4999 1.33594H10.1666C9.89042 1.33594 9.66656 1.5598 9.66656 1.83594C9.66656 2.11208 9.89042 2.33594 10.1666 2.33594H11.4999C12.6965 2.33594 13.6666 3.30599 13.6666 4.5026V5.69407C13.6666 5.97021 13.8904 6.19407 14.1666 6.19407C14.4427 6.19407 14.6666 5.97021 14.6666 5.69407V4.5026Z" fill="#4360DF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.6666 11.5005C14.6666 13.2494 13.2488 14.6672 11.4999 14.6672H10.1666C9.89042 14.6672 9.66656 14.4433 9.66656 14.1672C9.66656 13.891 9.89042 13.6672 10.1666 13.6672H11.4999C12.6965 13.6672 13.6666 12.6971 13.6666 11.5005V10.309C13.6666 10.0329 13.8904 9.80902 14.1666 9.80902C14.4427 9.80902 14.6666 10.0329 14.6666 10.309V11.5005Z" fill="#4360DF"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -14,17 +14,17 @@ StatusListItem {
signal buttonClicked()
title: keyPair ? keyPair.pairType === Constants.keycard.keyPairType.watchOnly ? qsTr("Watch only") : keyPair.name: ""
titleAsideText: keyPair && keyPair.pairType === Constants.keycard.keyPairType.profile ? Utils.getElidedCompressedPk(keyPair.pubKey): ""
title: !!root.keyPair? root.keyPair.pairType === Constants.keypair.type.watchOnly ? qsTr("Watch only") : root.keyPair.name: ""
titleAsideText: !!root.keyPair && root.keyPair.pairType === Constants.keypair.type.profile? Utils.getElidedCompressedPk(root.keyPair.pubKey): ""
asset {
width: keyPair && keyPair.icon ? Style.current.bigPadding : 40
height: keyPair && keyPair.icon ? Style.current.bigPadding : 40
name: keyPair ? keyPair.image ? keyPair.image : keyPair.icon: ""
isImage: !!keyPair && !!keyPair.image
color: keyPair && keyPair.pairType === Constants.keycard.keyPairType.profile ? Utils.colorForPubkey(root.userProfilePublicKey) : Theme.palette.primaryColor1
width: !!root.keyPair && root.keyPair.icon? Style.current.bigPadding : 40
height: !!root.keyPair && root.keyPair.icon? Style.current.bigPadding : 40
name: !!root.keyPair? !!root.keyPair.image? root.keyPair.image : root.keyPair.icon : ""
isImage: !!root.keyPair && !!root.keyPair.image
color: !!root.keyPair && root.keyPair.pairType === Constants.keypair.type.profile? Utils.colorForPubkey(root.userProfilePublicKey) : Theme.palette.primaryColor1
letterSize: Math.max(4, asset.width / 2.4)
charactersLen: 2
isLetterIdenticon: !!keyPair && !keyPair.icon && !asset.name.toString()
isLetterIdenticon: !!root.keyPair && !root.keyPair.icon && !asset.name.toString()
}
color: {
if (sensor.containsMouse || root.highlighted) {
@ -33,10 +33,10 @@ StatusListItem {
return Theme.palette.transparent
}
ringSettings {
ringSpecModel: keyPair && keyPair.pairType === Constants.keycard.keyPairType.profile ? Utils.getColorHashAsJson(root.userProfilePublicKey) : []
ringSpecModel: !!root.keyPair && root.keyPair.pairType === Constants.keypair.type.profile? Utils.getColorHashAsJson(root.userProfilePublicKey) : []
ringPxSize: Math.max(asset.width / 24.0)
}
tagsModel: keyPair ? keyPair.accounts: []
tagsModel: !!root.keyPair? root.keyPair.accounts: []
tagsDelegate: StatusListItemTag {
bgColor: !!model.account.colorId ? Utils.getColorForId(model.account.colorId): ""
bgRadius: 6

View File

@ -26,11 +26,9 @@ Rectangle {
QtObject {
id: d
readonly property var relatedAccounts: keyPair.accounts
readonly property bool isWatchOnly: keyPair.pairType === Constants.keycard.keyPairType.watchOnly
readonly property bool isPrivateKeyImport: keyPair.pairType === Constants.keycard.keyPairType.privateKeyImport
readonly property bool isProfileKeypair: keyPair.pairType === Constants.keycard.keyPairType.profile
readonly property string locationInfo: keyPair.migratedToKeycard ? qsTr("On Keycard"): qsTr("On device")
readonly property var relatedAccounts: !!root.keyPair? root.keyPair.accounts : {}
readonly property bool isWatchOnly: !!root.keyPair && root.keyPair.pairType === Constants.keypair.type.watchOnly
readonly property bool isProfileKeypair: !!root.keyPair && root.keyPair.pairType === Constants.keypair.type.profile
}
implicitHeight: layout.height
@ -43,25 +41,25 @@ Rectangle {
width: parent.width
StatusListItem {
Layout.fillWidth: true
title: d.isWatchOnly ? qsTr("Watched addresses") : keyPair.name
title: !!root.keyPair? d.isWatchOnly ? qsTr("Watched addresses") : root.keyPair.name : ""
statusListItemSubTitle.textFormat: Qt.RichText
titleTextIcon: keyPair.migratedToKeycard ? "keycard": ""
subTitle: d.isWatchOnly ? "" : d.isProfileKeypair ?
Utils.getElidedCompressedPk(keyPair.pubKey) + Constants.settingsSection.dotSepString + d.locationInfo : d.locationInfo
titleTextIcon: !!root.keyPair && keyPair.migratedToKeycard ? "keycard": ""
subTitle: Utils.getKeypairLocation(root.keyPair)
statusListItemSubTitle.color: Utils.getKeypairLocationColor(root.keyPair)
color: Theme.palette.transparent
ringSettings {
ringSpecModel: d.isProfileKeypair ? Utils.getColorHashAsJson(root.userProfilePublicKey) : []
ringPxSize: Math.max(asset.width / 24.0)
}
asset {
width: keyPair.icon ? Style.current.bigPadding : 40
height: keyPair.icon ? Style.current.bigPadding : 40
name: keyPair.image ? keyPair.image : keyPair.icon
isImage: !!keyPair.image
width: !!root.keyPair && keyPair.icon? Style.current.bigPadding : 40
height: !!root.keyPair && keyPair.icon? Style.current.bigPadding : 40
name: !!root.keyPair? !!root.keyPair.image? root.keyPair.image : root.keyPair.icon : ""
isImage: !!root.keyPair && !!keyPair.image
color: d.isProfileKeypair ? Utils.colorForPubkey(root.userProfilePublicKey) : Theme.palette.primaryColor1
letterSize: Math.max(4, asset.width / 2.4)
charactersLen: 2
isLetterIdenticon: !keyPair.icon && !asset.name.toString()
isLetterIdenticon: !!root.keyPair && !keyPair.icon && !asset.name.toString()
}
components: [
StatusFlatRoundButton {
@ -77,7 +75,7 @@ Rectangle {
Loader {
id: menuLoader
active: false
sourceComponent: WalletAccountKeycardMenu {
sourceComponent: WalletKeypairAccountMenu {
onClosed: {
menuLoader.active = false
}

View File

@ -1,69 +0,0 @@
import QtQuick 2.15
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import utils 1.0
StatusMenu {
id: root
property var keyPair
signal runRenameKeypairFlow()
signal runRemoveKeypairFlow()
QtObject {
id: d
readonly property bool isProfileKeypair: keyPair.pairType === Constants.keycard.keyPairType.profile
}
StatusAction {
text: enabled? qsTr("Show encrypted QR of keypairs on device") : ""
enabled: !d.isProfileKeypair &&
!keyPair.migratedToKeycard &&
!keyPair.operability === Constants.keypair.operability.nonOperable
icon.name: "qr"
icon.color: Theme.palette.primaryColor1
onTriggered: {
console.warn("TODO: show encrypted QR")
}
}
StatusAction {
text: keyPair.migratedToKeycard? qsTr("Stop using Keycard") : qsTr("Move keys to a Keycard")
icon.name: keyPair.migratedToKeycard? "keycard-crossed" : "keycard"
icon.color: Theme.palette.primaryColor1
onTriggered: {
if (keyPair.migratedToKeycard)
console.warn("TODO: stop using Keycard")
else
console.warn("TODO: move keys to a Keycard")
}
}
StatusAction {
text: enabled? qsTr("Rename keypair") : ""
enabled: !d.isProfileKeypair
icon.name: "edit"
icon.color: Theme.palette.primaryColor1
onTriggered: {
root.runRenameKeypairFlow()
}
}
StatusMenuSeparator {
visible: !d.isProfileKeypair
}
StatusAction {
text: enabled? qsTr("Remove keypair and associated accounts") : ""
enabled: !d.isProfileKeypair
type: StatusAction.Type.Danger
icon.name: "delete"
icon.color: Theme.palette.dangerColor1
onTriggered: {
root.runRemoveKeypairFlow()
}
}
}

View File

@ -0,0 +1,98 @@
import QtQuick 2.15
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import utils 1.0
StatusMenu {
id: root
property var keyPair
signal runRenameKeypairFlow()
signal runRemoveKeypairFlow()
StatusAction {
text: enabled? qsTr("Show encrypted QR of keypairs on device") : ""
enabled: !!root.keyPair &&
root.keyPair.pairType !== Constants.keypair.type.profile &&
!root.keyPair.migratedToKeycard &&
root.keyPair.operability === Constants.keypair.operability.fullyOperable
icon.name: "qr"
icon.color: Theme.palette.primaryColor1
onTriggered: {
console.warn("TODO: show encrypted QR")
}
}
StatusAction {
text: enabled? root.keyPair.migratedToKeycard? qsTr("Stop using Keycard") : qsTr("Move keys to a Keycard") : ""
enabled: !!root.keyPair &&
root.keyPair.operability !== Constants.keypair.operability.nonOperable
icon.name: !!root.keyPair && root.keyPair.migratedToKeycard? "keycard-crossed" : "keycard"
icon.color: Theme.palette.primaryColor1
onTriggered: {
if (root.keyPair.migratedToKeycard)
console.warn("TODO: stop using Keycard")
else
console.warn("TODO: move keys to a Keycard")
}
}
StatusAction {
text: enabled? qsTr("Import keypair from device via encrypted QR") : ""
enabled: !!root.keyPair &&
root.keyPair.pairType !== Constants.keypair.type.profile &&
root.keyPair.operability === Constants.keypair.operability.nonOperable &&
root.keyPair.syncedFrom !== Constants.keypair.syncedFrom.backup
icon.name: "qr-scan"
icon.color: Theme.palette.primaryColor1
onTriggered: {
console.warn("TODO: run import via encrypted QR")
}
}
StatusAction {
text: enabled? root.keyPair.pairType === Constants.keypair.type.privateKeyImport? qsTr("Import via entering private key") : qsTr("Import via entering seed phrase") : ""
enabled: !!root.keyPair &&
(root.keyPair.pairType === Constants.keypair.type.seedImport ||
root.keyPair.pairType === Constants.keypair.type.privateKeyImport)
icon.name: enabled? root.keyPair.pairType === Constants.keypair.type.privateKeyImport? "objects" : "key_pair_seed_phrase" : ""
icon.color: Theme.palette.primaryColor1
onTriggered: {
if (root.keyPair.pairType === Constants.keypair.type.privateKeyImport)
console.warn("TODO: run import via private key flow")
else
console.warn("TODO: run import via seed phrase flow")
}
}
StatusAction {
text: enabled? qsTr("Rename keypair") : ""
enabled: !!root.keyPair &&
root.keyPair.pairType !== Constants.keypair.type.profile
icon.name: "edit"
icon.color: Theme.palette.primaryColor1
onTriggered: {
root.runRenameKeypairFlow()
}
}
StatusMenuSeparator {
visible: !!root.keyPair &&
root.keyPair.pairType !== Constants.keypair.type.profile
}
StatusAction {
text: enabled? qsTr("Remove keypair and associated accounts") : ""
enabled: !!root.keyPair &&
root.keyPair.pairType !== Constants.keypair.type.profile
type: StatusAction.Type.Danger
icon.name: "delete"
icon.color: Theme.palette.dangerColor1
onTriggered: {
root.runRemoveKeypairFlow()
}
}
}

View File

@ -3,6 +3,6 @@ SetupSyncingPopup 1.0 SetupSyncingPopup.qml
AddSocialLinkModal 1.0 AddSocialLinkModal.qml
ModifySocialLinkModal 1.0 ModifySocialLinkModal.qml
RenameKeypairPopup 1.0 RenameKeypairPopup.qml
WalletAccountKeycardMenu 1.0 WalletAccountKeycardMenu.qml
WalletKeypairAccountMenu 1.0 WalletKeypairAccountMenu.qml
WalletAddressMenu 1.0 WalletAddressMenu.qml
RenameAccontModal 1.0 RenameAccontModal.qml

View File

@ -34,9 +34,9 @@ ColumnLayout {
QtObject {
id: d
readonly property bool watchOnlyAccount: keyPair && keyPair.pairType ? keyPair.pairType === Constants.keycard.keyPairType.watchOnly: false
readonly property bool privateKeyAccount: keyPair && keyPair.pairType ? keyPair.pairType === Constants.keycard.keyPairType.privateKeyImport: false
readonly property string preferredSharingNetworks: !!account ? account.preferredSharingChainIds: ""
readonly property bool watchOnlyAccount: !!root.keyPair? root.keyPair.pairType === Constants.keypair.type.watchOnly: false
readonly property bool privateKeyAccount: !!root.keyPair? root.keyPair.pairType === Constants.keypair.type.privateKeyImport: false
readonly property string preferredSharingNetworks: !!root.account? root.account.preferredSharingChainIds: ""
property var preferredSharingNetworksArray: preferredSharingNetworks.split(":").filter(Boolean)
property string preferredSharingNetworkShortNames: walletStore.getNetworkShortNames(preferredSharingNetworks)
onPreferredSharingNetworksChanged: {
@ -56,17 +56,17 @@ ColumnLayout {
id: accountName
objectName: "walletAccountViewAccountName"
Layout.alignment: Qt.AlignLeft
text: root.account ? root.account.name : ""
text: !!root.account? root.account.name : ""
font.weight: Font.Bold
font.pixelSize: 28
color: root.account ? Utils.getColorForId(root.account.colorId) : Theme.palette.directColor1
color: !!root.account? Utils.getColorForId(root.account.colorId) : Theme.palette.directColor1
}
StatusEmoji {
id: accountImage
objectName: "walletAccountViewAccountImage"
Layout.preferredWidth: 28
Layout.preferredHeight: 28
emojiId: StatusQUtils.Emoji.iconId(root.account && root.account.emoji ? root.account.emoji : "", StatusQUtils.Emoji.size.big) || ""
emojiId: StatusQUtils.Emoji.iconId(!!root.account && root.account.emoji ? root.account.emoji : "", StatusQUtils.Emoji.size.big) || ""
}
}
StatusButton {
@ -100,7 +100,7 @@ ColumnLayout {
WalletAccountDetailsListItem {
Layout.fillWidth: true
title: qsTr("Balance")
subTitle: root.account && root.account.balance ? LocaleUtils.currencyAmountToLocaleString(root.account.balance): ""
subTitle: !!root.account && root.account.balance ? LocaleUtils.currencyAmountToLocaleString(root.account.balance): ""
}
Separator {
Layout.fillWidth: true
@ -113,7 +113,7 @@ ColumnLayout {
moreButtonEnabled: true
title: qsTr("Address")
subTitle: {
let address = root.account && root.account.address ? root.account.address: ""
let address = !!root.account && root.account.address ? root.account.address: ""
return WalletUtils.colorizedChainPrefix(d.preferredSharingNetworkShortNames) + address
}
onButtonClicked: addressMenu.openMenu(this)
@ -147,15 +147,15 @@ ColumnLayout {
Layout.fillWidth: true
title: qsTr("Origin")
subTitle: {
if(keyPair) {
switch(keyPair.pairType) {
case Constants.keycard.keyPairType.profile:
if(!!root.keyPair) {
switch(root.keyPair.pairType) {
case Constants.keypair.type.profile:
return qsTr("Derived from your default Status keypair")
case Constants.keycard.keyPairType.seedImport:
case Constants.keypair.type.seedImport:
return qsTr("Imported from seed phrase")
case Constants.keycard.keyPairType.privateKeyImport:
case Constants.keypair.type.privateKeyImport:
return qsTr("Imported from private key")
case Constants.keycard.keyPairType.watchOnly:
case Constants.keypair.type.watchOnly:
return qsTr("Watched address")
default:
return ""
@ -175,8 +175,8 @@ ColumnLayout {
isInteractive: true
copyButtonEnabled: true
title: qsTr("Derivation Path")
subTitle: root.account ? Utils.getPathForDisplay(root.account.path) : ""
onCopyClicked: root.walletStore.copyToClipboard(root.account ? root.account.path : "")
subTitle: !!root.account? Utils.getPathForDisplay(root.account.path) : ""
onCopyClicked: root.walletStore.copyToClipboard(!!root.account? root.account.path : "")
visible: !!subTitle && !d.privateKeyAccount && !d.watchOnlyAccount
}
Separator {
@ -188,7 +188,8 @@ ColumnLayout {
WalletAccountDetailsListItem {
Layout.fillWidth: true
title: qsTr("Stored")
subTitle: keyPair && keyPair.migratedToKeycard ? qsTr("On Keycard"): qsTr("On device")
subTitle: Utils.getKeypairLocation(root.keyPair)
statusListItemSubTitle.color: Utils.getKeypairLocationColor(root.keyPair)
}
}
}
@ -226,7 +227,11 @@ ColumnLayout {
onToggleNetwork: (network) => {
d.preferredSharingNetworksArray = root.walletStore.processPreferredSharingNetworkToggle(d.preferredSharingNetworksArray, network)
}
control.popup.onClosed: root.walletStore.updateWalletAccountPreferredChains(root.account.address, d.preferredSharingNetworksArray.join(":"))
control.popup.onClosed: {
if (!!root.account) {
root.walletStore.updateWalletAccountPreferredChains(root.account.address, d.preferredSharingNetworksArray.join(":"))
}
}
}
]
}
@ -250,11 +255,13 @@ ColumnLayout {
ConfirmationDialog {
id: confirmationPopup
confirmButtonObjectName: "confirmDeleteAccountButton"
headerSettings.title: qsTr("Confirm %1 Removal").arg(root.account ? root.account.name : "")
headerSettings.title: qsTr("Confirm %1 Removal").arg(!!root.account? root.account.name : "")
confirmationText: qsTr("You will not be able to restore viewing access to this account in the future unless you enter this accounts address again.")
confirmButtonLabel: qsTr("Remove Account")
onConfirmButtonClicked: {
root.walletStore.deleteAccount(root.account.address);
if (!!root.account) {
root.walletStore.deleteAccount(root.account.address)
}
confirmationPopup.close()
root.goBack()
}
@ -281,7 +288,7 @@ ColumnLayout {
onCopyToClipboard: root.walletStore.copyToClipboard(address)
}
WalletAccountKeycardMenu {
WalletKeypairAccountMenu {
id: keycardMenu
keyPair: root.keyPair
onRunRenameKeypairFlow: root.runRenameKeypairFlow()

View File

@ -472,11 +472,24 @@ QtObject {
readonly property int nameLengthMax: 20
readonly property int nameLengthMin: 5
readonly property QtObject type: QtObject {
readonly property int unknown: -1
readonly property int profile: 0
readonly property int seedImport: 1
readonly property int privateKeyImport: 2
readonly property int watchOnly: 3 // added just because of UI, impossible to have watch only keypair
}
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 syncedFrom: QtObject {
readonly property string backup: "backup" // means a account is coming from backed up data
readonly property string localPairing: "local-pairing" // means a account is coming from another device when user is reocovering Status account
}
}
readonly property QtObject validators: QtObject {
@ -634,7 +647,6 @@ QtObject {
readonly property int profile: 0
readonly property int seedImport: 1
readonly property int privateKeyImport: 2
readonly property int watchOnly: 3
}
readonly property QtObject shared: QtObject {

View File

@ -822,6 +822,49 @@ QtObject {
return path.split("/").join(" / ")
}
function getKeypairLocationColor(keypair) {
return !keypair ||
keypair.migratedToKeycard ||
keypair.operability === Constants.keypair.operability.fullyOperable ||
keypair.operability === Constants.keypair.operability.partiallyOperable?
Theme.palette.baseColor1 :
Theme.palette.warningColor1
}
function getKeypairLocation(keypair) {
if (!keypair || keypair.pairType === Constants.keypair.type.watchOnly) {
return ""
}
let profileTitle = ""
if (keypair.pairType === Constants.keypair.type.profile) {
profileTitle = Utils.getElidedCompressedPk(keypair.pubKey) + Constants.settingsSection.dotSepString
}
if (keypair.migratedToKeycard) {
return profileTitle + qsTr("On Keycard")
}
if (keypair.operability === Constants.keypair.operability.fullyOperable ||
keypair.operability === Constants.keypair.operability.partiallyOperable) {
return profileTitle + qsTr("On device")
}
if (keypair.operability === Constants.keypair.operability.nonOperable) {
if (keypair.syncedFrom === Constants.keypair.syncedFrom.backup) {
if (keypair.pairType === Constants.keypair.type.seedImport) {
return qsTr("Restored from backup. Re-enter seed phrase to use.")
}
if (keypair.pairType === Constants.keypair.type.privateKeyImport) {
return qsTr("Restored from backup. Re-enter private key to use.")
}
}
if (keypair.syncedFrom !== "" &&
keypair.syncedFrom !== Constants.keypair.syncedFrom.localPairing) {
return qsTr("Synced from %1").arg(keypair.syncedFrom)
}
}
return ""
}
// Leave this function at the bottom of the file as QT Creator messes up the code color after this
function isPunct(c) {
return /(!|\@|#|\$|%|\^|&|\*|\(|\)|\+|\||-|=|\\|{|}|[|]|"|;|'|<|>|\?|,|\.|\/)/.test(c)