mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-19 18:18:38 +00:00
fix(wallet): Update amount to send decimal handling (#14399)
This commit is contained in:
parent
d3f037f93b
commit
7cb59576a1
66
storybook/pages/StatusAmountInputPage.qml
Normal file
66
storybook/pages/StatusAmountInputPage.qml
Normal file
@ -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
|
97
storybook/qmlTests/tests/tst_StatusAmountInput.qml
Normal file
97
storybook/qmlTests/tests/tst_StatusAmountInput.qml
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -279,7 +279,7 @@ Rectangle {
|
|||||||
color: Theme.palette.pinColor1
|
color: Theme.palette.pinColor1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatusInput {
|
StatusAmountInput {
|
||||||
id: advancedInput
|
id: advancedInput
|
||||||
Layout.preferredWidth: layout.width
|
Layout.preferredWidth: layout.width
|
||||||
maximumHeight: 32
|
maximumHeight: 32
|
||||||
@ -287,6 +287,7 @@ Rectangle {
|
|||||||
bottomPadding: 0
|
bottomPadding: 0
|
||||||
leftPadding: 8
|
leftPadding: 8
|
||||||
rightPadding: 5
|
rightPadding: 5
|
||||||
|
locale: root.locale
|
||||||
input.edit.color: { // crash workaround, https://bugreports.qt.io/browse/QTBUG-107795
|
input.edit.color: { // crash workaround, https://bugreports.qt.io/browse/QTBUG-107795
|
||||||
if (root.state === "error")
|
if (root.state === "error")
|
||||||
return Theme.palette.dangerColor1
|
return Theme.palette.dangerColor1
|
||||||
|
34
ui/StatusQ/src/StatusQ/Controls/StatusAmountInput.qml
Normal file
34
ui/StatusQ/src/StatusQ/Controls/StatusAmountInput.qml
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -273,6 +273,13 @@ Item {
|
|||||||
*/
|
*/
|
||||||
signal editingFinished()
|
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: {
|
onFocusChanged: {
|
||||||
if(focus) edit.forceActiveFocus()
|
if(focus) edit.forceActiveFocus()
|
||||||
}
|
}
|
||||||
@ -369,7 +376,7 @@ Item {
|
|||||||
focus: true
|
focus: true
|
||||||
font.pixelSize: 15
|
font.pixelSize: 15
|
||||||
font.family: Theme.palette.baseFont.name
|
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
|
wrapMode: root.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
|
||||||
|
|
||||||
Keys.onReturnPressed: {
|
Keys.onReturnPressed: {
|
||||||
|
@ -27,6 +27,7 @@ StatusLabeledSlider 0.1 StatusLabeledSlider.qml
|
|||||||
StatusSelect 0.1 StatusSelect.qml
|
StatusSelect 0.1 StatusSelect.qml
|
||||||
StatusBaseInput 0.1 StatusBaseInput.qml
|
StatusBaseInput 0.1 StatusBaseInput.qml
|
||||||
StatusInput 0.1 StatusInput.qml
|
StatusInput 0.1 StatusInput.qml
|
||||||
|
StatusAmountInput 0.1 StatusAmountInput.qml
|
||||||
StatusPickerButton 0.1 StatusPickerButton.qml
|
StatusPickerButton 0.1 StatusPickerButton.qml
|
||||||
StatusPinInput 0.1 StatusPinInput.qml
|
StatusPinInput 0.1 StatusPinInput.qml
|
||||||
StatusProgressBar 0.1 StatusProgressBar.qml
|
StatusProgressBar 0.1 StatusProgressBar.qml
|
||||||
|
@ -6,7 +6,7 @@ import Qt.labs.settings 1.0
|
|||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property var userInputLocale: Qt.locale("en_US")
|
readonly property var userInputLocale: Qt.locale()
|
||||||
|
|
||||||
function integralPartLength(num) {
|
function integralPartLength(num) {
|
||||||
num = Math.abs(num)
|
num = Math.abs(num)
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
<file>StatusQ/Controls/StatusImageCrop.qml</file>
|
<file>StatusQ/Controls/StatusImageCrop.qml</file>
|
||||||
<file>StatusQ/Controls/StatusImageSelector.qml</file>
|
<file>StatusQ/Controls/StatusImageSelector.qml</file>
|
||||||
<file>StatusQ/Controls/StatusInput.qml</file>
|
<file>StatusQ/Controls/StatusInput.qml</file>
|
||||||
|
<file>StatusQ/Controls/StatusAmountInput.qml</file>
|
||||||
<file>StatusQ/Controls/StatusItemDelegate.qml</file>
|
<file>StatusQ/Controls/StatusItemDelegate.qml</file>
|
||||||
<file>StatusQ/Controls/StatusItemPicker.qml</file>
|
<file>StatusQ/Controls/StatusItemPicker.qml</file>
|
||||||
<file>StatusQ/Controls/StatusLabeledSlider.qml</file>
|
<file>StatusQ/Controls/StatusLabeledSlider.qml</file>
|
||||||
|
@ -138,8 +138,17 @@ ColumnLayout {
|
|||||||
if(!addOrUpdateButton.enabled)
|
if(!addOrUpdateButton.enabled)
|
||||||
return
|
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()
|
addOrUpdateButton.clicked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if(visible)
|
if(visible)
|
||||||
|
@ -606,7 +606,7 @@ SettingsContentBase {
|
|||||||
text: qsTr("Choose a number between 1 and 100")
|
text: qsTr("Choose a number between 1 and 100")
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusInput {
|
StatusAmountInput {
|
||||||
id: numberInput
|
id: numberInput
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@ -616,7 +616,7 @@ SettingsContentBase {
|
|||||||
input.text: root.advancedStore.logMaxBackups
|
input.text: root.advancedStore.logMaxBackups
|
||||||
placeholderText: qsTr("Number between 1 and 100")
|
placeholderText: qsTr("Number between 1 and 100")
|
||||||
validators: [
|
validators: [
|
||||||
StatusFloatValidator {
|
StatusIntValidator {
|
||||||
bottom: 1
|
bottom: 1
|
||||||
top: 100
|
top: 100
|
||||||
errorMessage: qsTr("Number needs to be between 1 and 100")
|
errorMessage: qsTr("Number needs to be between 1 and 100")
|
||||||
|
@ -504,8 +504,7 @@ StatusDialog {
|
|||||||
totalTokenFeesInFiat = gasTimeEstimate.totalTokenFees * d.selectedHolding.marketDetails.currencyPrice.amount
|
totalTokenFeesInFiat = gasTimeEstimate.totalTokenFees * d.selectedHolding.marketDetails.currencyPrice.amount
|
||||||
d.totalFeesInFiat = d.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat
|
d.totalFeesInFiat = d.currencyStore.getFiatValue(gasTimeEstimate.totalFeesInEth, Constants.ethToken) + totalTokenFeesInFiat
|
||||||
|
|
||||||
if (!!d.selectedHolding.type && (d.selectedHolding.type === Constants.TokenType.ERC20
|
if (d.selectedHolding.type === Constants.TokenType.ERC20 || d.selectedHolding.type === Constants.TokenType.Native) {
|
||||||
|| d.selectedHolding.type === Constants.TokenType.ETH)) {
|
|
||||||
// If assets
|
// If assets
|
||||||
d.totalAmountToReceive = popup.store.getWei2Eth(txRoutes.amountToReceive, d.selectedHolding.decimals)
|
d.totalAmountToReceive = popup.store.getWei2Eth(txRoutes.amountToReceive, d.selectedHolding.decimals)
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,7 +7,7 @@ import StatusQ.Core.Theme 0.1
|
|||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
StatusInput {
|
StatusAmountInput {
|
||||||
id: cursorInput
|
id: cursorInput
|
||||||
|
|
||||||
leftPadding: 0
|
leftPadding: 0
|
||||||
@ -16,7 +16,6 @@ StatusInput {
|
|||||||
bottomPadding: 0
|
bottomPadding: 0
|
||||||
|
|
||||||
placeholderText: ""
|
placeholderText: ""
|
||||||
input.edit.objectName: "amountInput"
|
|
||||||
input.edit.cursorVisible: true
|
input.edit.cursorVisible: true
|
||||||
input.edit.font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text)
|
input.edit.font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text)
|
||||||
input.placeholderFont.pixelSize: 34
|
input.placeholderFont.pixelSize: 34
|
||||||
|
@ -131,7 +131,7 @@ ColumnLayout {
|
|||||||
id: topAmountToSendInput
|
id: topAmountToSendInput
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
Layout.maximumWidth: 250
|
Layout.maximumWidth: 250
|
||||||
Layout.preferredWidth: !!text ? input.edit.paintedWidth
|
Layout.preferredWidth: !!text ? input.edit.paintedWidth + 2
|
||||||
: textMetrics.advanceWidth
|
: textMetrics.advanceWidth
|
||||||
placeholderText: d.zeroString
|
placeholderText: d.zeroString
|
||||||
input.edit.color: input.valid ? Theme.palette.directColor1
|
input.edit.color: input.valid ? Theme.palette.directColor1
|
||||||
@ -143,7 +143,7 @@ ColumnLayout {
|
|||||||
id: floatValidator
|
id: floatValidator
|
||||||
bottom: 0
|
bottom: 0
|
||||||
errorMessage: ""
|
errorMessage: ""
|
||||||
locale: LocaleUtils.userInputLocale
|
locale: topAmountToSendInput.locale
|
||||||
},
|
},
|
||||||
StatusValidator {
|
StatusValidator {
|
||||||
errorMessage: ""
|
errorMessage: ""
|
||||||
@ -168,7 +168,7 @@ ColumnLayout {
|
|||||||
Keys.onReleased: {
|
Keys.onReleased: {
|
||||||
const amount = LocaleUtils.numberFromLocaleString(
|
const amount = LocaleUtils.numberFromLocaleString(
|
||||||
topAmountToSendInput.text,
|
topAmountToSendInput.text,
|
||||||
LocaleUtils.userInputLocale)
|
locale)
|
||||||
if (!isNaN(amount))
|
if (!isNaN(amount))
|
||||||
d.waitTimer.restart()
|
d.waitTimer.restart()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user