feat(@desktop/wallet): Using Floating Buttons in the Send Modal
fixes #6228
This commit is contained in:
parent
9b298e4ace
commit
e6f809b921
|
@ -895,7 +895,7 @@ Item {
|
||||||
}
|
}
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (!!sendModal.selectedAccount) {
|
if (!!sendModal.selectedAccount) {
|
||||||
item.preSelectedAccount = sendModal.selectedAccount
|
item.selectedAccount = sendModal.selectedAccount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ StatusInput {
|
||||||
|
|
||||||
property string cursorColor: Theme.palette.primaryColor1
|
property string cursorColor: Theme.palette.primaryColor1
|
||||||
|
|
||||||
height: input.edit.height
|
|
||||||
leftPadding: 0
|
leftPadding: 0
|
||||||
rightPadding: 0
|
rightPadding: 0
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ StatusModal {
|
||||||
|
|
||||||
property var store
|
property var store
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
property var preSelectedAccount
|
property var selectedAccount: store.currentAccount
|
||||||
property var preSelectedRecipient
|
property var preSelectedRecipient
|
||||||
property bool launchedFromChat: false
|
property bool launchedFromChat: false
|
||||||
property MessageDialog sendingError: MessageDialog {
|
property MessageDialog sendingError: MessageDialog {
|
||||||
|
@ -40,10 +40,10 @@ StatusModal {
|
||||||
stack.currentGroup.isPending = true
|
stack.currentGroup.isPending = true
|
||||||
let success = false
|
let success = false
|
||||||
success = popup.store.transfer(
|
success = popup.store.transfer(
|
||||||
advancedHeader.accountSelector.selectedAccount.address,
|
popup.selectedAccount.address,
|
||||||
advancedHeader.recipientSelector.selectedRecipient.address,
|
recipientSelector.selectedRecipient.address,
|
||||||
advancedHeader.assetSelector.selectedAsset.symbol,
|
assetSelector.selectedAsset.symbol,
|
||||||
advancedHeader.amountToSendInput.text,
|
amountToSendInput.text,
|
||||||
gasSelector.selectedGasLimit,
|
gasSelector.selectedGasLimit,
|
||||||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||||
gasSelector.selectedTipLimit,
|
gasSelector.selectedTipLimit,
|
||||||
|
@ -57,7 +57,7 @@ StatusModal {
|
||||||
|
|
||||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||||
networkSelector.suggestedRoutes = popup.store.suggestedRoutes(
|
networkSelector.suggestedRoutes = popup.store.suggestedRoutes(
|
||||||
advancedHeader.accountSelector.selectedAccount.address, advancedHeader.amountToSendInput.text, advancedHeader.assetSelector.selectedAsset.symbol
|
popup.selectedAccount.address, amountToSendInput.text, assetSelector.selectedAsset.symbol
|
||||||
)
|
)
|
||||||
if (networkSelector.suggestedRoutes.length) {
|
if (networkSelector.suggestedRoutes.length) {
|
||||||
networkSelector.selectedNetwork = networkSelector.suggestedRoutes[0]
|
networkSelector.selectedNetwork = networkSelector.suggestedRoutes[0]
|
||||||
|
@ -70,84 +70,244 @@ StatusModal {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
readonly property string maxFiatBalance: Utils.stripTrailingZeros(parseFloat(assetSelector.selectedAsset.totalBalance).toFixed(4))
|
||||||
|
readonly property bool isReady: amountToSendInput.valid && !amountToSendInput.pending && recipientSelector.isValid && !recipientSelector.isPending
|
||||||
|
onIsReadyChanged: {
|
||||||
|
if(!isReady && stack.isLastGroup)
|
||||||
|
stack.back()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: 556
|
width: 556
|
||||||
// To-Do as per design once the account selector become floating the heigth can be as defined in design as 595
|
height: 595
|
||||||
height: 670
|
|
||||||
showHeader: false
|
showHeader: false
|
||||||
showFooter: false
|
showFooter: false
|
||||||
showAdvancedFooter: !!popup.advancedHeader ? popup.advancedHeader.isReady && gasValidator.isValid : false
|
showAdvancedFooter: d.isReady && gasValidator.isValid
|
||||||
showAdvancedHeader: true
|
showAdvancedHeader: true
|
||||||
|
|
||||||
|
onSelectedAccountChanged: popup.recalculateRoutesAndFees()
|
||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
if(!!advancedHeader) {
|
amountToSendInput.input.edit.forceActiveFocus()
|
||||||
advancedHeader.amountToSendInput.input.edit.forceActiveFocus()
|
|
||||||
|
|
||||||
if(popup.launchedFromChat) {
|
assetSelector.assets = Qt.binding(function() {
|
||||||
advancedHeader.recipientSelector.selectedType = RecipientSelector.Type.Contact
|
if (popup.selectedAccount) {
|
||||||
advancedHeader.recipientSelector.readOnly = true
|
return popup.selectedAccount.assets
|
||||||
advancedHeader.recipientSelector.selectedRecipient = popup.preSelectedRecipient
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}
|
if(popup.launchedFromChat) {
|
||||||
if(popup.preSelectedAccount) {
|
recipientSelector.selectedType = RecipientSelector.Type.Contact
|
||||||
advancedHeader.accountSelector.selectedAccount = popup.preSelectedAccount
|
recipientSelector.readOnly = true
|
||||||
}
|
recipientSelector.selectedRecipient = popup.preSelectedRecipient
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.recalculateRoutesAndFees()
|
popup.recalculateRoutesAndFees()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasFloatingButtons: true
|
||||||
advancedHeaderComponent: SendModalHeader {
|
advancedHeaderComponent: SendModalHeader {
|
||||||
store: popup.store
|
model: popup.store.accounts
|
||||||
contactsStore: popup.contactsStore
|
selectedAccount: popup.selectedAccount
|
||||||
estimateGas: function() {
|
onUpdatedSelectedAccount: {
|
||||||
if(popup.contentItem.currentGroup.isValid)
|
popup.selectedAccount = account
|
||||||
gasSelector.estimateGas()
|
|
||||||
}
|
|
||||||
|
|
||||||
onAssetChanged: function() {
|
|
||||||
popup.recalculateRoutesAndFees()
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelectedAccountChanged: function() {
|
|
||||||
popup.recalculateRoutesAndFees()
|
|
||||||
}
|
|
||||||
|
|
||||||
onAmountToSendChanged: function() {
|
|
||||||
popup.recalculateRoutesAndFees()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: TransactionStackView {
|
TransactionStackView {
|
||||||
id: stack
|
id: stack
|
||||||
property alias currentGroup: stack.currentGroup
|
property alias currentGroup: stack.currentGroup
|
||||||
anchors.leftMargin: Style.current.xlPadding
|
anchors.leftMargin: Style.current.xlPadding
|
||||||
anchors.topMargin: (!!advancedHeader ? advancedHeader.height: 0) + Style.current.smallPadding
|
anchors.topMargin: Style.current.xlPadding
|
||||||
anchors.rightMargin: Style.current.xlPadding
|
anchors.rightMargin: Style.current.xlPadding
|
||||||
anchors.bottomMargin: popup.showAdvancedFooter && !!advancedFooter ? advancedFooter.height : Style.current.padding
|
anchors.bottomMargin: popup.showAdvancedFooter && !!advancedFooter ? advancedFooter.height : Style.current.padding
|
||||||
TransactionFormGroup {
|
TransactionFormGroup {
|
||||||
id: group1
|
id: group1
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
ScrollView {
|
|
||||||
height: stack.height
|
ColumnLayout {
|
||||||
width: parent.width
|
id: assetAndAmmountSelector
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
RowLayout {
|
||||||
|
spacing: 16
|
||||||
|
StatusBaseText {
|
||||||
|
//% "Send"
|
||||||
|
text: qsTrId("command-button-send")
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
StatusListItemTag {
|
||||||
|
//% "No balances active"
|
||||||
|
title: assetSelector.selectedAsset.totalBalance > 0 ? qsTr("Max: ") + (assetSelector.selectedAsset ? d.maxFiatBalance : "0.00") : qsTr("No balances active")
|
||||||
|
closeButtonVisible: false
|
||||||
|
titleText.font.pixelSize: 12
|
||||||
|
Layout.preferredHeight: 22
|
||||||
|
Layout.preferredWidth: childrenRect.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
AmountInputWithCursor {
|
||||||
|
id: amountToSendInput
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
width: parent.width - assetSelector.width
|
||||||
|
input.placeholderText: "0.00" + " " + assetSelector.selectedAsset.symbol
|
||||||
|
errorMessageCmp.anchors.rightMargin: -100
|
||||||
|
validators: [
|
||||||
|
StatusFloatValidator{
|
||||||
|
id: floatValidator
|
||||||
|
bottom: 0
|
||||||
|
top: d.maxFiatBalance
|
||||||
|
errorMessage: qsTr("Please enter a valid amount")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
Keys.onReleased: {
|
||||||
|
let amount = amountToSendInput.text.trim()
|
||||||
|
|
||||||
|
if (isNaN(amount)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (amount === "") {
|
||||||
|
txtFiatBalance.text = "0.00"
|
||||||
|
} else {
|
||||||
|
txtFiatBalance.text = popup.store.getFiatValue(amount, assetSelector.selectedAsset.symbol, popup.store.currentCurrency)
|
||||||
|
}
|
||||||
|
gasSelector.estimateGas()
|
||||||
|
popup.recalculateRoutesAndFees()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatusAssetSelector {
|
||||||
|
id: assetSelector
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
|
||||||
|
getCurrencyBalanceString: function (currencyBalance) {
|
||||||
|
return Utils.toLocaleString(currencyBalance.toFixed(2), popup.store.locale, {"currency": true}) + " " + popup.store.currentCurrency.toUpperCase()
|
||||||
|
}
|
||||||
|
tokenAssetSourceFn: function (symbol) {
|
||||||
|
return symbol ? Style.png("tokens/" + symbol) : defaultToken
|
||||||
|
}
|
||||||
|
onSelectedAssetChanged: {
|
||||||
|
if (!assetSelector.selectedAsset) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (amountToSendInput.text === "" || isNaN(amountToSendInput.text)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
txtFiatBalance.text = popup.store.getFiatValue(amountToSendInput.text, assetSelector.selectedAsset.symbol, popup.store.currentCurrency)
|
||||||
|
gasSelector.estimateGas()
|
||||||
|
popup.recalculateRoutesAndFees()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
StyledTextField {
|
||||||
|
id: txtFiatBalance
|
||||||
|
color: txtFiatBalance.activeFocus ? Style.current.textColor : Style.current.secondaryText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.pixelSize: 12
|
||||||
|
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||||
|
text: "0.00"
|
||||||
|
selectByMouse: true
|
||||||
|
background: Rectangle {
|
||||||
|
color: Style.current.transparent
|
||||||
|
}
|
||||||
|
padding: 0
|
||||||
|
Keys.onReleased: {
|
||||||
|
let balance = txtFiatBalance.text.trim()
|
||||||
|
if (balance === "" || isNaN(balance)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// To-Do Not refactored yet
|
||||||
|
// amountToSendInput.text = root.getCryptoValue(balance, popup.store.currentCurrency, assetSelector.selectedAsset.symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
id: currencyText
|
||||||
|
text: popup.store.currentCurrency.toUpperCase()
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: Theme.palette.directColor5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: border
|
||||||
|
anchors.top: assetAndAmmountSelector.bottom
|
||||||
|
anchors.topMargin: Style.current.padding
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: -Style.current.xlPadding
|
||||||
|
|
||||||
|
width: popup.width
|
||||||
|
height: 1
|
||||||
|
color: Theme.palette.directColor8
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
DropShadow {
|
||||||
|
anchors.fill: border
|
||||||
|
horizontalOffset: 0
|
||||||
|
verticalOffset: 2
|
||||||
|
radius: 8.0
|
||||||
|
samples: 17
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
source: border
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
id: scrollView
|
||||||
|
height: stack.height - assetAndAmmountSelector.height
|
||||||
|
width: parent.width
|
||||||
|
anchors.top: border.bottom
|
||||||
|
anchors.topMargin: Style.current.halfPadding
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
||||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||||
contentHeight: addressSelector.height + networkSelector.height + gasSelector.height + gasValidator.height
|
contentHeight: recipientSelector.height + addressSelector.height + networkSelector.height + gasSelector.height + gasValidator.height
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
// To-do use standard StatusInput component once the flow for ens name resolution is clear
|
||||||
|
RecipientSelector {
|
||||||
|
anchors.top: assetAndAmmountSelector.bottom
|
||||||
|
anchors.topMargin: Style.current.halfPadding
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
id: recipientSelector
|
||||||
|
accounts: popup.store.accounts
|
||||||
|
contactsStore: popup.contactsStore
|
||||||
|
//% To
|
||||||
|
label: qsTr("To")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
//% "Enter an ENS name or address"
|
||||||
|
input.placeholderText: qsTr("Enter an ENS name or address")
|
||||||
|
input.anchors.leftMargin: 0
|
||||||
|
input.anchors.rightMargin: 0
|
||||||
|
labelFont.pixelSize: 15
|
||||||
|
labelFont.weight: Font.Normal
|
||||||
|
input.height: 56
|
||||||
|
isSelectorVisible: false
|
||||||
|
addContactEnabled: false
|
||||||
|
onSelectedRecipientChanged: gasSelector.estimateGas()
|
||||||
|
}
|
||||||
|
|
||||||
TabAddressSelectorView {
|
TabAddressSelectorView {
|
||||||
id: addressSelector
|
id: addressSelector
|
||||||
anchors.top: parent.top
|
anchors.top: recipientSelector.bottom
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
store: popup.store
|
store: popup.store
|
||||||
onContactSelected: {
|
onContactSelected: {
|
||||||
if(!!popup.advancedHeader)
|
recipientSelector.input.text = address
|
||||||
advancedHeader.recipientSelector.input.text = address
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,20 +332,20 @@ StatusModal {
|
||||||
chainId: networkSelector.selectedNetwork.chainId
|
chainId: networkSelector.selectedNetwork.chainId
|
||||||
width: stack.width
|
width: stack.width
|
||||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||||
if (!(advancedHeader.accountSelector.selectedAccount && advancedHeader.accountSelector.selectedAccount.address &&
|
if (!(popup.selectedAccount && popup.selectedAccount.address &&
|
||||||
advancedHeader.recipientSelector.selectedRecipient && advancedHeader.recipientSelector.selectedRecipient.address &&
|
recipientSelector.selectedRecipient && recipientSelector.selectedRecipient.address &&
|
||||||
advancedHeader.assetSelector.selectedAsset && advancedHeader.assetSelector.selectedAsset.symbol &&
|
assetSelector.selectedAsset && assetSelector.selectedAsset.symbol &&
|
||||||
advancedHeader.amountToSendInput.text)) {
|
amountToSendInput.text)) {
|
||||||
selectedGasLimit = 250000
|
selectedGasLimit = 250000
|
||||||
defaultGasLimit = selectedGasLimit
|
defaultGasLimit = selectedGasLimit
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let gasEstimate = JSON.parse(popup.store.estimateGas(
|
let gasEstimate = JSON.parse(popup.store.estimateGas(
|
||||||
advancedHeader.accountSelector.selectedAccount.address,
|
popup.selectedAccount.address,
|
||||||
advancedHeader.recipientSelector.selectedRecipient.address,
|
recipientSelector.selectedRecipient.address,
|
||||||
advancedHeader.assetSelector.selectedAsset.symbol,
|
assetSelector.selectedAsset.symbol,
|
||||||
advancedHeader.amountToSendInput.text,
|
amountToSendInput.text,
|
||||||
networkSelector.selectedNetwork.chainId || Global.currentChainId,
|
networkSelector.selectedNetwork.chainId || Global.currentChainId,
|
||||||
""))
|
""))
|
||||||
|
|
||||||
|
@ -204,10 +364,10 @@ StatusModal {
|
||||||
GasValidator {
|
GasValidator {
|
||||||
id: gasValidator
|
id: gasValidator
|
||||||
anchors.top: gasSelector.bottom
|
anchors.top: gasSelector.bottom
|
||||||
selectedAccount: advancedHeader.accountSelector.selectedAccount
|
selectedAccount: popup.selectedAccount
|
||||||
selectedAmount: advancedHeader.amountToSendInput.text === "" ? 0.0
|
selectedAmount: amountToSendInput.text === "" ? 0.0
|
||||||
: parseFloat(advancedHeader.amountToSendInput.text)
|
: parseFloat(amountToSendInput.text)
|
||||||
selectedAsset: advancedHeader.assetSelector.selectedAsset
|
selectedAsset: assetSelector.selectedAsset
|
||||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||||
selectedNetwork: networkSelector.selectedNetwork
|
selectedNetwork: networkSelector.selectedNetwork
|
||||||
}
|
}
|
||||||
|
@ -232,17 +392,17 @@ StatusModal {
|
||||||
advancedFooterComponent: SendModalFooter {
|
advancedFooterComponent: SendModalFooter {
|
||||||
maxFiatFees: gasSelector.maxFiatFees
|
maxFiatFees: gasSelector.maxFiatFees
|
||||||
estimatedTxTimeFlag: gasSelector.estimatedTxTimeFlag
|
estimatedTxTimeFlag: gasSelector.estimatedTxTimeFlag
|
||||||
currentGroupPending: popup.contentItem.currentGroup.isPending
|
currentGroupPending: stack.currentGroup.isPending
|
||||||
currentGroupValid: popup.contentItem.currentGroup.isValid
|
currentGroupValid: stack.currentGroup.isValid
|
||||||
isLastGroup: popup.contentItem.isLastGroup
|
isLastGroup: stack.isLastGroup
|
||||||
onNextButtonClicked: {
|
onNextButtonClicked: {
|
||||||
const validity = popup.contentItem.currentGroup.validate()
|
const validity = stack.currentGroup.validate()
|
||||||
if (validity.isValid && !validity.isPending) {
|
if (validity.isValid && !validity.isPending) {
|
||||||
if (popup.contentItem.isLastGroup) {
|
if (stack.isLastGroup) {
|
||||||
return popup.sendTransaction()
|
return popup.sendTransaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gasSelector.suggestedFees.eip1559Enabled && popup.contentItem.currentGroup === group1 && gasSelector.advancedMode){
|
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === group1 && gasSelector.advancedMode){
|
||||||
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||||
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||||
currentBaseFee: gasSelector.suggestedFees.baseFee,
|
currentBaseFee: gasSelector.suggestedFees.baseFee,
|
||||||
|
@ -255,14 +415,14 @@ StatusModal {
|
||||||
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||||
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||||
onConfirm: function(){
|
onConfirm: function(){
|
||||||
popup.contentItem.next();
|
stack.next();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.contentItem.next()
|
stack.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,15 +432,6 @@ StatusModal {
|
||||||
TransactionSettingsConfirmationPopup {}
|
TransactionSettingsConfirmationPopup {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: advancedHeader
|
|
||||||
onIsReadyChanged: {
|
|
||||||
if(!advancedHeader.isReady && popup.contentItem.isLastGroup)
|
|
||||||
popup.contentItem.back()
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: popup.store.walletSectionTransactionsInst
|
target: popup.store.walletSectionTransactionsInst
|
||||||
onTransactionSent: {
|
onTransactionSent: {
|
||||||
|
|
|
@ -10,217 +10,87 @@ import StatusQ.Popups 0.1
|
||||||
import StatusQ.Components 0.1
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||||
|
|
||||||
import "../controls"
|
import "../controls"
|
||||||
import "../views"
|
import "../views"
|
||||||
|
|
||||||
Rectangle {
|
StatusFloatingButtonsSelector {
|
||||||
id: header
|
id: floatingHeader
|
||||||
|
|
||||||
property alias accountSelector: accountSelector
|
property var selectedAccount
|
||||||
property alias recipientSelector: recipientSelector
|
|
||||||
property alias amountToSendInput: amountToSendInput
|
|
||||||
property alias assetSelector: assetSelector
|
|
||||||
|
|
||||||
property var store
|
signal updatedSelectedAccount(var account)
|
||||||
property var contactsStore
|
|
||||||
property var estimateGas: function() {}
|
|
||||||
property bool isReady: amountToSendInput.valid && !amountToSendInput.pending && recipientSelector.isValid && !recipientSelector.isPending
|
|
||||||
|
|
||||||
signal assetChanged()
|
|
||||||
signal selectedAccountChanged()
|
|
||||||
signal amountToSendChanged()
|
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: _internal
|
id: d
|
||||||
property string maxFiatBalance: Utils.stripTrailingZeros(parseFloat(assetSelector.selectedAsset.totalBalance).toFixed(4))
|
property var firstModelData: null
|
||||||
//% "Please enter a valid amount"
|
|
||||||
property string sendAmountInputErrorMessage: qsTr("Please enter a valid amount")
|
|
||||||
//% "Max:"
|
|
||||||
property string maxString: qsTr("Max: ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
radius: 8
|
delegate: Rectangle {
|
||||||
|
width: button.width
|
||||||
|
height: button.height
|
||||||
|
radius: 8
|
||||||
|
visible: floatingHeader.visibleIndices.includes(index) && walletType !== Constants.watchWalletType
|
||||||
|
color: Theme.palette.statusAppLayout.backgroundColor
|
||||||
|
StatusButton {
|
||||||
|
id: button
|
||||||
|
topPadding: 8
|
||||||
|
bottomPadding: 0
|
||||||
|
implicitHeight: 32
|
||||||
|
defaultLeftPadding: 4
|
||||||
|
text: name
|
||||||
|
icon.emoji: !!emoji ? emoji: ""
|
||||||
|
icon.emojiSize: StatusQUtils.Emoji.size.middle
|
||||||
|
icon.name: !emoji ? "filled-account": ""
|
||||||
|
normalColor: "transparent"
|
||||||
|
highlighted: index === floatingHeader.currentIndex
|
||||||
|
onClicked: {
|
||||||
|
updatedSelectedAccount(model)
|
||||||
|
floatingHeader.currentIndex = index
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
// On startup make the preseected wallet in the floating menu,
|
||||||
|
// and if the selectedAccount is watch only then select 0th item
|
||||||
|
if(index === 0) {
|
||||||
|
d.firstModelData = model
|
||||||
|
}
|
||||||
|
|
||||||
color: Theme.palette.statusModal.backgroundColor
|
if(name !== floatingHeader.selectedAccount.name) {
|
||||||
width: parent.width
|
return
|
||||||
height: headerLayout.height + Style.current.xlPadding + (!!recipientSelector.input.text && recipientSelector.input.hasValidSearchResult ? 70 : 0)
|
}
|
||||||
|
|
||||||
Rectangle {
|
if(name === floatingHeader.selectedAccount.name) {
|
||||||
id: border
|
if(walletType !== Constants.watchWalletType) {
|
||||||
anchors.bottom: parent.bottom
|
// If the selected index wont be displayed, added it to the visible indices
|
||||||
width: parent.width
|
if(index > 2) {
|
||||||
height: parent.radius
|
visibleIndices = [0, 1, index]
|
||||||
color: parent.color
|
}
|
||||||
|
floatingHeader.currentIndex = index
|
||||||
StatusModalDivider {
|
}
|
||||||
anchors.bottom: parent.bottom
|
else {
|
||||||
width: parent.width
|
floatingHeader.currentIndex = 0
|
||||||
|
updatedSelectedAccount(d.firstModelData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
popupMenuDelegate: StatusListItem {
|
||||||
ColumnLayout {
|
implicitWidth: 272
|
||||||
id: headerLayout
|
title: name
|
||||||
spacing: 8
|
subTitle: currencyBalance
|
||||||
width: parent.width
|
icon.emoji: !!emoji ? emoji: ""
|
||||||
anchors.top: parent.top
|
icon.color: model.color
|
||||||
anchors.leftMargin: Style.current.xlPadding
|
icon.name: !emoji ? "filled-account": ""
|
||||||
anchors.rightMargin: Style.current.xlPadding
|
icon.letterSize: 14
|
||||||
anchors.topMargin: Style.current.padding
|
icon.isLetterIdenticon: !!model.emoji
|
||||||
anchors.left: parent.left
|
icon.background.color: Theme.palette.indirectColor1
|
||||||
anchors.right: parent.right
|
onClicked: {
|
||||||
|
updatedSelectedAccount(model)
|
||||||
StatusAccountSelector {
|
floatingHeader.itemSelected(index)
|
||||||
id: accountSelector
|
|
||||||
accounts: header.store.accounts
|
|
||||||
selectedAccount: {
|
|
||||||
const currAcc = header.store.currentAccount
|
|
||||||
if (currAcc.walletType !== Constants.watchWalletType) {
|
|
||||||
return currAcc
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
currency: header.store.currentCurrency
|
|
||||||
width: parent.width
|
|
||||||
label: ""
|
|
||||||
onSelectedAccountChanged: {
|
|
||||||
assetSelector.assets = Qt.binding(function() {
|
|
||||||
if (selectedAccount) {
|
|
||||||
return selectedAccount.assets
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (isValid) { estimateGas() }
|
|
||||||
header.selectedAccountChanged()
|
|
||||||
}
|
|
||||||
showAccountDetails: false
|
|
||||||
selectField.select.height: 32
|
|
||||||
}
|
|
||||||
ColumnLayout {
|
|
||||||
id: assetAndAmmountSelector
|
|
||||||
RowLayout {
|
|
||||||
spacing: 16
|
|
||||||
StatusBaseText {
|
|
||||||
//% "Send"
|
|
||||||
text: qsTrId("command-button-send")
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
StatusListItemTag {
|
|
||||||
//% "No balances active"
|
|
||||||
title: assetSelector.selectedAsset.totalBalance > 0 ? _internal.maxString + (assetSelector.selectedAsset ? _internal.maxFiatBalance : "0.00") : qsTr("No balances active")
|
|
||||||
closeButtonVisible: false
|
|
||||||
titleText.font.pixelSize: 12
|
|
||||||
height: 22
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: childrenRect.height
|
|
||||||
AmountInputWithCursor {
|
|
||||||
id: amountToSendInput
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.left: parent.left
|
|
||||||
width: parent.width - assetSelector.width
|
|
||||||
input.placeholderText: "0.00" + " " + assetSelector.selectedAsset.symbol
|
|
||||||
errorMessageCmp.anchors.rightMargin: -100
|
|
||||||
validators: [
|
|
||||||
StatusFloatValidator{
|
|
||||||
id: floatValidator
|
|
||||||
bottom: 0
|
|
||||||
top: _internal.maxFiatBalance
|
|
||||||
errorMessage: _internal.sendAmountInputErrorMessage
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Keys.onReleased: {
|
|
||||||
let amount = amountToSendInput.text.trim()
|
|
||||||
|
|
||||||
if (isNaN(amount)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (amount === "") {
|
|
||||||
txtFiatBalance.text = "0.00"
|
|
||||||
} else {
|
|
||||||
txtFiatBalance.text = header.store.getFiatValue(amount, assetSelector.selectedAsset.symbol, header.store.currentCurrency)
|
|
||||||
}
|
|
||||||
estimateGas()
|
|
||||||
header.amountToSendChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StatusAssetSelector {
|
|
||||||
id: assetSelector
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: parent.right
|
|
||||||
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
|
|
||||||
getCurrencyBalanceString: function (currencyBalance) {
|
|
||||||
return Utils.toLocaleString(currencyBalance.toFixed(2), header.store.locale, {"currency": true}) + " " + header.store.currentCurrency.toUpperCase()
|
|
||||||
}
|
|
||||||
tokenAssetSourceFn: function (symbol) {
|
|
||||||
return symbol ? Style.png("tokens/" + symbol) : defaultToken
|
|
||||||
}
|
|
||||||
onSelectedAssetChanged: {
|
|
||||||
if (!assetSelector.selectedAsset) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (amountToSendInput.text === "" || isNaN(amountToSendInput.text)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
txtFiatBalance.text = header.store.getFiatValue(amountToSendInput.text, assetSelector.selectedAsset.symbol, header.store.currentCurrency)
|
|
||||||
estimateGas()
|
|
||||||
header.assetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
StyledTextField {
|
|
||||||
id: txtFiatBalance
|
|
||||||
color: txtFiatBalance.activeFocus ? Style.current.textColor : Style.current.secondaryText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
font.pixelSize: 12
|
|
||||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
|
||||||
text: "0.00"
|
|
||||||
selectByMouse: true
|
|
||||||
background: Rectangle {
|
|
||||||
color: Style.current.transparent
|
|
||||||
}
|
|
||||||
padding: 0
|
|
||||||
Keys.onReleased: {
|
|
||||||
let balance = txtFiatBalance.text.trim()
|
|
||||||
if (balance === "" || isNaN(balance)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// To-Do Not refactored yet
|
|
||||||
// amountToSendInput.text = root.getCryptoValue(balance, header.store.currentCurrency, assetSelector.selectedAsset.symbol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
id: currencyText
|
|
||||||
text: header.store.currentCurrency.toUpperCase()
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.palette.directColor5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// To-do use standard StatusInput component once the flow for ens name resolution is clear
|
|
||||||
RecipientSelector {
|
|
||||||
id: recipientSelector
|
|
||||||
accounts: header.store.accounts
|
|
||||||
contactsStore: header.contactsStore
|
|
||||||
//% To
|
|
||||||
label: qsTr("To")
|
|
||||||
Layout.fillWidth: true
|
|
||||||
//% "Enter an ENS name or address"
|
|
||||||
input.placeholderText: qsTr("Enter an ENS name or address")
|
|
||||||
input.anchors.leftMargin: 0
|
|
||||||
input.anchors.rightMargin: 0
|
|
||||||
labelFont.pixelSize: 15
|
|
||||||
labelFont.weight: Font.Normal
|
|
||||||
input.height: 56
|
|
||||||
isSelectorVisible: false
|
|
||||||
addContactEnabled: false
|
|
||||||
onSelectedRecipientChanged: estimateGas()
|
|
||||||
}
|
}
|
||||||
|
visible: !floatingHeader.visibleIndices.includes(index) && walletType !== Constants.watchWalletType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue