mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-16 16:47:24 +00:00
fix(BurnTokensPopup): Handle non-integer values for assets
Closes: #11864
This commit is contained in:
parent
2de2393ec1
commit
1bc7eb374b
@ -28,9 +28,7 @@
|
|||||||
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1573%3A296338"
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1573%3A296338"
|
||||||
],
|
],
|
||||||
"BurnTokensPopup": [
|
"BurnTokensPopup": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?type=design&node-id=29528%3A588403&t=GUxMZEWcfRO7pXJb-1",
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=35082-612599&mode=design&t=XTDQ4GeU1k9LPuVK-0"
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?type=design&node-id=29528%3A588563&t=GUxMZEWcfRO7pXJb-1",
|
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?type=design&node-id=29528%3A587660&t=GUxMZEWcfRO7pXJb-1"
|
|
||||||
],
|
],
|
||||||
"ChatAnchorButtonsPanel": [
|
"ChatAnchorButtonsPanel": [
|
||||||
"https://www.figma.com/file/Mr3rqxxgKJ2zMQ06UAKiWL/%F0%9F%92%AC-Chat%E2%8E%9CDesktop?node-id=14632-460085&t=SGTU2JeRA8ifbv2E-0"
|
"https://www.figma.com/file/Mr3rqxxgKJ2zMQ06UAKiWL/%F0%9F%92%AC-Chat%E2%8E%9CDesktop?node-id=14632-460085&t=SGTU2JeRA8ifbv2E-0"
|
||||||
|
@ -44,23 +44,49 @@ SplitView {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Reopen"
|
text: "Reopen"
|
||||||
|
|
||||||
onClicked: dialog.open()
|
onClicked: burnTokensPopup.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
BurnTokensPopup {
|
BurnTokensPopup {
|
||||||
id: dialog
|
id: burnTokensPopup
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
visible: true
|
||||||
|
modal: false
|
||||||
|
closePolicy: Popup.NoAutoClose
|
||||||
|
|
||||||
communityName: editorCommunity.text
|
communityName: editorCommunity.text
|
||||||
tokenName: editorToken.text
|
tokenName: editorToken.text
|
||||||
remainingTokens: editorAmount.text
|
remainingTokens: editorAmount.text
|
||||||
|
multiplierIndex: assetButton.checked ? 18 : 0
|
||||||
isAsset: assetButton.checked
|
isAsset: assetButton.checked
|
||||||
tokenSource: assetButton.checked ? ModelsData.assets.socks : ModelsData.collectibles.kitty1Big
|
tokenSource: assetButton.checked
|
||||||
|
? ModelsData.assets.socks
|
||||||
|
: ModelsData.collectibles.kitty1Big
|
||||||
accounts: accountsModel
|
accounts: accountsModel
|
||||||
chainName: "Optimism"
|
chainName: "Optimism"
|
||||||
|
|
||||||
onBurnClicked: logs.logEvent("BurnTokensPopup::onBurnClicked --> Burn amount: " + burnAmount)
|
onBurnClicked: logs.logEvent("BurnTokensPopup::onBurnClicked --> Burn amount: " + burnAmount)
|
||||||
onCancelClicked: logs.logEvent("BurnTokensPopup::onCancelClicked")
|
onCancelClicked: logs.logEvent("BurnTokensPopup::onCancelClicked")
|
||||||
|
|
||||||
|
onBurnFeesRequested: {
|
||||||
|
feeText = ""
|
||||||
|
feeErrorText = ""
|
||||||
|
isFeeLoading = true
|
||||||
|
|
||||||
|
feeCalculationTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: feeCalculationTimer
|
||||||
|
|
||||||
|
interval: 1000
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
burnTokensPopup.feeText = "0.0015 ETH ($75.43)"
|
||||||
|
burnTokensPopup.isFeeLoading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +105,7 @@ SplitView {
|
|||||||
SplitView.preferredWidth: 300
|
SplitView.preferredWidth: 300
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -87,8 +114,8 @@ SplitView {
|
|||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: editorCommunity
|
id: editorCommunity
|
||||||
background: Rectangle { border.color: 'lightgrey' }
|
|
||||||
Layout.preferredWidth: 200
|
Layout.fillWidth: true
|
||||||
text: "Community lovers"
|
text: "Community lovers"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,8 +128,8 @@ SplitView {
|
|||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: editorToken
|
id: editorToken
|
||||||
background: Rectangle { border.color: 'lightgrey' }
|
|
||||||
Layout.preferredWidth: 200
|
Layout.fillWidth: true
|
||||||
text: "Anniversary"
|
text: "Anniversary"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,8 +142,8 @@ SplitView {
|
|||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: editorAmount
|
id: editorAmount
|
||||||
background: Rectangle { border.color: 'lightgrey' }
|
|
||||||
Layout.preferredWidth: 200
|
Layout.fillWidth: true
|
||||||
text: "123"
|
text: "123"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +166,10 @@ SplitView {
|
|||||||
|
|
||||||
text: "Collectible"
|
text: "Collectible"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
import QtQml.Models 2.14
|
import QtQml.Models 2.15
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import QtQml 2.15
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Popups.Dialog 0.1
|
import StatusQ.Popups.Dialog 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||||
import StatusQ.Controls.Validators 0.1
|
|
||||||
import StatusQ.Components 0.1
|
|
||||||
|
|
||||||
import AppLayouts.Communities.panels 1.0
|
import AppLayouts.Communities.panels 1.0
|
||||||
import AppLayouts.Communities.helpers 1.0
|
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import SortFilterProxyModel 0.2
|
import shared.controls 1.0
|
||||||
|
|
||||||
|
|
||||||
StatusDialog {
|
StatusDialog {
|
||||||
id: root
|
id: root
|
||||||
@ -54,13 +51,16 @@ StatusDialog {
|
|||||||
LocaleUtils.numberToLocaleString(remainingTokensFloat)
|
LocaleUtils.numberToLocaleString(remainingTokensFloat)
|
||||||
|
|
||||||
property string accountAddress
|
property string accountAddress
|
||||||
property alias amountToBurn: amountToBurnInput.text
|
|
||||||
readonly property bool isFeeError: root.feeErrorText !== ""
|
readonly property bool isFeeError: root.feeErrorText !== ""
|
||||||
readonly property bool isFormValid: specificAmountButton.checked && amountToBurnInput.valid || allTokensButton.checked
|
|
||||||
|
readonly property bool isFormValid:
|
||||||
|
(specificAmountButton.checked && amountInput.valid && amountInput.text)
|
||||||
|
|| allTokensButton.checked
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
specificAmountButton.checked = true
|
specificAmountButton.checked = true
|
||||||
amountToBurnInput.forceActiveFocus()
|
amountInput.forceActiveFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVerticalPadding() {
|
function getVerticalPadding() {
|
||||||
@ -72,7 +72,7 @@ StatusDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitWidth: 600 // by design
|
width: 600 // by design
|
||||||
implicitHeight: content.implicitHeight + footer.height + header.height + d.getVerticalPadding()
|
implicitHeight: content.implicitHeight + footer.height + header.height + d.getVerticalPadding()
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
@ -83,22 +83,38 @@ StatusDialog {
|
|||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("How many of %1’s remaining %n %2 tokens would you like to burn?", "", d.remainingTokensFloat).arg(root.communityName).arg(root.tokenName)
|
text: {
|
||||||
|
if (Number.isInteger(d.remainingTokensFloat))
|
||||||
|
return qsTr("How many of %1’s remaining %Ln %2 token(s) would you like to burn?",
|
||||||
|
"", d.remainingTokensFloat).arg(root.communityName).arg(root.tokenName)
|
||||||
|
|
||||||
|
return qsTr("How many of %1’s remaining %2 %3 tokens would you like to burn?")
|
||||||
|
.arg(root.communityName).arg(d.remainingTokensDisplayText).arg(root.tokenName)
|
||||||
|
}
|
||||||
|
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
lineHeight: 1.2
|
lineHeight: 1.2
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
font.pixelSize: Style.current.primaryTextFontSize
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
Item {
|
||||||
Layout.bottomMargin: 12
|
Layout.bottomMargin: 12
|
||||||
Layout.leftMargin: -Style.current.halfPadding
|
Layout.leftMargin: -Style.current.halfPadding
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
spacing: 26
|
implicitHeight: childrenRect.height
|
||||||
|
|
||||||
|
readonly property int spacing: 26
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
id: specificAmountColumn
|
||||||
|
|
||||||
StatusRadioButton {
|
StatusRadioButton {
|
||||||
id: specificAmountButton
|
id: specificAmountButton
|
||||||
|
|
||||||
|
Layout.preferredWidth: amountInput.Layout.preferredWidth
|
||||||
|
+ amountInput.Layout.leftMargin
|
||||||
|
|
||||||
text: qsTr("Specific amount")
|
text: qsTr("Specific amount")
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
font.pixelSize: Style.current.primaryTextFontSize
|
||||||
ButtonGroup.group: radioGroup
|
ButtonGroup.group: radioGroup
|
||||||
@ -106,46 +122,33 @@ StatusDialog {
|
|||||||
onToggled: if(checked) amountToBurnInput.forceActiveFocus()
|
onToggled: if(checked) amountToBurnInput.forceActiveFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusInput {
|
AmountInput {
|
||||||
id: amountToBurnInput
|
id: amountInput
|
||||||
|
|
||||||
Layout.preferredWidth: 192
|
Layout.preferredWidth: 192
|
||||||
Layout.leftMargin: 30
|
Layout.leftMargin: 30
|
||||||
enabled: specificAmountButton.checked
|
customHeight: 44
|
||||||
validationMode: StatusInput.ValidationMode.OnlyWhenDirty
|
|
||||||
validators: [
|
|
||||||
StatusValidator {
|
|
||||||
validate: (value) => {
|
|
||||||
const intAmount = parseInt(value)
|
|
||||||
|
|
||||||
if (!intAmount)
|
allowDecimals: root.multiplierIndex > 0
|
||||||
return false
|
maximumAmount: root.remainingTokens
|
||||||
|
multiplierIndex: root.multiplierIndex
|
||||||
|
|
||||||
const current = SQUtils.AmountsArithmetic.fromNumber(
|
validateMaximumAmount: true
|
||||||
intAmount, root.multiplierIndex)
|
allowZero: false
|
||||||
const remaining = SQUtils.AmountsArithmetic.fromString(
|
|
||||||
root.remainingTokens)
|
|
||||||
|
|
||||||
return SQUtils.AmountsArithmetic.cmp(current, remaining) <= 0
|
placeholderText: qsTr("Enter amount")
|
||||||
}
|
labelText: ""
|
||||||
errorMessage: qsTr("Exceeds available remaining")
|
|
||||||
},
|
maximumExceededErrorText: qsTr("Exceeds available remaining")
|
||||||
StatusValidator {
|
|
||||||
validate: (value) => { return parseInt(value) !== 0 }
|
|
||||||
errorMessage: qsTr("Amount must be greater than 0")
|
|
||||||
},
|
|
||||||
StatusRegularExpressionValidator {
|
|
||||||
regularExpression: Constants.regularExpressions.numerical
|
|
||||||
errorMessage: qsTr("Invalid characters (0-9 only)")
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusRadioButton {
|
StatusRadioButton {
|
||||||
id: allTokensButton
|
id: allTokensButton
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignTop
|
anchors.left: specificAmountColumn.right
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: parent.spacing
|
||||||
|
|
||||||
text: qsTr("All available remaining (%1)").arg(d.remainingTokensDisplayText)
|
text: qsTr("All available remaining (%1)").arg(d.remainingTokensDisplayText)
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
font.pixelSize: Style.current.primaryTextFontSize
|
||||||
@ -164,13 +167,12 @@ StatusDialog {
|
|||||||
|
|
||||||
readonly property bool triggerFeeReevaluation: {
|
readonly property bool triggerFeeReevaluation: {
|
||||||
specificAmountButton.checked
|
specificAmountButton.checked
|
||||||
amountToBurnInput.text
|
amountInput.amount
|
||||||
allTokensButton.checked
|
|
||||||
feesBox.accountsSelector.currentIndex
|
feesBox.accountsSelector.currentIndex
|
||||||
|
|
||||||
if (root.opened) {
|
if (root.opened)
|
||||||
requestFeeDelayTimer.restart()
|
requestFeeDelayTimer.restart()
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +188,10 @@ StatusDialog {
|
|||||||
if (accountsSelector.currentIndex < 0)
|
if (accountsSelector.currentIndex < 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
const item = SQUtils.ModelUtils.get(accountsSelector.model, accountsSelector.currentIndex)
|
const item = SQUtils.ModelUtils.get(
|
||||||
|
accountsSelector.model,
|
||||||
|
accountsSelector.currentIndex)
|
||||||
|
|
||||||
d.accountAddress = item.address
|
d.accountAddress = item.address
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,17 +200,15 @@ StatusDialog {
|
|||||||
|
|
||||||
interval: 500
|
interval: 500
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if(specificAmountButton.checked) {
|
if (specificAmountButton.checked) {
|
||||||
if (!amountToBurnInput.text)
|
if (!amountInput.valid)
|
||||||
return
|
return
|
||||||
|
|
||||||
root.burnFeesRequested(
|
root.burnFeesRequested(amountInput.amount,
|
||||||
SQUtils.AmountsArithmetic.fromNumber(
|
|
||||||
parseInt(amountToBurnInput.text),
|
|
||||||
root.multiplierIndex),
|
|
||||||
d.accountAddress)
|
d.accountAddress)
|
||||||
} else {
|
} else {
|
||||||
root.burnFeesRequested(root.remainingTokens, d.accountAddress)
|
root.burnFeesRequested(root.remainingTokens,
|
||||||
|
d.accountAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,8 +217,8 @@ StatusDialog {
|
|||||||
id: singleFeeModel
|
id: singleFeeModel
|
||||||
|
|
||||||
readonly property string title: root.feeLabel
|
readonly property string title: root.feeLabel
|
||||||
readonly property string feeText: root.isFeeLoading ?
|
readonly property string feeText: root.isFeeLoading
|
||||||
"" : root.feeText
|
? "" : root.feeText
|
||||||
readonly property bool error: d.isFeeError
|
readonly property bool error: d.isFeeError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +226,9 @@ StatusDialog {
|
|||||||
|
|
||||||
header: StatusDialogHeader {
|
header: StatusDialogHeader {
|
||||||
headline.title: qsTr("Burn %1 tokens").arg(root.tokenName)
|
headline.title: qsTr("Burn %1 tokens").arg(root.tokenName)
|
||||||
headline.subtitle: qsTr("%n %1 remaining in smart contract", "", d.remainingTokensFloat).arg(root.tokenName)
|
headline.subtitle: qsTr("%1 %2 remaining in smart contract")
|
||||||
|
.arg(d.remainingTokensDisplayText).arg(root.tokenName)
|
||||||
|
|
||||||
leftComponent: Rectangle {
|
leftComponent: Rectangle {
|
||||||
height: 40
|
height: 40
|
||||||
width: height
|
width: height
|
||||||
@ -263,22 +268,19 @@ StatusDialog {
|
|||||||
|
|
||||||
StatusButton {
|
StatusButton {
|
||||||
enabled: d.isFormValid && !d.isFeeError && !root.isFeeLoading
|
enabled: d.isFormValid && !d.isFeeError && !root.isFeeLoading
|
||||||
|
&& root.feeText !== ""
|
||||||
text: qsTr("Burn tokens")
|
text: qsTr("Burn tokens")
|
||||||
type: StatusBaseButton.Type.Danger
|
type: StatusBaseButton.Type.Danger
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if(specificAmountButton.checked) {
|
if (specificAmountButton.checked)
|
||||||
root.burnClicked(
|
root.burnClicked(amountInput.amount, d.accountAddress)
|
||||||
SQUtils.AmountsArithmetic.fromNumber(
|
else
|
||||||
parseInt(amountToBurnInput.text),
|
|
||||||
root.multiplierIndex),
|
|
||||||
d.accountAddress)
|
|
||||||
} else {
|
|
||||||
root.burnClicked(root.remainingTokens, d.accountAddress)
|
root.burnClicked(root.remainingTokens, d.accountAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onOpened: d.initialize()
|
onOpened: d.initialize()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user