import QtQuick 2.15 import QtQuick.Controls 2.14 import QtQuick.Layouts 1.14 import QtQml.Models 2.14 import QtGraphicalEffects 1.0 import QtQml 2.15 import StatusQ.Core 0.1 import StatusQ.Controls 0.1 import StatusQ.Popups.Dialog 0.1 import StatusQ.Core.Theme 0.1 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.helpers 1.0 import utils 1.0 import SortFilterProxyModel 0.2 StatusDialog { id: root property string communityName property bool isAsset // If asset isAsset = true; if collectible --> isAsset = false property string tokenName property string remainingTokens property int multiplierIndex property url tokenSource property string chainName // Fees related properties: property string feeText property string feeErrorText: "" property bool isFeeLoading readonly property string feeLabel: qsTr("Burn %1 token on %2").arg(root.tokenName).arg(root.chainName) // Account expected roles: address, name, color, emoji, walletType property var accounts signal burnClicked(string burnAmount, string accountAddress) signal cancelClicked signal burnFeesRequested(string burnAmount, string accountAddress) QtObject { id: d readonly property real remainingTokensFloat: SQUtils.AmountsArithmetic.toNumber( root.remainingTokens, root.multiplierIndex) readonly property string remainingTokensDisplayText: LocaleUtils.numberToLocaleString(remainingTokensFloat) property string accountAddress property alias amountToBurn: amountToBurnInput.text readonly property bool isFeeError: root.feeErrorText !== "" readonly property bool isFormValid: specificAmountButton.checked && amountToBurnInput.valid || allTokensButton.checked function initialize() { specificAmountButton.checked = true amountToBurnInput.forceActiveFocus() } function getVerticalPadding() { return root.topPadding + root.bottomPadding } function getHorizontalPadding() { return root.leftPadding + root.rightPadding } } implicitWidth: 600 // by design implicitHeight: content.implicitHeight + footer.height + header.height + d.getVerticalPadding() contentItem: ColumnLayout { id: content spacing: Style.current.padding StatusBaseText { 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) wrapMode: Text.WordWrap lineHeight: 1.2 font.pixelSize: Style.current.primaryTextFontSize } RowLayout { Layout.bottomMargin: 12 Layout.leftMargin: -Style.current.halfPadding spacing: 26 ColumnLayout { StatusRadioButton { id: specificAmountButton text: qsTr("Specific amount") font.pixelSize: Style.current.primaryTextFontSize ButtonGroup.group: radioGroup onToggled: if(checked) amountToBurnInput.forceActiveFocus() } StatusInput { id: amountToBurnInput Layout.preferredWidth: 192 Layout.leftMargin: 30 enabled: specificAmountButton.checked validationMode: StatusInput.ValidationMode.OnlyWhenDirty validators: [ StatusValidator { validate: (value) => { const intAmount = parseInt(value) if (!intAmount) return false const current = SQUtils.AmountsArithmetic.fromNumber( intAmount, root.multiplierIndex) const remaining = SQUtils.AmountsArithmetic.fromString( root.remainingTokens) return SQUtils.AmountsArithmetic.cmp(current, remaining) <= 0 } errorMessage: 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 { id: allTokensButton Layout.alignment: Qt.AlignTop text: qsTr("All available remaining (%1)").arg(d.remainingTokensDisplayText) font.pixelSize: Style.current.primaryTextFontSize ButtonGroup.group: radioGroup } ButtonGroup { id: radioGroup } } StatusDialogDivider { Layout.fillWidth: true } FeesBox { id: feesBox readonly property bool triggerFeeReevaluation: { specificAmountButton.checked amountToBurnInput.text allTokensButton.checked feesBox.accountsSelector.currentIndex requestFeeDelayTimer.restart() return true } Layout.fillWidth: true placeholderText: qsTr("Choose number of tokens to burn to see gas fees") accountErrorText: root.feeErrorText implicitWidth: 0 model: d.isFormValid ? singleFeeModel : undefined accountsSelector.model: root.accounts accountsSelector.onCurrentIndexChanged: { if (accountsSelector.currentIndex < 0) return const item = SQUtils.ModelUtils.get(accountsSelector.model, accountsSelector.currentIndex) d.accountAddress = item.address } Timer { id: requestFeeDelayTimer interval: 500 onTriggered: { if(specificAmountButton.checked) { if (!amountToBurnInput.text) return root.burnFeesRequested( SQUtils.AmountsArithmetic.fromNumber( parseInt(amountToBurnInput.text), root.multiplierIndex), d.accountAddress) } else { root.burnFeesRequested(root.remainingTokens, d.accountAddress) } } } QtObject { id: singleFeeModel readonly property string title: root.feeLabel readonly property string feeText: root.isFeeLoading ? "" : root.feeText readonly property bool error: d.isFeeError } } } header: StatusDialogHeader { headline.title: qsTr("Burn %1 tokens").arg(root.tokenName) headline.subtitle: qsTr("%n %1 remaining in smart contract", "", d.remainingTokensFloat).arg(root.tokenName) leftComponent: Rectangle { height: 40 width: height radius: root.isAsset ? height/2 : 8 color:Theme.palette.baseColor2 Image { id: image source: root.tokenSource anchors.fill: parent fillMode: Image.PreserveAspectFit visible: false } OpacityMask { anchors.fill: image source: image maskSource: parent } } actions.closeButton.onClicked: root.close() } footer: StatusDialogFooter { spacing: Style.current.padding rightButtons: ObjectModel { StatusButton { text: qsTr("Cancel") normalColor: "transparent" onClicked: { root.cancelClicked() close() } } StatusButton { enabled: d.isFormValid && !d.isFeeError && !root.isFeeLoading text: qsTr("Burn tokens") type: StatusBaseButton.Type.Danger onClicked: { if(specificAmountButton.checked) { root.burnClicked( SQUtils.AmountsArithmetic.fromNumber( parseInt(amountToBurnInput.text), root.multiplierIndex), d.accountAddress) } else { root.burnClicked(root.remainingTokens, d.accountAddress) } } } } } onOpened: d.initialize() }