chore(@desktop/wallet): sorting out keypair/account menu
This commit is contained in:
parent
f8dd1dc811
commit
6e5469f5aa
|
@ -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:
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -299,3 +299,6 @@ rpc(getCachedCurrencyFormats, "wallet"):
|
|||
|
||||
rpc(fetchAllCurrencyFormats, "wallet"):
|
||||
discard
|
||||
|
||||
rpc(hasPairedDevices, "accounts"):
|
||||
discard
|
|
@ -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 |
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 account’s 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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue