mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-22 04:21:44 +00:00
feat/tx-comps: Add TransactionPreview component
Adds a TransactionPreview component as per the spec https://www.notion.so/emizzle/Wallet-transaction-components-2003b78a8d0d41c4ab3d21eb2496fb20 - update ReceiveModal dropdown to match design - long alias and account name support - long name support in account selector - strip all trailing zeros from displayed balances
This commit is contained in:
parent
832518a0e1
commit
3dac87df3d
@ -46,6 +46,8 @@ ModalPopup {
|
|||||||
anchors.topMargin: Style.current.padding
|
anchors.topMargin: Style.current.padding
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: 240
|
width: 240
|
||||||
|
dropdownWidth: parent.width - (Style.current.padding * 2)
|
||||||
|
dropdownAlignment: Select.MenuAlignment.Center
|
||||||
}
|
}
|
||||||
|
|
||||||
Input {
|
Input {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
import QtQuick.Controls 2.13
|
import QtQuick.Controls 2.13
|
||||||
|
import QtQuick.Layouts 1.13
|
||||||
import "../../../imports"
|
import "../../../imports"
|
||||||
import "../../../shared"
|
import "../../../shared"
|
||||||
import "./components"
|
import "./components"
|
||||||
@ -9,10 +10,10 @@ ModalPopup {
|
|||||||
|
|
||||||
//% "Send"
|
//% "Send"
|
||||||
title: qsTrId("command-button-send")
|
title: qsTrId("command-button-send")
|
||||||
height: 600
|
height: 700
|
||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
sendModalContent.amountInput.text = ""
|
sendModalContent.amountInput.selectedAmount = ""
|
||||||
sendModalContent.passwordInput.text = ""
|
sendModalContent.passwordInput.text = ""
|
||||||
sendModalContent.amountInput.forceActiveFocus(Qt.MouseFocusReason)
|
sendModalContent.amountInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||||
}
|
}
|
||||||
@ -24,15 +25,41 @@ ModalPopup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: StyledButton {
|
footer: Item {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Style.current.padding
|
StyledButton {
|
||||||
//% "Send"
|
id: btnBack
|
||||||
label: qsTrId("command-button-send")
|
anchors.left: parent.left
|
||||||
|
label: qsTr("Back")
|
||||||
onClicked: {
|
visible: !btnPreview.visible
|
||||||
sendModalContent.send()
|
onClicked: {
|
||||||
|
btnPreview.visible = true
|
||||||
|
sendModalContent.showInputs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StyledButton {
|
||||||
|
id: btnPreview
|
||||||
|
anchors.right: parent.right
|
||||||
|
label: qsTr("Preview")
|
||||||
|
onClicked: {
|
||||||
|
if (!sendModalContent.validate()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
visible = false
|
||||||
|
sendModalContent.showPreview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StyledButton {
|
||||||
|
id: btnSend
|
||||||
|
anchors.right: parent.right
|
||||||
|
visible: !btnPreview.visible
|
||||||
|
//% "Send"
|
||||||
|
label: qsTrId("command-button-send")
|
||||||
|
onClicked: {
|
||||||
|
sendModalContent.send()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,6 @@ Item {
|
|||||||
property alias passwordInput: txtPassword
|
property alias passwordInput: txtPassword
|
||||||
|
|
||||||
property string passwordValidationError: ""
|
property string passwordValidationError: ""
|
||||||
property string toValidationError: ""
|
|
||||||
property string amountValidationError: ""
|
|
||||||
|
|
||||||
function send() {
|
function send() {
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
@ -20,7 +18,7 @@ Item {
|
|||||||
}
|
}
|
||||||
let result = walletModel.onSendTransaction(selectFromAccount.selectedAccount.address,
|
let result = walletModel.onSendTransaction(selectFromAccount.selectedAccount.address,
|
||||||
selectRecipient.selectedRecipient,
|
selectRecipient.selectedRecipient,
|
||||||
selectAsset.selectedAsset.address,
|
txtAmount.selectedAsset.address,
|
||||||
txtAmount.text,
|
txtAmount.text,
|
||||||
txtPassword.text)
|
txtPassword.text)
|
||||||
|
|
||||||
@ -47,7 +45,17 @@ Item {
|
|||||||
passwordValidationError = ""
|
passwordValidationError = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return passwordValidationError === "" && toValidationError === "" && amountValidationError === "" && isRecipientValid && isAssetAndAmountValid
|
return passwordValidationError === "" && isRecipientValid && isAssetAndAmountValid
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPreview() {
|
||||||
|
pvwTransaction.visible = true
|
||||||
|
txtAmount.visible = selectFromAccount.visible = selectRecipient.visible = txtPassword.visible = gasSelector.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function showInputs() {
|
||||||
|
pvwTransaction.visible = false
|
||||||
|
txtAmount.visible = selectFromAccount.visible = selectRecipient.visible = txtPassword.visible = gasSelector.visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@ -58,6 +66,9 @@ Item {
|
|||||||
title: "Error sending the transaction"
|
title: "Error sending the transaction"
|
||||||
icon: StandardIcon.Critical
|
icon: StandardIcon.Critical
|
||||||
standardButtons: StandardButton.Ok
|
standardButtons: StandardButton.Ok
|
||||||
|
onAccepted: {
|
||||||
|
sendModalContent.showInputs()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MessageDialog {
|
MessageDialog {
|
||||||
id: sendingSuccess
|
id: sendingSuccess
|
||||||
@ -67,6 +78,7 @@ Item {
|
|||||||
standardButtons: StandardButton.Ok
|
standardButtons: StandardButton.Ok
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
closePopup()
|
closePopup()
|
||||||
|
sendModalContent.showInputs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,20 +99,21 @@ Item {
|
|||||||
anchors.topMargin: Style.current.padding
|
anchors.topMargin: Style.current.padding
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
label: qsTr("From account")
|
||||||
onSelectedAccountChanged: {
|
onSelectedAccountChanged: {
|
||||||
txtAmount.selectedAccount = selectFromAccount.selectedAccount
|
txtAmount.selectedAccount = selectFromAccount.selectedAccount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GasSelector {
|
GasSelector {
|
||||||
id: gasSelector
|
id: gasSelector
|
||||||
anchors.top: selectFromAccount.bottom
|
anchors.top: selectFromAccount.bottom
|
||||||
anchors.topMargin: Style.current.bigPadding
|
anchors.topMargin: Style.current.bigPadding
|
||||||
slowestGasPrice: parseFloat(walletModel.safeLowGasPrice)
|
slowestGasPrice: parseFloat(walletModel.safeLowGasPrice)
|
||||||
fastestGasPrice: parseFloat(walletModel.fastestGasPrice)
|
fastestGasPrice: parseFloat(walletModel.fastestGasPrice)
|
||||||
getGasEthValue: walletModel.getGasEthValue
|
getGasEthValue: walletModel.getGasEthValue
|
||||||
getFiatValue: walletModel.getFiatValue
|
getFiatValue: walletModel.getFiatValue
|
||||||
defaultCurrency: walletModel.defaultCurrency
|
defaultCurrency: walletModel.defaultCurrency
|
||||||
}
|
}
|
||||||
|
|
||||||
RecipientSelector {
|
RecipientSelector {
|
||||||
@ -114,6 +127,23 @@ Item {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransactionPreview {
|
||||||
|
id: pvwTransaction
|
||||||
|
visible: false
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
fromAccount: selectFromAccount.selectedAccount
|
||||||
|
gas: {
|
||||||
|
const value = walletModel.getGasEthValue(gasSelector.selectedGasPrice, gasSelector.selectedGasLimit)
|
||||||
|
const fiatValue = walletModel.getFiatValue(value, "ETH", walletModel.defaultCurrency)
|
||||||
|
return { value, "symbol": "ETH", fiatValue }
|
||||||
|
}
|
||||||
|
toAccount: selectRecipient.selectedRecipient
|
||||||
|
asset: txtAmount.selectedAsset
|
||||||
|
amount: { "value": txtAmount.selectedAmount, "fiatValue": txtAmount.selectedFiatAmount }
|
||||||
|
currency: walletModel.defaultCurrency
|
||||||
|
}
|
||||||
|
|
||||||
Input {
|
Input {
|
||||||
id: txtPassword
|
id: txtPassword
|
||||||
//% "Password"
|
//% "Password"
|
||||||
@ -125,6 +155,7 @@ Item {
|
|||||||
textField.echoMode: TextInput.Password
|
textField.echoMode: TextInput.Password
|
||||||
validationError: passwordValidationError
|
validationError: passwordValidationError
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*##^##
|
/*##^##
|
||||||
|
@ -69,4 +69,15 @@ QtObject {
|
|||||||
function isValidAddress(inputValue) {
|
function isValidAddress(inputValue) {
|
||||||
return /0x[a-fA-F0-9]{40}/.test(inputValue)
|
return /0x[a-fA-F0-9]{40}/.test(inputValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes trailing zeros from a string-representation of a number. Throws
|
||||||
|
* if parameter is not a string
|
||||||
|
*/
|
||||||
|
function stripTrailingZeros(strNumber) {
|
||||||
|
if (!(typeof strNumber === "string")) {
|
||||||
|
throw "must be a string"
|
||||||
|
}
|
||||||
|
return strNumber.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,6 +313,7 @@ DISTFILES += \
|
|||||||
shared/AddButton.qml \
|
shared/AddButton.qml \
|
||||||
shared/IconButton.qml \
|
shared/IconButton.qml \
|
||||||
shared/Input.qml \
|
shared/Input.qml \
|
||||||
|
shared/LabelValueRow.qml \
|
||||||
shared/ModalPopup.qml \
|
shared/ModalPopup.qml \
|
||||||
shared/NotificationWindow.qml \
|
shared/NotificationWindow.qml \
|
||||||
shared/PopupMenu.qml \
|
shared/PopupMenu.qml \
|
||||||
@ -332,6 +333,7 @@ DISTFILES += \
|
|||||||
shared/StyledTextField.qml \
|
shared/StyledTextField.qml \
|
||||||
shared/SVGImage.qml \
|
shared/SVGImage.qml \
|
||||||
shared/TextWithLabel.qml \
|
shared/TextWithLabel.qml \
|
||||||
|
shared/TransactionPreview.qml \
|
||||||
shared/img/check.svg \
|
shared/img/check.svg \
|
||||||
shared/img/close.svg \
|
shared/img/close.svg \
|
||||||
shared/img/loading.png \
|
shared/img/loading.png \
|
||||||
|
@ -20,6 +20,7 @@ Item {
|
|||||||
// nothing will be displayed
|
// nothing will be displayed
|
||||||
property string showAssetBalance: ""
|
property string showAssetBalance: ""
|
||||||
property int dropdownWidth: width
|
property int dropdownWidth: width
|
||||||
|
property alias dropdownAlignment: select.menuAlignment
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
visible: showAssetBalance !== ""
|
visible: showAssetBalance !== ""
|
||||||
@ -71,11 +72,10 @@ Item {
|
|||||||
id: selectedTextField
|
id: selectedTextField
|
||||||
text: selectedAccount.name
|
text: selectedAccount.name
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.current.bigPadding
|
|
||||||
anchors.left: selectedIconImg.right
|
anchors.left: selectedIconImg.right
|
||||||
anchors.leftMargin: 8
|
anchors.leftMargin: 8
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: select.contentWidth - (Style.current.padding + selectedIconImg.width + anchors.leftMargin)
|
||||||
font.pixelSize: 15
|
font.pixelSize: 15
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
height: 22
|
height: 22
|
||||||
@ -143,15 +143,17 @@ Item {
|
|||||||
id: column
|
id: column
|
||||||
anchors.left: iconImg.right
|
anchors.left: iconImg.right
|
||||||
anchors.leftMargin: 14
|
anchors.leftMargin: 14
|
||||||
|
anchors.right: txtFiatBalance.left
|
||||||
|
anchors.rightMargin: 8
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: accountName
|
id: accountName
|
||||||
text: name
|
text: name
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.left: parent.left
|
|
||||||
font.pixelSize: 15
|
font.pixelSize: 15
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
height: 22
|
height: 22
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +168,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
StyledText {
|
StyledText {
|
||||||
|
id: txtFiatBalance
|
||||||
anchors.right: fiatCurrencySymbol.left
|
anchors.right: fiatCurrencySymbol.left
|
||||||
anchors.rightMargin: 4
|
anchors.rightMargin: 4
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
@ -9,11 +9,10 @@ Item {
|
|||||||
property string greaterThan0ErrorMessage: qsTr("Must be greater than 0")
|
property string greaterThan0ErrorMessage: qsTr("Must be greater than 0")
|
||||||
//% "This needs to be a number"
|
//% "This needs to be a number"
|
||||||
property string invalidInputErrorMessage: qsTrId("this-needs-to-be-a-number")
|
property string invalidInputErrorMessage: qsTrId("this-needs-to-be-a-number")
|
||||||
//% "You need to enter an amount"
|
property string noInputErrorMessage: qsTr("Please enter an amount")
|
||||||
property string noInputErrorMessage: qsTrId("you-need-to-enter-an-amount")
|
|
||||||
property string defaultCurrency: "USD"
|
property string defaultCurrency: "USD"
|
||||||
property string fiatBalance: "0.00"
|
property alias selectedFiatAmount: txtFiatBalance.text
|
||||||
property alias text: inputAmount.text
|
property alias selectedAmount: inputAmount.text
|
||||||
property var selectedAccount
|
property var selectedAccount
|
||||||
property alias selectedAsset: selectAsset.selectedAsset
|
property alias selectedAsset: selectAsset.selectedAsset
|
||||||
property var getFiatValue: function () {}
|
property var getFiatValue: function () {}
|
||||||
@ -62,7 +61,7 @@ Item {
|
|||||||
if (!selectAsset.selectedAsset) {
|
if (!selectAsset.selectedAsset) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txtBalance.text = selectAsset.selectedAsset.value
|
txtBalance.text = Utils.stripTrailingZeros(selectAsset.selectedAsset.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@ -83,7 +82,7 @@ Item {
|
|||||||
StyledText {
|
StyledText {
|
||||||
id: txtBalance
|
id: txtBalance
|
||||||
property bool hovered: false
|
property bool hovered: false
|
||||||
text: selectAsset.selectedAsset ? selectAsset.selectedAsset.value : "0.00"
|
text: selectAsset.selectedAsset ? Utils.stripTrailingZeros(selectAsset.selectedAsset.value) : "0.00"
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
font.pixelSize: 13
|
font.pixelSize: 13
|
||||||
@ -146,7 +145,7 @@ Item {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Style.current.smallPadding
|
anchors.rightMargin: Style.current.smallPadding
|
||||||
onSelectedAssetChanged: {
|
onSelectedAssetChanged: {
|
||||||
txtBalance.text = selectAsset.selectedAsset.value
|
txtBalance.text = Utils.stripTrailingZeros(selectAsset.selectedAsset.value)
|
||||||
if (inputAmount.text === "" || isNan(inputAmount.text)) {
|
if (inputAmount.text === "" || isNan(inputAmount.text)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -168,7 +167,7 @@ Item {
|
|||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||||
text: root.fiatBalance
|
text: "0.00"
|
||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Style.current.transparent
|
color: Style.current.transparent
|
||||||
|
@ -28,6 +28,7 @@ Item {
|
|||||||
select.select.border.width = 0
|
select.select.border.width = 0
|
||||||
validationErrorText.visible = false
|
validationErrorText.visible = false
|
||||||
}
|
}
|
||||||
|
return isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
Select {
|
Select {
|
||||||
|
@ -23,9 +23,13 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateGasEthValue() {
|
function updateGasEthValue() {
|
||||||
|
// causes error on application load without this null check
|
||||||
|
if (!inputGasPrice || !inputGasLimit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
let ethValue = root.getGasEthValue(inputGasPrice.text, inputGasLimit.text)
|
let ethValue = root.getGasEthValue(inputGasPrice.text, inputGasLimit.text)
|
||||||
let fiatValue = root.getFiatValue(ethValue, "ETH", root.defaultCurrency)
|
let fiatValue = root.getFiatValue(ethValue, "ETH", root.defaultCurrency)
|
||||||
let summary = ethValue + " ETH ~" + fiatValue + " " + root.defaultCurrency.toUpperCase()
|
let summary = Utils.stripTrailingZeros(ethValue) + " ETH ~" + fiatValue + " " + root.defaultCurrency.toUpperCase()
|
||||||
labelGasPriceSummary.text = summary
|
labelGasPriceSummary.text = summary
|
||||||
labelGasPriceSummaryAdvanced.text = summary
|
labelGasPriceSummaryAdvanced.text = summary
|
||||||
}
|
}
|
||||||
|
32
ui/shared/LabelValueRow.qml
Normal file
32
ui/shared/LabelValueRow.qml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Controls 2.13
|
||||||
|
import QtQuick.Layouts 1.13
|
||||||
|
import "../imports"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: itmFrom
|
||||||
|
property alias label: txtLabel.text
|
||||||
|
property alias value: itmValue.children
|
||||||
|
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
width: parent.width
|
||||||
|
height: 52
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: txtLabel
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: parent.height
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
width: 105
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
id: itmValue
|
||||||
|
anchors.left: txtLabel.right
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
height: parent.height
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,12 @@ Item {
|
|||||||
height: (readOnly ? inpReadOnly.height : inpAddress.height) + txtLabel.height
|
height: (readOnly ? inpReadOnly.height : inpAddress.height) + txtLabel.height
|
||||||
readonly property string addressValidationError: qsTr("Invalid ethereum address")
|
readonly property string addressValidationError: qsTr("Invalid ethereum address")
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
Address,
|
||||||
|
Contact,
|
||||||
|
Account
|
||||||
|
}
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
let isValid = true
|
let isValid = true
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
@ -97,7 +103,7 @@ Item {
|
|||||||
if (root.readOnly) {
|
if (root.readOnly) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
root.selectedRecipient = { address: selectedAddress }
|
root.selectedRecipient = { address: selectedAddress, type: RecipientSelector.Type.Address }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +121,8 @@ Item {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(selectedContact && selectedContact.address) {
|
if(selectedContact && selectedContact.address) {
|
||||||
root.selectedRecipient = { name: selectedContact.name, address: selectedContact.address }
|
const { address, name, alias, isContact, identicon, ensVerified } = selectedContact
|
||||||
|
root.selectedRecipient = { address, name, alias, isContact, identicon, ensVerified, type: RecipientSelector.Type.Contact }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +141,8 @@ Item {
|
|||||||
if (root.readOnly) {
|
if (root.readOnly) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
root.selectedRecipient = { address: selectedAccount.address }
|
const { address, name, iconColor, assets, fiatBalance } = selectedAccount
|
||||||
|
root.selectedRecipient = { address, name, iconColor, assets, fiatBalance, type: RecipientSelector.Type.Account }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressSourceSelector {
|
AddressSourceSelector {
|
||||||
@ -149,21 +157,31 @@ Item {
|
|||||||
if (root.readOnly) {
|
if (root.readOnly) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let address, name
|
||||||
switch (selectedSource) {
|
switch (selectedSource) {
|
||||||
case "Address":
|
case "Address":
|
||||||
inpAddress.visible = true
|
inpAddress.visible = true
|
||||||
selContact.visible = selAccount.visible = false
|
selContact.visible = selAccount.visible = false
|
||||||
root.height = Qt.binding(function() { return inpAddress.height + txtLabel.height })
|
root.height = Qt.binding(function() { return inpAddress.height + txtLabel.height })
|
||||||
|
root.selectedRecipient = { address: inpAddress.selectedAddress, type: RecipientSelector.Type.Address }
|
||||||
break;
|
break;
|
||||||
case "Contact":
|
case "Contact":
|
||||||
selContact.visible = true
|
selContact.visible = true
|
||||||
inpAddress.visible = selAccount.visible = false
|
inpAddress.visible = selAccount.visible = false
|
||||||
root.height = Qt.binding(function() { return selContact.height + txtLabel.height })
|
root.height = Qt.binding(function() { return selContact.height + txtLabel.height })
|
||||||
|
let { alias, isContact, identicon, ensVerified } = selContact.selectedContact
|
||||||
|
address = selContact.selectedContact.address
|
||||||
|
name = selContact.selectedContact.name
|
||||||
|
root.selectedRecipient = { address, name, alias, isContact, identicon, ensVerified, type: RecipientSelector.Type.Contact }
|
||||||
break;
|
break;
|
||||||
case "My account":
|
case "My account":
|
||||||
selAccount.visible = true
|
selAccount.visible = true
|
||||||
inpAddress.visible = selContact.visible = false
|
inpAddress.visible = selContact.visible = false
|
||||||
root.height = Qt.binding(function() { return selAccount.height + txtLabel.height })
|
root.height = Qt.binding(function() { return selAccount.height + txtLabel.height })
|
||||||
|
const { iconColor, assets, fiatBalance } = selAccount.selectedAccount
|
||||||
|
address = selAccount.selectedAccount.address
|
||||||
|
name = selAccount.selectedAccount.name
|
||||||
|
root.selectedRecipient = { address, name, iconColor, assets, fiatBalance, type: RecipientSelector.Type.Account }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ import "../imports"
|
|||||||
Item {
|
Item {
|
||||||
enum MenuAlignment {
|
enum MenuAlignment {
|
||||||
Left,
|
Left,
|
||||||
Right
|
Right,
|
||||||
|
Center
|
||||||
}
|
}
|
||||||
property string label: ""
|
property string label: ""
|
||||||
readonly property bool hasLabel: label !== ""
|
readonly property bool hasLabel: label !== ""
|
||||||
@ -18,9 +19,11 @@ Item {
|
|||||||
property color bgColorHover: bgColor
|
property color bgColorHover: bgColor
|
||||||
property alias selectedItemView: selectedItemContainer.children
|
property alias selectedItemView: selectedItemContainer.children
|
||||||
property int caretRightMargin: Style.current.padding
|
property int caretRightMargin: Style.current.padding
|
||||||
|
property int caretLeftMargin: 8
|
||||||
property alias select: inputRectangle
|
property alias select: inputRectangle
|
||||||
property int menuAlignment: Select.MenuAlignment.Right
|
property int menuAlignment: Select.MenuAlignment.Right
|
||||||
property Item zeroItemsView: Item {}
|
property Item zeroItemsView: Item {}
|
||||||
|
property int contentWidth: inputRectangle.width - (caret.width + caretRightMargin + caretLeftMargin)
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
@ -147,7 +150,17 @@ Item {
|
|||||||
selectMenu.close()
|
selectMenu.close()
|
||||||
} else {
|
} else {
|
||||||
const rightOffset = inputRectangle.width - selectMenu.width
|
const rightOffset = inputRectangle.width - selectMenu.width
|
||||||
const offset = root.menuAlignment === Select.MenuAlignment.Left ? 0 : rightOffset
|
let offset = rightOffset
|
||||||
|
switch (root.menuAlignment) {
|
||||||
|
case Select.MenuAlignment.Left:
|
||||||
|
offset = 0
|
||||||
|
break
|
||||||
|
case Select.MenuAlignment.Right:
|
||||||
|
offset = rightOffset
|
||||||
|
break
|
||||||
|
case Select.MenuAlignment.Center:
|
||||||
|
offset = rightOffset / 2
|
||||||
|
}
|
||||||
selectMenu.popup(inputRectangle.x + offset, inputRectangle.y + inputRectangle.height + 8)
|
selectMenu.popup(inputRectangle.x + offset, inputRectangle.y + inputRectangle.height + 8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
361
ui/shared/TransactionPreview.qml
Normal file
361
ui/shared/TransactionPreview.qml
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Controls 2.13
|
||||||
|
import QtQuick.Layouts 1.13
|
||||||
|
import QtGraphicalEffects 1.13
|
||||||
|
import "../imports"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
property var fromAccount: ({})
|
||||||
|
property var toAccount: ({ type: "" })
|
||||||
|
property var asset: ({ name: "", symbol: "" })
|
||||||
|
property var amount: ({ value: "", fiatValue: "", currency: "" })
|
||||||
|
property string currency: "USD"
|
||||||
|
property var gas: ({ value: "", symbol: "", fiatValue: "" })
|
||||||
|
height: itmFrom.height
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
LabelValueRow {
|
||||||
|
id: itmFrom
|
||||||
|
label: qsTr("From")
|
||||||
|
value: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: root.fromAccount.name
|
||||||
|
elide: Text.ElideRight
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: imgFromWallet.left
|
||||||
|
anchors.rightMargin: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
SVGImage {
|
||||||
|
id: imgFromWallet
|
||||||
|
sourceSize.height: 18
|
||||||
|
sourceSize.width: 18
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: "../app/img/walletIcon.svg"
|
||||||
|
}
|
||||||
|
ColorOverlay {
|
||||||
|
anchors.fill: imgFromWallet
|
||||||
|
source: imgFromWallet
|
||||||
|
color: fromAccount.iconColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LabelValueRow {
|
||||||
|
id: itmTo
|
||||||
|
property var props: { "primaryText": "replace1", "secondaryText": "me1" }
|
||||||
|
label: qsTr("Recipient")
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "Address"
|
||||||
|
when: root.toAccount.type === RecipientSelector.Type.Address
|
||||||
|
PropertyChanges {
|
||||||
|
target: txtToPrimary
|
||||||
|
text: root.toAccount.address
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
anchors.leftMargin: 190
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: txtToSecondary
|
||||||
|
width: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "Contact"
|
||||||
|
when: root.toAccount.type === RecipientSelector.Type.Contact && !!root.toAccount.address
|
||||||
|
PropertyChanges {
|
||||||
|
target: metSecondary
|
||||||
|
text: root.toAccount.ensVerified ? root.toAccount.alias : root.toAccount.address
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: txtToSecondary
|
||||||
|
anchors.rightMargin: Style.current.padding + idtToContact.width + 8
|
||||||
|
width: metSecondary.elidedWidth
|
||||||
|
text: metSecondary.elidedText
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: idtToContact
|
||||||
|
source: root.toAccount.identicon
|
||||||
|
visible: true
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: txtToPrimary
|
||||||
|
text: Utils.removeStatusEns(root.toAccount.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "Account"
|
||||||
|
when: root.toAccount.type === RecipientSelector.Type.Account && !!root.toAccount.address
|
||||||
|
PropertyChanges {
|
||||||
|
target: metSecondary
|
||||||
|
text: root.toAccount.address
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: txtToSecondary
|
||||||
|
anchors.rightMargin: Style.current.padding + imgToWallet.width + 8
|
||||||
|
text: metSecondary.elidedText
|
||||||
|
width: metSecondary.elidedWidth
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: imgToWallet
|
||||||
|
visible: true
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: ovlToWallet
|
||||||
|
visible: true
|
||||||
|
color: root.toAccount.iconColor
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: txtToPrimary
|
||||||
|
text: root.toAccount.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
value: Item {
|
||||||
|
id: recipientRoot
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: txtToPrimary
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: txtToSeparator.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtToSeparator
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: " • "
|
||||||
|
visible: txtToSecondary.visible && txtToSecondary.width > 0
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: txtToSecondary.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtToSecondary
|
||||||
|
visible: true
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
TextMetrics {
|
||||||
|
id: metSecondary
|
||||||
|
elideWidth: 102
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
}
|
||||||
|
SVGImage {
|
||||||
|
id: imgToWallet
|
||||||
|
visible: false
|
||||||
|
sourceSize.height: 18
|
||||||
|
sourceSize.width: 18
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: "../app/img/walletIcon.svg"
|
||||||
|
}
|
||||||
|
ColorOverlay {
|
||||||
|
id: ovlToWallet
|
||||||
|
anchors.fill: imgToWallet
|
||||||
|
visible: false
|
||||||
|
source: imgToWallet
|
||||||
|
}
|
||||||
|
Identicon {
|
||||||
|
id: idtToContact
|
||||||
|
visible: false
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LabelValueRow {
|
||||||
|
id: itmAsset
|
||||||
|
label: qsTr("Asset")
|
||||||
|
value: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: (root.asset && root.asset.name) ? root.asset.name : ""
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: txtAssetSymbol.left
|
||||||
|
anchors.rightMargin: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtAssetSymbol
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: (root.asset && root.asset.symbol) ? root.asset.symbol : ""
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: imgAsset.left
|
||||||
|
anchors.rightMargin: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
id: imgAsset
|
||||||
|
sourceSize.height: 32
|
||||||
|
sourceSize.width: 32
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: "../app/img/tokens/" + ((root.asset && root.asset.symbol) ? root.asset.symbol : "ETH") + ".png"
|
||||||
|
onStatusChanged: {
|
||||||
|
if (status == Image.Error) {
|
||||||
|
source = "../app/img/tokens/0-native.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LabelValueRow {
|
||||||
|
id: itmAmount
|
||||||
|
label: qsTr("Amount")
|
||||||
|
value: Item {
|
||||||
|
id: amountRoot
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: root.amount.value ? Utils.stripTrailingZeros(root.amount.value) : ""
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: txtAmountSymbol.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtAmountSymbol
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: ((root.asset && root.asset.symbol) ? root.asset.symbol : "") + " •"
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: txtAmountFiat.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtAmountFiat
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: "~" + (root.amount.fiatValue ? root.amount.fiatValue : "0.00")
|
||||||
|
anchors.right: txtAmountCurrency.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtAmountCurrency
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: root.currency.toUpperCase()
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LabelValueRow {
|
||||||
|
id: itmNetworkFee
|
||||||
|
label: qsTr("Network fee")
|
||||||
|
value: Item {
|
||||||
|
id: networkFeeRoot
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: (root.gas && root.gas.value) ? Utils.stripTrailingZeros(root.gas.value) : ""
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: txtFeeSymbol.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtFeeSymbol
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: ((root.gas && root.gas.symbol) ? root.gas.symbol : "") + " •"
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: txtFeeFiat.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtFeeFiat
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: "~" + ((root.gas && root.gas.fiatValue) ? root.gas.fiatValue : "0.00")
|
||||||
|
anchors.right: txtFeeCurrency.left
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
id: txtFeeCurrency
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: root.currency.toUpperCase()
|
||||||
|
color: Style.current.secondaryText
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user