diff --git a/storybook/pages/StatusAmountInputPage.qml b/storybook/pages/StatusAmountInputPage.qml
new file mode 100644
index 0000000000..bd9fa6df50
--- /dev/null
+++ b/storybook/pages/StatusAmountInputPage.qml
@@ -0,0 +1,66 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+
+import StatusQ.Controls 0.1
+import Storybook 1.0
+import utils 1.0
+
+import shared.controls 1.0
+
+SplitView {
+ id: root
+
+ orientation: Qt.Horizontal
+
+ Item {
+ SplitView.fillWidth: true
+ SplitView.fillHeight: true
+
+ StatusAmountInput {
+ id: input
+ anchors.centerIn: parent
+ }
+ }
+
+ LogsAndControlsPanel {
+ SplitView.minimumWidth: 300
+ SplitView.preferredWidth: 400
+
+ SplitView.fillHeight: true
+
+ ColumnLayout {
+ Layout.fillWidth: true
+ RowLayout {
+ Layout.fillWidth: true
+ Label {
+ text: "Valid:"
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignRight
+ horizontalAlignment: Text.AlignRight
+ font.bold: true
+ text: input.valid ? "true" : "false"
+ }
+ }
+ RowLayout {
+ Layout.fillWidth: true
+ Label {
+ text: "Locale:"
+ }
+ Label {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignRight
+ horizontalAlignment: Text.AlignRight
+ font.bold: true
+ text: input.locale.name
+ }
+ }
+ }
+ }
+}
+
+// category: Controls
+
+// https://www.figma.com/file/eM26pyHZUeAwMLviaS1KJn/%E2%9A%99%EF%B8%8F-Wallet-Settings%3A-Manage-Tokens?type=design&node-id=305-139866&mode=design&t=g49O9LFh8PkuPxZB-0
diff --git a/storybook/qmlTests/tests/tst_StatusAmountInput.qml b/storybook/qmlTests/tests/tst_StatusAmountInput.qml
new file mode 100644
index 0000000000..6e823cef17
--- /dev/null
+++ b/storybook/qmlTests/tests/tst_StatusAmountInput.qml
@@ -0,0 +1,97 @@
+import QtQuick 2.15
+import QtTest 1.15
+
+import StatusQ.Controls 0.1
+
+import Storybook 1.0
+import shared.controls 1.0
+
+Item {
+ id: root
+ width: 600
+ height: 400
+
+ Component {
+ id: componentUnderTest
+ StatusAmountInput {
+ id: input
+ anchors.centerIn: parent
+ locale: Qt.locale("en_US") // US uses period as decimal point
+ }
+ }
+
+ TestCase {
+ name: "StatusAmountInput"
+ when: windowShown
+
+ property StatusAmountInput controlUnderTest: null
+
+ function init() {
+ controlUnderTest = createTemporaryObject(componentUnderTest, root)
+ controlUnderTest.forceActiveFocus()
+ }
+
+ function test_decimalPoint() {
+ verify(!!controlUnderTest)
+
+ keyClick(Qt.Key_1)
+ keyClick(Qt.Key_2)
+ keyClick(Qt.Key_Comma)
+ keyClick(Qt.Key_2)
+
+ compare(controlUnderTest.text, "12.2")
+
+ keyClick(Qt.Key_Period)
+ compare(controlUnderTest.text, "12.2", "There can be only single decimal point")
+
+ controlUnderTest.text = ""
+ compare(controlUnderTest.text.length, 0)
+
+ keyClick(Qt.Key_5)
+ keyClick(Qt.Key_3)
+ keyClick(Qt.Key_Period)
+ keyClick(Qt.Key_3)
+
+ compare(controlUnderTest.text, "53.3")
+ keyClick(Qt.Key_Comma)
+ compare(controlUnderTest.text, "53.3", "There can be only single decimal point")
+
+ controlUnderTest.text = ""
+ compare(controlUnderTest.text.length, 0)
+
+ controlUnderTest.locale = Qt.locale("pl_PL") // PL uses comma as decimal point
+
+ keyClick(Qt.Key_6)
+ keyClick(Qt.Key_2)
+ keyClick(Qt.Key_Period)
+ keyClick(Qt.Key_1)
+
+ compare(controlUnderTest.text, "62,1")
+ }
+
+ function test_unallowedKeys() {
+ verify(!!controlUnderTest)
+
+ keyClick(Qt.Key_1)
+ for (let i = Qt.Key_A ; i <= Qt.Key_BracketRight ; i++) {
+ keyClick(i)
+ }
+ keyClick(Qt.Key_Space)
+ keyClick(Qt.Key_3)
+
+ compare(controlUnderTest.text, "13")
+ }
+
+ function test_defaultValidation() {
+ verify(!!controlUnderTest)
+
+ verify(!controlUnderTest.valid)
+
+ keyClick(Qt.Key_4)
+ verify(controlUnderTest.valid)
+
+ controlUnderTest.text = "-12"
+ verify(!controlUnderTest.valid, "Amount below zero is not allowed")
+ }
+ }
+}
diff --git a/ui/StatusQ/src/StatusQ/Components/StatusCard.qml b/ui/StatusQ/src/StatusQ/Components/StatusCard.qml
index 1b7ebcfb98..7c2c89e51b 100644
--- a/ui/StatusQ/src/StatusQ/Components/StatusCard.qml
+++ b/ui/StatusQ/src/StatusQ/Components/StatusCard.qml
@@ -279,7 +279,7 @@ Rectangle {
color: Theme.palette.pinColor1
}
}
- StatusInput {
+ StatusAmountInput {
id: advancedInput
Layout.preferredWidth: layout.width
maximumHeight: 32
@@ -287,6 +287,7 @@ Rectangle {
bottomPadding: 0
leftPadding: 8
rightPadding: 5
+ locale: root.locale
input.edit.color: { // crash workaround, https://bugreports.qt.io/browse/QTBUG-107795
if (root.state === "error")
return Theme.palette.dangerColor1
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusAmountInput.qml b/ui/StatusQ/src/StatusQ/Controls/StatusAmountInput.qml
new file mode 100644
index 0000000000..e94f856367
--- /dev/null
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusAmountInput.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+
+import StatusQ.Core 0.1
+import StatusQ.Controls.Validators 0.1
+
+// StatusInput variation that allows only one decimal point and only numbers
+StatusInput {
+ id: root
+
+ property var locale: LocaleUtils.userInputLocale
+
+ input.edit.objectName: "amountInput"
+
+ validators: [
+ StatusFloatValidator {
+ bottom: 0
+ errorMessage: ""
+ locale: LocaleUtils.userInputLocale
+ }
+ ]
+
+ onKeyPressed: (event) => {
+ // additionally accept dot (.) and convert it to the correct decimal point char
+ if (event.key === Qt.Key_Period || event.key === Qt.Key_Comma) {
+ // Only one decimal point is allowed
+ if(root.text.indexOf(root.locale.decimalPoint) === -1)
+ root.input.insert(root.input.cursorPosition, root.locale.decimalPoint)
+ event.accepted = true
+ } else if ((event.key > Qt.Key_9 && event.key <= Qt.Key_BraceRight) || event.key === Qt.Key_Space) {
+ event.accepted = true
+ }
+ }
+}
diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusBaseInput.qml b/ui/StatusQ/src/StatusQ/Controls/StatusBaseInput.qml
index 00f913b826..e40e892f9e 100644
--- a/ui/StatusQ/src/StatusQ/Controls/StatusBaseInput.qml
+++ b/ui/StatusQ/src/StatusQ/Controls/StatusBaseInput.qml
@@ -273,6 +273,13 @@ Item {
*/
signal editingFinished()
+ function insert(position, text) {
+ let pos = edit.cursorVisible ? edit.cursorPosition : -1
+ edit.insert(position, text)
+ if (pos >= 0)
+ edit.cursorPosition = position <= pos ? pos + 1 : pos
+ }
+
onFocusChanged: {
if(focus) edit.forceActiveFocus()
}
@@ -369,7 +376,7 @@ Item {
focus: true
font.pixelSize: 15
font.family: Theme.palette.baseFont.name
- color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
+ color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
wrapMode: root.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
Keys.onReturnPressed: {
diff --git a/ui/StatusQ/src/StatusQ/Controls/qmldir b/ui/StatusQ/src/StatusQ/Controls/qmldir
index f7dcd81834..4b6fba584a 100644
--- a/ui/StatusQ/src/StatusQ/Controls/qmldir
+++ b/ui/StatusQ/src/StatusQ/Controls/qmldir
@@ -27,6 +27,7 @@ StatusLabeledSlider 0.1 StatusLabeledSlider.qml
StatusSelect 0.1 StatusSelect.qml
StatusBaseInput 0.1 StatusBaseInput.qml
StatusInput 0.1 StatusInput.qml
+StatusAmountInput 0.1 StatusAmountInput.qml
StatusPickerButton 0.1 StatusPickerButton.qml
StatusPinInput 0.1 StatusPinInput.qml
StatusProgressBar 0.1 StatusProgressBar.qml
diff --git a/ui/StatusQ/src/StatusQ/Core/LocaleUtils.qml b/ui/StatusQ/src/StatusQ/Core/LocaleUtils.qml
index c19ec2b1f5..770d3af238 100644
--- a/ui/StatusQ/src/StatusQ/Core/LocaleUtils.qml
+++ b/ui/StatusQ/src/StatusQ/Core/LocaleUtils.qml
@@ -6,7 +6,7 @@ import Qt.labs.settings 1.0
QtObject {
id: root
- readonly property var userInputLocale: Qt.locale("en_US")
+ readonly property var userInputLocale: Qt.locale()
function integralPartLength(num) {
num = Math.abs(num)
diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc
index 18680190dd..4c00daee5a 100644
--- a/ui/StatusQ/src/statusq.qrc
+++ b/ui/StatusQ/src/statusq.qrc
@@ -109,6 +109,7 @@
StatusQ/Controls/StatusImageCrop.qml
StatusQ/Controls/StatusImageSelector.qml
StatusQ/Controls/StatusInput.qml
+ StatusQ/Controls/StatusAmountInput.qml
StatusQ/Controls/StatusItemDelegate.qml
StatusQ/Controls/StatusItemPicker.qml
StatusQ/Controls/StatusLabeledSlider.qml
diff --git a/ui/app/AppLayouts/Communities/controls/TokenPanel.qml b/ui/app/AppLayouts/Communities/controls/TokenPanel.qml
index b39e31efc7..406a237a6b 100644
--- a/ui/app/AppLayouts/Communities/controls/TokenPanel.qml
+++ b/ui/app/AppLayouts/Communities/controls/TokenPanel.qml
@@ -138,8 +138,17 @@ ColumnLayout {
if(!addOrUpdateButton.enabled)
return
- if(event.key === Qt.Key_Enter || event.key === Qt.Key_Return)
+ // additionally accept dot (.) and convert it to the correct decimal point char
+ if (event.key === Qt.Key_Period || event.key === Qt.Key_Comma) {
+ // Only one decimal point is allowed
+ if(amountInput.text.indexOf(amountInput.locale.decimalPoint) === -1)
+ amountInput.textField.insert(amountInput.textField.cursorPosition, amountInput.locale.decimalPoint)
+ event.accepted = true
+ } else if ((event.key > Qt.Key_9 && event.key <= Qt.Key_BraceRight) || event.key === Qt.Key_Space) {
+ event.accepted = true
+ } else if(event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
addOrUpdateButton.clicked()
+ }
}
onVisibleChanged: {
if(visible)
diff --git a/ui/app/AppLayouts/Profile/views/AdvancedView.qml b/ui/app/AppLayouts/Profile/views/AdvancedView.qml
index c719add9f4..5c01e3dfa3 100644
--- a/ui/app/AppLayouts/Profile/views/AdvancedView.qml
+++ b/ui/app/AppLayouts/Profile/views/AdvancedView.qml
@@ -606,7 +606,7 @@ SettingsContentBase {
text: qsTr("Choose a number between 1 and 100")
}
- StatusInput {
+ StatusAmountInput {
id: numberInput
anchors.left: parent.left
anchors.right: parent.right
@@ -616,7 +616,7 @@ SettingsContentBase {
input.text: root.advancedStore.logMaxBackups
placeholderText: qsTr("Number between 1 and 100")
validators: [
- StatusFloatValidator {
+ StatusIntValidator {
bottom: 1
top: 100
errorMessage: qsTr("Number needs to be between 1 and 100")
diff --git a/ui/imports/shared/popups/send/controls/AmountInputWithCursor.qml b/ui/imports/shared/popups/send/controls/AmountInputWithCursor.qml
index f319e52d01..74b4521b04 100644
--- a/ui/imports/shared/popups/send/controls/AmountInputWithCursor.qml
+++ b/ui/imports/shared/popups/send/controls/AmountInputWithCursor.qml
@@ -7,7 +7,7 @@ import StatusQ.Core.Theme 0.1
import utils 1.0
-StatusInput {
+StatusAmountInput {
id: cursorInput
leftPadding: 0
@@ -16,7 +16,6 @@ StatusInput {
bottomPadding: 0
placeholderText: ""
- input.edit.objectName: "amountInput"
input.edit.cursorVisible: true
input.edit.font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text)
input.placeholderFont.pixelSize: 34
diff --git a/ui/imports/shared/popups/send/views/AmountToSend.qml b/ui/imports/shared/popups/send/views/AmountToSend.qml
index df836bf54c..606458f888 100644
--- a/ui/imports/shared/popups/send/views/AmountToSend.qml
+++ b/ui/imports/shared/popups/send/views/AmountToSend.qml
@@ -131,7 +131,7 @@ ColumnLayout {
id: topAmountToSendInput
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.maximumWidth: 250
- Layout.preferredWidth: !!text ? input.edit.paintedWidth
+ Layout.preferredWidth: !!text ? input.edit.paintedWidth + 2
: textMetrics.advanceWidth
placeholderText: d.zeroString
input.edit.color: input.valid ? Theme.palette.directColor1
@@ -143,7 +143,7 @@ ColumnLayout {
id: floatValidator
bottom: 0
errorMessage: ""
- locale: LocaleUtils.userInputLocale
+ locale: topAmountToSendInput.locale
},
StatusValidator {
errorMessage: ""
@@ -168,7 +168,7 @@ ColumnLayout {
Keys.onReleased: {
const amount = LocaleUtils.numberFromLocaleString(
topAmountToSendInput.text,
- LocaleUtils.userInputLocale)
+ locale)
if (!isNaN(amount))
d.waitTimer.restart()
}