status-desktop/ui/imports/shared/popups/keycard/states/ManageAccounts.qml

330 lines
14 KiB
QML

import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import AppLayouts.Wallet.stores 1.0 as WalletStore
import utils 1.0
import shared.popups 1.0
import "../helpers"
Item {
id: root
property var sharedKeycardModule
property var emojiPopup
signal validation(bool result)
QtObject {
id: d
property var observedAccount: root.sharedKeycardModule.keyPairForProcessing.observedAccount
property bool entryValid: false
property string emptyName: " "
property string accountNameToBeRemoved: ""
property int accountIndexToBeRemoved: -1
property string observedImportingAccountShortAddress: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard?
StatusQUtils.Utils.elideText(root.sharedKeycardModule.keyPairHelper.observedAccount.address, 6, 4)
: ""
onObservedAccountChanged: {
if (d.observedAccount.name.trim().length > 0) {
accountName.text = d.observedAccount.name
}
else {
accountName.text = ""
d.observedAccount.name = d.emptyName
}
if (d.observedAccount.colorId.length === 0) {
let color = Theme.palette.customisationColorsArray[Math.floor(Math.random() * Theme.palette.customisationColorsArray.length)]
let emoji = StatusQUtils.Emoji.getRandomEmoji(StatusQUtils.Emoji.size.verySmall) // TODO: Reuse status-go RandomWalletEmoji
d.observedAccount.colorId = Utils.getIdForColor(color)
d.observedAccount.emoji = emoji
}
let ind = d.evaluateColorIndex(d.observedAccount.colorId)
colorSelection.selectedColorIndex = ind
d.updateValidity()
accountName.input.edit.forceActiveFocus()
}
function updateValidity() {
d.entryValid = d.observedAccount.name.trim().length > 0
root.validation(d.entryValid)
}
function evaluateColorIndex(color) {
for (let i = 0; i < Theme.palette.customisationColorsArray.length; i++) {
if(Theme.palette.customisationColorsArray[i] === color) {
return i
}
}
return 0
}
}
Component.onCompleted: {
d.updateValidity()
accountName.input.edit.forceActiveFocus()
}
Connections {
target: root.emojiPopup
enabled: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.setupNewKeycardNewSeedPhrase ||
root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.setupNewKeycardOldSeedPhrase ||
root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard
function onEmojiSelected (emojiText, atCursor) {
let emoji = StatusQUtils.Emoji.deparse(emojiText)
d.observedAccount.emoji = emoji
}
}
ConfirmationDialog {
id: confirmationPopup
headerSettings.title: qsTr("Remove account")
confirmationText: d.accountNameToBeRemoved.length > 0?
qsTr("Do you want to delete the %1 account?").arg(d.accountNameToBeRemoved)
: qsTr("Do you want to delete the last account?")
confirmButtonLabel: qsTr("Yes, delete this account")
onConfirmButtonClicked: {
confirmationPopup.close();
root.sharedKeycardModule.keyPairForProcessing.removeAccountAtIndex(d.accountIndexToBeRemoved)
}
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Theme.xlPadding
anchors.bottomMargin: Theme.halfPadding
anchors.leftMargin: Theme.xlPadding
anchors.rightMargin: Theme.xlPadding
spacing: Theme.padding
StatusStepper {
id: stepper
Layout.preferredWidth: Constants.keycard.general.keycardNameInputWidth
Layout.alignment: Qt.AlignCenter
titleFontSize: Constants.keycard.general.fontSize2
}
StatusBaseText {
id: title
Layout.alignment: Qt.AlignCenter
font.weight: Font.Bold
}
Rectangle {
id: accountDetails
Layout.preferredWidth: Constants.keycard.general.keycardNameInputWidth
Layout.alignment: Qt.AlignCenter
visible: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard
height: Theme.xlPadding * 2
color: "transparent"
border.color: Theme.palette.baseColor2
border.width: 1
radius: Theme.halfPadding
RowLayout {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Theme.padding
anchors.rightMargin: Theme.padding
ColumnLayout {
StatusBaseText {
text: d.observedImportingAccountShortAddress
wrapMode: Text.WordWrap
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
StatusBaseText {
text: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard?
root.sharedKeycardModule.keyPairHelper.observedAccount.path : ""
wrapMode: Text.WordWrap
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: parent.height
}
ColumnLayout {
StatusBaseText {
text: qsTr("Balance: %1").arg(LocaleUtils.currencyAmountToLocaleString(root.sharedKeycardModule.keyPairHelper.observedAccount.balance))
wrapMode: Text.WordWrap
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
Row {
padding: 0
StatusBaseText {
text: qsTr("View on Etherscan")
wrapMode: Text.WordWrap
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
StatusFlatRoundButton {
height: 20
width: 20
icon.name: "external"
icon.width: 16
icon.height: 16
onClicked: {
let link = Utils.getUrlForAddressOnNetwork(Constants.networkShortChainNames.mainnet,
WalletStore.RootStore.areTestNetworksEnabled,
root.sharedKeycardModule.keyPairHelper.observedAccount.address)
Global.openLink(link)
}
}
}
}
}
}
StatusInput {
id: accountName
Layout.preferredWidth: Constants.keycard.general.keycardNameInputWidth
Layout.alignment: Qt.AlignCenter
charLimit: Constants.keycard.general.keycardNameLength
placeholderText: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard) {
return qsTr("What name should account %1 have?").arg(d.observedImportingAccountShortAddress)
}
return qsTr("What would you like this account to be called?")
}
input.acceptReturn: true
input.isIconSelectable: true
input.leftPadding: Theme.padding
input.asset.color: Utils.getColorForId(d.observedAccount.colorId)
input.asset.emoji: d.observedAccount.emoji
onTextChanged: {
d.observedAccount.name = text.trim().length > 0? text : d.emptyName
d.updateValidity()
}
onKeyPressed: {
if (d.entryValid &&
(input.edit.keyEvent === Qt.Key_Return ||
input.edit.keyEvent === Qt.Key_Enter)) {
event.accepted = true
root.sharedKeycardModule.currentState.doPrimaryAction()
}
}
onIconClicked: {
let inputCoords = accountName.mapToItem(appMain, 0, 0)
root.emojiPopup.open()
root.emojiPopup.emojiSize = StatusQUtils.Emoji.size.verySmall
root.emojiPopup.x = inputCoords.x
root.emojiPopup.y = inputCoords.y + accountName.height + Theme.halfPadding
}
}
StatusColorSelectorGrid {
id: colorSelection
Layout.alignment: Qt.AlignCenter
title.text: qsTr("Colour")
title.font.pixelSize: Constants.keycard.general.fontSize2
model: Theme.palette.customisationColorsArray
onSelectedColorChanged: {
d.observedAccount.colorId = Utils.getIdForColor(selectedColor)
}
}
StatusBaseText {
Layout.alignment: Qt.AlignLeft
text: qsTr("Preview")
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
KeyPairItem {
Layout.preferredWidth: parent.width
tagClickable: true
tagDisplayRemoveAccountButton: root.sharedKeycardModule.currentState.flowType !== Constants.keycardSharedFlow.importFromKeycard
keyPairType: root.sharedKeycardModule.keyPairForProcessing.pairType
keyPairKeyUid: root.sharedKeycardModule.keyPairForProcessing.keyUid
keyPairName: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard?
root.sharedKeycardModule.keyPairHelper.name
: root.sharedKeycardModule.keyPairForProcessing.name
keyPairIcon: root.sharedKeycardModule.keyPairForProcessing.icon
keyPairImage: root.sharedKeycardModule.keyPairForProcessing.image
keyPairDerivedFrom: root.sharedKeycardModule.keyPairForProcessing.derivedFrom
keyPairAccounts: root.sharedKeycardModule.keyPairForProcessing.accounts
keyPairCardLocked: root.sharedKeycardModule.keyPairForProcessing.locked
onRemoveAccount: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard)
return
if (name.trim().length == 0) {
root.sharedKeycardModule.keyPairForProcessing.removeAccountAtIndex(index)
return
}
d.accountIndexToBeRemoved = index
d.accountNameToBeRemoved = name
confirmationPopup.open()
}
onAccountClicked: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard) {
root.sharedKeycardModule.keyPairHelper.setAccountAtIndexAsObservedAccount(index)
}
root.sharedKeycardModule.keyPairForProcessing.setAccountAtIndexAsObservedAccount(index)
}
}
}
states: [
State {
name: Constants.keycardSharedState.manageKeycardAccounts
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.manageKeycardAccounts
PropertyChanges {
target: stepper
visible: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard &&
root.sharedKeycardModule.keyPairHelper.accounts.count > 1
totalSteps: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard?
root.sharedKeycardModule.keyPairHelper.accounts.count : 0
completedSteps: root.sharedKeycardModule.keyPairForProcessing.accounts.count
title: qsTr("Account %1 of %2").arg(completedSteps).arg(totalSteps)
}
PropertyChanges {
target: title
text: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard) {
return qsTr("Name account %1").arg(d.observedImportingAccountShortAddress)
}
return qsTr("Name accounts")
}
font.pixelSize: Constants.keycard.general.fontSize1
color: Theme.palette.directColor1
}
PropertyChanges {
target: accountDetails
visible: root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard &&
root.sharedKeycardModule.keyPairHelper.accounts.count > 1
}
}
]
}