diff --git a/storybook/pages/AirdropsSettingsPanelPage.qml b/storybook/pages/AirdropsSettingsPanelPage.qml index b48a31e67..d53547957 100644 --- a/storybook/pages/AirdropsSettingsPanelPage.qml +++ b/storybook/pages/AirdropsSettingsPanelPage.qml @@ -177,6 +177,10 @@ SplitView { name: "chainName" expression: model.index ? "Ethereum Mainnet" : "Goerli" }, + ExpressionRole { + name: "decimals" + expression: decimalsText.text + }, ExpressionRole { readonly property string icon1: "network/Network=Ethereum" @@ -192,7 +196,6 @@ SplitView { value: TokenCategories.Category.Community } - Component.onCompleted: { Qt.callLater(() => airdropsSettingsPanel.assetsModel = this) } @@ -250,6 +253,19 @@ SplitView { text: "Owner and TMaster tokens deployed" } + + Row { + Label { + anchors.verticalCenter: parent.verticalCenter + text: "Assets Decimals" + } + + TextField { + id: decimalsText + text: "2" + width: 50 + } + } } } } diff --git a/storybook/pages/HoldingsDropdownPage.qml b/storybook/pages/HoldingsDropdownPage.qml index 6e064b2e8..057fcd58a 100644 --- a/storybook/pages/HoldingsDropdownPage.qml +++ b/storybook/pages/HoldingsDropdownPage.qml @@ -119,7 +119,10 @@ SplitView { expression: model.index ? "Ethereum Mainnet" : "Goerli" }, ExpressionRole { - + name: "decimals" + expression: decimalsText.text + }, + ExpressionRole { readonly property string icon1: "network/Network=Ethereum" readonly property string icon2: "network/Network=Testnet" @@ -169,6 +172,16 @@ SplitView { id: ctrlAllTokensMode text: "All tokens mode" } + + Label { + text: "Assets Decimals" + } + + TextField { + id: decimalsText + Layout.preferredWidth: 50 + text: "2" + } } } } diff --git a/storybook/pages/TokenPanelPage.qml b/storybook/pages/TokenPanelPage.qml index 78ca30cfa..8106173e4 100644 --- a/storybook/pages/TokenPanelPage.qml +++ b/storybook/pages/TokenPanelPage.qml @@ -24,28 +24,32 @@ SplitView { icon: Style.svg(ModelsData.networks.optimism), amount: "300", multiplierIndex: 0, - infiniteAmount: false + infiniteAmount: false, + decimals: 6 }, { name: "Arbitrum", icon: Style.svg(ModelsData.networks.arbitrum), amount: "400000", multiplierIndex: 3, - infiniteAmount: false + infiniteAmount: false, + decimals: 9 }, { name: "Hermez", icon: Style.svg(ModelsData.networks.hermez), amount: "0", multiplierIndex: 0, - infiniteAmount: true + infiniteAmount: true, + decimals: 0 }, { name: "Ethereum", icon: Style.svg(ModelsData.networks.ethereum), amount: "12" + "0".repeat(18), multiplierIndex: 18, - infiniteAmount: false + infiniteAmount: false, + decimals: 9 } ] @@ -130,10 +134,24 @@ SplitView { text: "∞" } + + Label { + text: "Decimals:" + } + TextField { + id: decimalsTextField + + text: "0" + } } - Label { - text: "amount: " + tokenPanel.amount + RowLayout { + Label { + text: "amount: " + tokenPanel.amount + } + Label { + text: "decimals: " + tokenPanel.decimals + } } } } diff --git a/ui/app/AppLayouts/Communities/controls/InlineNetworksComboBox.qml b/ui/app/AppLayouts/Communities/controls/InlineNetworksComboBox.qml index a511ce065..0196d6c2f 100644 --- a/ui/app/AppLayouts/Communities/controls/InlineNetworksComboBox.qml +++ b/ui/app/AppLayouts/Communities/controls/InlineNetworksComboBox.qml @@ -15,6 +15,7 @@ StatusComboBox { readonly property string currentName: control.currentText readonly property alias currentAmount: instantiator.amount + readonly property alias decimals: instantiator.decimals readonly property alias currentMultiplierIndex: instantiator.multiplierIndex readonly property alias currentInfiniteAmount: instantiator.infiniteAmount readonly property alias currentIcon: instantiator.icon @@ -100,6 +101,7 @@ StatusComboBox { property string amount property int multiplierIndex property bool infiniteAmount + property int decimals model: SortFilterProxyModel { sourceModel: root.model @@ -113,6 +115,7 @@ StatusComboBox { readonly property list bindings: [ Bind { property: "icon"; value: model.icon }, Bind { property: "amount"; value: model.amount }, + Bind { property: "decimals"; value: model.decimals }, Bind { property: "multiplierIndex"; value: model.multiplierIndex }, Bind { property: "infiniteAmount"; value: model.infiniteAmount } ] diff --git a/ui/app/AppLayouts/Communities/controls/TokenPanel.qml b/ui/app/AppLayouts/Communities/controls/TokenPanel.qml index e1fd77f57..f24675c5a 100644 --- a/ui/app/AppLayouts/Communities/controls/TokenPanel.qml +++ b/ui/app/AppLayouts/Communities/controls/TokenPanel.qml @@ -21,6 +21,7 @@ ColumnLayout { property alias tokenImage: item.iconSource property alias amountText: amountInput.text property alias amount: amountInput.amount + property alias decimals: amountInput.tokenDecimals property alias multiplierIndex: amountInput.multiplierIndex property alias tokenCategoryText: tokenLabel.text property alias networkLabelText: d.networkLabelText @@ -88,6 +89,7 @@ ColumnLayout { spacing: 10 property alias currentAmount: inlineNetworksComboBox.currentAmount + property alias decimals: inlineNetworksComboBox.decimals property alias currentMultiplierIndex: inlineNetworksComboBox.currentMultiplierIndex property alias currentInfiniteAmount: @@ -128,7 +130,8 @@ ColumnLayout { maximumAmount: !!networksComboBoxLoader.item ? networksComboBoxLoader.item.currentAmount : "0" - + tokenDecimals: !!networksComboBoxLoader.item + ? networksComboBoxLoader.item.decimals : 0 multiplierIndex: !!networksComboBoxLoader.item ? networksComboBoxLoader.item.currentMultiplierIndex : 0 diff --git a/ui/app/AppLayouts/Communities/popups/HoldingsDropdown.qml b/ui/app/AppLayouts/Communities/popups/HoldingsDropdown.qml index a8d4e916e..04f928fb2 100644 --- a/ui/app/AppLayouts/Communities/popups/HoldingsDropdown.qml +++ b/ui/app/AppLayouts/Communities/popups/HoldingsDropdown.qml @@ -425,6 +425,7 @@ StatusDropdown { name: chainName, icon: chainIcon, amount: asset.remainingSupply, + decimals: asset.decimals, multiplierIndex: asset.multiplierIndex, infiniteAmount: asset.infiniteSupply }) diff --git a/ui/imports/shared/controls/AmountInput.qml b/ui/imports/shared/controls/AmountInput.qml index 2779fb5a5..d2ec401d7 100644 --- a/ui/imports/shared/controls/AmountInput.qml +++ b/ui/imports/shared/controls/AmountInput.qml @@ -10,7 +10,6 @@ import utils 1.0 Input { id: root - property int maximumLength: 10 property var locale: LocaleUtils.userInputLocale readonly property alias amount: d.amount @@ -18,6 +17,7 @@ Input { readonly property bool valid: validationError.length === 0 property bool allowDecimals: true + property int tokenDecimals: 0 property bool validateMaximumAmount: false property string maximumAmount: "0" @@ -66,17 +66,12 @@ Input { if (!root.allowDecimals) root.text = root.text.replace(root.locale.decimalPoint, "") - if(root.text.length === 0) { + if (root.text.length === 0) { d.amount = "0" root.validationError = "" return } - if (d.getEffectiveDigitsCount(text) > root.maximumLength) { - root.validationError = qsTr("The maximum number of characters is %1").arg(root.maximumLength) - return - } - const amountNumber = LocaleUtils.numberFromLocaleString(root.text, root.locale) if (isNaN(amountNumber)) { d.amount = "0" @@ -84,23 +79,26 @@ Input { return } + const fractionalPartLength = LocaleUtils.fractionalPartLength(amountNumber) + if (fractionalPartLength > root.tokenDecimals) { + d.amount = "0" + root.validationError = qsTr("Max %n decimal place(s) for this asset", "", root.tokenDecimals) + return + } + if (!root.allowZero && amountNumber === 0) { d.amount = "0" root.validationError = qsTr("Amount must be greater than 0") return } - const amount = SQUtils.AmountsArithmetic.fromNumber( - amountNumber, d.multiplierIndex) + const amount = SQUtils.AmountsArithmetic.fromNumber(amountNumber, d.multiplierIndex) - if (root.validateMaximumAmount) { - const maximumAmount = SQUtils.AmountsArithmetic.fromString( - root.maximumAmount) + if (root.validateMaximumAmount && root.maximumAmount && root.maximumAmount.length > 0) { + const maximumAmount = SQUtils.AmountsArithmetic.fromString(root.maximumAmount) + const maxExceeded = SQUtils.AmountsArithmetic.cmp(amount, maximumAmount) === 1 - const maxExceeded = SQUtils.AmountsArithmetic.cmp( - amount, maximumAmount) === 1 - - if (SQUtils.AmountsArithmetic.cmp(amount, maximumAmount) === 1) { + if (maxExceeded) { root.validationError = root.maximumExceededErrorText return } @@ -110,7 +108,7 @@ Input { // As a target amount should be always integer number if (!Number.isInteger(amountNumber) && d.multiplierIndex === 0) { d.amount = amount.toString() - } else { + } else { d.amount = amount.toFixed(0) } diff --git a/ui/imports/shared/controls/Input.qml b/ui/imports/shared/controls/Input.qml index 4fa37b493..190045e3b 100644 --- a/ui/imports/shared/controls/Input.qml +++ b/ui/imports/shared/controls/Input.qml @@ -177,9 +177,10 @@ Item { id: validationErrorText visible: !!validationError text: validationError + anchors.left: inputField.left + anchors.leftMargin: 2 anchors.top: inputField.bottom anchors.topMargin: validationErrorTopMargin - width: parent.width horizontalAlignment: Text.AlignRight font.pixelSize: 12 height: 16