SendModal: new AmountToSend initial integration
- new AmountToSend used in SendModal - MaxSendButton simplified Closes: #15207
This commit is contained in:
parent
613fa4d19f
commit
1e88756c13
|
@ -176,7 +176,7 @@ QObject* ObjectProxyModel::proxyObject(int index)
|
|||
auto parentContext = creationContext
|
||||
? creationContext : m_delegate->engine()->rootContext();
|
||||
|
||||
auto context = new QQmlContext(parentContext/*, submodelObj*/);
|
||||
auto context = new QQmlContext(parentContext);
|
||||
|
||||
auto rowData = new QQmlPropertyMap(context);
|
||||
auto model = sourceModel();
|
||||
|
|
|
@ -1,33 +1,19 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import AppLayouts.Wallet 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusButton {
|
||||
id: root
|
||||
required property string formattedValue
|
||||
property bool markAsInvalid: false
|
||||
|
||||
required property double value
|
||||
required property string symbol
|
||||
required property bool valid
|
||||
property var formatCurrencyAmount: (amount, symbol) => { return "FIXME" }
|
||||
|
||||
readonly property double maxSafeValue: WalletUtils.calculateMaxSafeSendAmount(value, symbol)
|
||||
readonly property string maxSafeValueAsString: maxSafeValue.toLocaleString(locale, 'f', -128)
|
||||
|
||||
locale: LocaleUtils.userInputLocale
|
||||
|
||||
implicitHeight: 22
|
||||
|
||||
type: valid ? StatusBaseButton.Type.Normal : StatusBaseButton.Type.Danger
|
||||
text: qsTr("Max. %1").arg(value === 0 ? locale.zeroDigit : root.formatCurrencyAmount(maxSafeValue, root.symbol))
|
||||
text: qsTr("Max. %1").arg(formattedValue)
|
||||
type: markAsInvalid ? StatusBaseButton.Type.Danger
|
||||
: StatusBaseButton.Type.Normal
|
||||
|
||||
horizontalPadding: 8
|
||||
verticalPadding: 3
|
||||
implicitHeight: 22
|
||||
|
||||
radius: 20
|
||||
font.pixelSize: 12
|
||||
font.weight: Font.Normal
|
||||
|
|
|
@ -10,6 +10,7 @@ import StatusQ.Core 0.1
|
|||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import AppLayouts.Wallet 1.0
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
import AppLayouts.Wallet.stores 1.0
|
||||
import AppLayouts.Wallet.adaptors 1.0
|
||||
|
@ -256,14 +257,24 @@ Control {
|
|||
|
||||
MaxSendButton {
|
||||
id: maxSendButton
|
||||
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.maximumWidth: parent.width
|
||||
objectName: "maxTagButton"
|
||||
|
||||
value: d.maxInputBalance
|
||||
symbol: d.inputSymbol
|
||||
valid: (amountToSendInput.input.valid || !amountToSendInput.input.text) && value > 0
|
||||
formatCurrencyAmount: (amount, symbol) => root.currencyStore.formatCurrencyAmount(amount, symbol, {noSymbol: !amountToSendInput.inputIsFiat})
|
||||
readonly property double maxSafeValue: WalletUtils.calculateMaxSafeSendAmount(
|
||||
d.maxInputBalance, d.inputSymbol)
|
||||
readonly property string maxSafeValueAsString: maxSafeValue.toLocaleString(
|
||||
LocaleUtils.userInputLocale, 'f', -128)
|
||||
|
||||
markAsInvalid: (!amountToSendInput.input.valid && !!amountToSendInput.input.text)
|
||||
|| d.maxInputBalance === 0
|
||||
|
||||
formattedValue:
|
||||
d.maxInputBalance === 0 ? LocaleUtils.userInputLocale.zeroDigit
|
||||
: root.currencyStore.formatCurrencyAmount(
|
||||
maxSafeValue, d.inputSymbol,
|
||||
{ noSymbol: !amountToSendInput.inputIsFiat })
|
||||
|
||||
visible: d.isSelectedHoldingValidAsset && root.swapSide === SwapInputPanel.SwapSide.Pay
|
||||
|
||||
|
|
|
@ -73,9 +73,9 @@ StatusDialog {
|
|||
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||
if(!!popup.preSelectedAccount && !!holdingSelector.selectedItem
|
||||
&& recipientInputLoader.ready && (amountToSendInput.inputNumberValid || d.isCollectiblesTransfer)) {
|
||||
&& recipientInputLoader.ready && (amountToSend.ready || d.isCollectiblesTransfer)) {
|
||||
popup.isLoading = true
|
||||
popup.store.suggestedRoutes(d.isCollectiblesTransfer ? "1" : amountToSendInput.cryptoValueToSend)
|
||||
popup.store.suggestedRoutes(d.isCollectiblesTransfer ? "1" : amountToSend.amount)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -94,15 +94,34 @@ StatusDialog {
|
|||
popup.preSelectedSendType === Constants.SendType.StickersBuy
|
||||
|
||||
readonly property var currencyStore: store.currencyStore
|
||||
readonly property int errorType: !amountToSendInput.input.valid && (!isCollectiblesTransfer) ? Constants.SendAmountExceedsBalance :
|
||||
(popup.bestRoutes && popup.bestRoutes.count === 0 &&
|
||||
!!amountToSendInput.input.text && recipientInputLoader.ready && !popup.isLoading) ?
|
||||
Constants.NoRoute : Constants.NoError
|
||||
|
||||
readonly property int errorType: {
|
||||
if (amountToSend.balanceExceeded && !isCollectiblesTransfer)
|
||||
return Constants.SendAmountExceedsBalance
|
||||
|
||||
if (popup.bestRoutes && popup.bestRoutes.count === 0
|
||||
&& !amountToSend.empty && recipientInputLoader.ready
|
||||
&& !popup.isLoading)
|
||||
return Constants.NoRoute
|
||||
|
||||
return Constants.NoError
|
||||
}
|
||||
|
||||
readonly property double maxFiatBalance: isSelectedHoldingValidAsset ? selectedHolding.currentCurrencyBalance : 0
|
||||
readonly property double maxCryptoBalance: isSelectedHoldingValidAsset ? selectedHolding.currentBalance : 0
|
||||
readonly property double maxInputBalance: amountToSendInput.inputIsFiat ? maxFiatBalance : maxCryptoBalance
|
||||
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? currencyStore.currentCurrency : !!d.selectedHolding && !!d.selectedHolding.symbol ? d.selectedHolding.symbol: ""
|
||||
readonly property bool errorMode: popup.isLoading || !recipientInputLoader.ready ? false : errorType !== Constants.NoError || networkSelector.errorMode || !(amountToSendInput.inputNumberValid || d.isCollectiblesTransfer)
|
||||
readonly property double maxInputBalance: amountToSend.fiatMode ? maxFiatBalance : maxCryptoBalance
|
||||
|
||||
readonly property string tokenSymbol: !!d.selectedHolding && !!d.selectedHolding.symbol ? d.selectedHolding.symbol: ""
|
||||
readonly property string inputSymbol: amountToSend.fiatMode ? currencyStore.currentCurrency : tokenSymbol
|
||||
readonly property bool errorMode: {
|
||||
if (popup.isLoading || !recipientInputLoader.ready)
|
||||
return false
|
||||
|
||||
return errorType !== Constants.NoError
|
||||
|| networkSelector.errorMode
|
||||
|| !(amountToSend.ready || d.isCollectiblesTransfer)
|
||||
}
|
||||
|
||||
readonly property string uuid: Utils.uuid()
|
||||
property bool isPendingTx: false
|
||||
property string totalTimeEstimate
|
||||
|
@ -114,9 +133,6 @@ StatusDialog {
|
|||
property var selectedHolding: null
|
||||
property var selectedHoldingType: Constants.TokenType.Unknown
|
||||
readonly property bool isSelectedHoldingValidAsset: !!selectedHolding && selectedHoldingType === Constants.TokenType.ERC20
|
||||
property var hoveredHolding: null
|
||||
property var hoveredHoldingType: Constants.TokenType.Unknown
|
||||
readonly property bool isHoveredHoldingValidAsset: !!hoveredHolding && hoveredHoldingType === Constants.TokenType.ERC20
|
||||
|
||||
onSelectedHoldingChanged: {
|
||||
if (d.selectedHoldingType === Constants.TokenType.ERC20) {
|
||||
|
@ -128,7 +144,7 @@ StatusDialog {
|
|||
d.selectedHoldingType === Constants.TokenType.ERC1155) {
|
||||
let sendType = d.selectedHoldingType === Constants.TokenType.ERC721 ? Constants.SendType.ERC721Transfer : Constants.SendType.ERC1155Transfer
|
||||
store.setSendType(sendType)
|
||||
amountToSendInput.input.text = 1
|
||||
amountToSend.setValue("1")
|
||||
store.setSelectedAssetKey(selectedHolding.contractAddress+":"+selectedHolding.tokenId)
|
||||
store.setRouteEnabledFromChains(selectedHolding.chainId)
|
||||
store.updateRoutePreferredChains(selectedHolding.chainId)
|
||||
|
@ -168,7 +184,7 @@ StatusDialog {
|
|||
}
|
||||
|
||||
onOpened: {
|
||||
amountToSendInput.input.input.edit.forceActiveFocus()
|
||||
amountToSend.forceActiveFocus()
|
||||
|
||||
// IMPORTANT: This step must be the first one since it's storing the send type
|
||||
// into the backend at this stage so that, before this assignement, some properties
|
||||
|
@ -216,7 +232,14 @@ StatusDialog {
|
|||
}
|
||||
|
||||
if(!!popup.preDefinedAmountToSend) {
|
||||
amountToSendInput.input.text = Number(popup.preDefinedAmountToSend).toLocaleString(Qt.locale(), 'f', -128)
|
||||
// TODO: At this stage the number should not be localized. However
|
||||
// in many places when initializing popup the number is provided
|
||||
// in localized version. It should be refactored to provide raw
|
||||
// number consistently. Only the displaying component should apply
|
||||
// final localized formatting.
|
||||
const delocalized = popup.preDefinedAmountToSend.replace(",", ".")
|
||||
|
||||
amountToSend.setValue(delocalized)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,45 +402,98 @@ StatusDialog {
|
|||
}
|
||||
|
||||
MaxSendButton {
|
||||
id: maxButton
|
||||
|
||||
readonly property double maxSafeValue: WalletUtils.calculateMaxSafeSendAmount(
|
||||
d.maxInputBalance, d.inputSymbol)
|
||||
|
||||
readonly property double maxSafeCryptoValue: WalletUtils.calculateMaxSafeSendAmount(
|
||||
d.maxCryptoBalance, d.tokenSymbol)
|
||||
|
||||
formattedValue: d.currencyStore.formatCurrencyAmount(
|
||||
maxSafeValue, d.inputSymbol,
|
||||
{ noSymbol: !amountToSend.fiatMode })
|
||||
|
||||
markAsInvalid: amountToSend.markAsInvalid
|
||||
|
||||
Layout.maximumWidth: 300
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
visible: d.isSelectedHoldingValidAsset || d.isHoveredHoldingValidAsset && !d.isCollectiblesTransfer
|
||||
|
||||
value: d.maxInputBalance
|
||||
symbol: d.inputSymbol
|
||||
valid: amountToSendInput.input.valid || !amountToSendInput.input.text
|
||||
formatCurrencyAmount: (amount, symbol) => d.currencyStore.formatCurrencyAmount(amount, symbol, {noSymbol: !amountToSendInput.inputIsFiat})
|
||||
visible: d.isSelectedHoldingValidAsset && !d.isCollectiblesTransfer
|
||||
|
||||
onClicked: {
|
||||
if (maxSafeValue > 0)
|
||||
amountToSendInput.input.text = maxSafeValueAsString
|
||||
else
|
||||
amountToSendInput.input.input.edit.clear()
|
||||
amountToSendInput.input.forceActiveFocus()
|
||||
if (maxSafeValue > 0) {
|
||||
amountToSend.setValue(SQUtils.AmountsArithmetic.fromNumber(maxSafeValue).toString())
|
||||
}else {
|
||||
amountToSend.clear()
|
||||
}
|
||||
|
||||
amountToSend.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
visible: d.isSelectedHoldingValidAsset && !d.isCollectiblesTransfer
|
||||
AmountToSend {
|
||||
id: amountToSendInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
isBridgeTx: d.isBridgeTx
|
||||
AmountToSendNew {
|
||||
id: amountToSend
|
||||
|
||||
caption: d.isBridgeTx ? qsTr("Amount to bridge")
|
||||
: qsTr("Amount to send")
|
||||
interactive: popup.interactive
|
||||
selectedHolding: d.selectedHolding
|
||||
maxInputBalance: d.maxInputBalance
|
||||
currentCurrency: d.currencyStore.currentCurrency
|
||||
|
||||
readonly property bool balanceExceeded:
|
||||
SQUtils.AmountsArithmetic.cmp(
|
||||
SQUtils.AmountsArithmetic.fromNumber(maxButton.maxSafeCryptoValue, multiplierIndex),
|
||||
SQUtils.AmountsArithmetic.fromString(amount)) === -1
|
||||
|
||||
readonly property bool ready: valid && !empty && !balanceExceeded
|
||||
&& amount !== "0"
|
||||
|
||||
readonly property string selectedSymbol:
|
||||
!!d.selectedHolding && !!d.selectedHolding.symbol
|
||||
? d.selectedHolding.symbol : ""
|
||||
|
||||
// For backward compatibility. To be removed when
|
||||
// dependent components (NetworkSelector, AmountToReceive)
|
||||
// are refactored.
|
||||
readonly property double asNumber: {
|
||||
if (!valid)
|
||||
return 0
|
||||
|
||||
return parseFloat(text.replace(",", "."))
|
||||
}
|
||||
readonly property int minSendCryptoDecimals:
|
||||
!fiatMode ? LocaleUtils.fractionalPartLength(asNumber) : 0
|
||||
readonly property int minReceiveCryptoDecimals:
|
||||
!fiatMode ? minSendCryptoDecimals + 1 : 0
|
||||
readonly property int minSendFiatDecimals:
|
||||
fiatMode ? LocaleUtils.fractionalPartLength(asNumber) : 0
|
||||
readonly property int minReceiveFiatDecimals:
|
||||
fiatMode ? minSendFiatDecimals + 1 : 0
|
||||
// End of to-be-removed part
|
||||
|
||||
decimalPoint: LocaleUtils.userInputLocale.decimalPoint
|
||||
markAsInvalid: balanceExceeded
|
||||
|
||||
// Collectibles do not have decimals
|
||||
multiplierIndex: d.isSelectedHoldingValidAsset && !!holdingSelector.selectedItem && !!holdingSelector.selectedItem.decimals
|
||||
? holdingSelector.selectedItem.decimals
|
||||
: 0
|
||||
multiplierIndex:
|
||||
d.isSelectedHoldingValidAsset
|
||||
&& !!holdingSelector.selectedItem
|
||||
&& !!holdingSelector.selectedItem.decimals
|
||||
? holdingSelector.selectedItem.decimals : 0
|
||||
|
||||
formatCurrencyAmount: d.currencyStore.formatCurrencyAmount
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
input.input.tabNavItem: recipientInputLoader.item
|
||||
Keys.onTabPressed: event.accepted = true
|
||||
price: d.isSelectedHoldingValidAsset
|
||||
? (d.selectedHolding ?
|
||||
d.selectedHolding.marketDetails.currencyPrice.amount : 1)
|
||||
: 1
|
||||
|
||||
formatFiat: amount => d.currencyStore.formatCurrencyAmount(
|
||||
amount, d.currencyStore.currentCurrency)
|
||||
formatBalance: amount => d.currencyStore.formatCurrencyAmount(
|
||||
amount, selectedSymbol)
|
||||
|
||||
onAmountChanged: popup.recalculateRoutesAndFees()
|
||||
}
|
||||
|
||||
// Horizontal spacer
|
||||
|
@ -428,14 +504,14 @@ StatusDialog {
|
|||
Layout.alignment: Qt.AlignRight
|
||||
Layout.fillWidth:true
|
||||
visible: !!popup.bestRoutes && popup.bestRoutes !== undefined &&
|
||||
popup.bestRoutes.count > 0 && amountToSendInput.inputNumberValid
|
||||
popup.bestRoutes.count > 0 && amountToSend.ready
|
||||
isLoading: popup.isLoading
|
||||
selectedHolding: d.selectedHolding
|
||||
isBridgeTx: d.isBridgeTx
|
||||
cryptoValueToReceive: d.totalAmountToReceive
|
||||
inputIsFiat: amountToSendInput.inputIsFiat
|
||||
minCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
|
||||
minFiatDecimals: amountToSendInput.minReceiveFiatDecimals
|
||||
inputIsFiat: amountToSend.fiatMode
|
||||
minCryptoDecimals: amountToSend.minReceiveCryptoDecimals
|
||||
minFiatDecimals: amountToSend.minReceiveFiatDecimals
|
||||
currentCurrency: d.currencyStore.currentCurrency
|
||||
formatCurrencyAmount: d.currencyStore.formatCurrencyAmount
|
||||
}
|
||||
|
@ -520,7 +596,7 @@ StatusDialog {
|
|||
contentWidth: availableWidth
|
||||
|
||||
visible: recipientInputLoader.ready &&
|
||||
(amountToSendInput.inputNumberValid || d.isCollectiblesTransfer)
|
||||
(amountToSend.ready || d.isCollectiblesTransfer)
|
||||
|
||||
objectName: "sendModalScroll"
|
||||
|
||||
|
@ -537,9 +613,9 @@ StatusDialog {
|
|||
interactive: popup.interactive
|
||||
selectedRecipient: popup.preSelectedRecipient
|
||||
ensAddressOrEmpty: recipientInputLoader.resolvedENSAddress
|
||||
amountToSend: amountToSendInput.cryptoValueToSendFloat
|
||||
minSendCryptoDecimals: amountToSendInput.minSendCryptoDecimals
|
||||
minReceiveCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
|
||||
amountToSend: amountToSend.cryptoValueToSendFloat
|
||||
minSendCryptoDecimals: amountToSend.minSendCryptoDecimals
|
||||
minReceiveCryptoDecimals: amountToSend.minReceiveCryptoDecimals
|
||||
selectedAsset: d.selectedHolding
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
errorType: d.errorType
|
||||
|
@ -562,7 +638,8 @@ StatusDialog {
|
|||
maxFiatFees: popup.isLoading ? "..." : d.currencyStore.formatCurrencyAmount(d.totalFeesInFiat, d.currencyStore.currentCurrency)
|
||||
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
|
||||
pending: d.isPendingTx || popup.isLoading
|
||||
visible: recipientInputLoader.ready && (amountToSendInput.inputNumberValid || d.isCollectiblesTransfer) && !d.errorMode
|
||||
visible: recipientInputLoader.ready && (amountToSend.ready || d.isCollectiblesTransfer) && !d.errorMode
|
||||
|
||||
onNextButtonClicked: popup.sendTransaction()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue