feat(HoldingsDropdown): maximum amount validation

This commit is contained in:
Michał Cieślak 2023-04-27 23:38:09 +02:00 committed by Michał
parent 27aac8d83a
commit 45aaa5a3de
6 changed files with 107 additions and 48 deletions

View File

@ -63,7 +63,7 @@ SplitView {
proxyRoles: [
ExpressionRole {
name: "supply"
expression: ((model.index + 1) * 115).toString()
expression: (model.index + 1) * 115
},
ExpressionRole {
name: "infiniteSupply"
@ -75,8 +75,8 @@ SplitView {
},
ExpressionRole {
readonly property string icon1: Style.svg("network/Network=Optimism")
readonly property string icon2: Style.svg("network/Network=Arbitrum")
readonly property string icon1: "network/Network=Optimism"
readonly property string icon2: "network/Network=Arbitrum"
name: "chainIcon"
expression: model.index ? icon1 : icon2

View File

@ -1,5 +1,6 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Models 1.0
import utils 1.0
@ -12,17 +13,20 @@ Item {
{
name: "Optimism",
icon: Style.svg(ModelsData.networks.optimism),
amount: "300"
amount: 300,
infiniteAmount: false
},
{
name: "Arbitrum",
icon: Style.svg(ModelsData.networks.arbitrum),
amount: "400"
amount: 400,
infiniteAmount: false
},
{
name: "Hermez",
icon: Style.svg(ModelsData.networks.hermez),
amount: "500"
amount: 0,
infiniteAmount: true
}
]
@ -48,19 +52,36 @@ Item {
model: singleItemRadioButton.checked ? singleItemModel
: multipleItemsModel
}
Row {
Pane {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: implicitHeight / 2
RadioButton {
id: singleItemRadioButton
text: "single item model"
}
RadioButton {
text: "multiple items model"
checked: true
ColumnLayout {
Row {
Layout.alignment: Qt.AlignHCenter
RadioButton {
id: singleItemRadioButton
text: "single item model"
}
RadioButton {
text: "multiple items model"
checked: true
}
}
Label {
Layout.alignment: Qt.AlignHCenter
text: `current name: ${comboBox.control.displayText}`
}
Label {
Layout.alignment: Qt.AlignHCenter
text: `current amount: ${comboBox.currentAmount}`
}
Label {
Layout.alignment: Qt.AlignHCenter
text: `current amount infinite: ${comboBox.currentInfiniteAmount}`
}
}
}
}

View File

@ -429,7 +429,9 @@ StatusDropdown {
append({
name:chainName,
icon: chainIcon
icon: chainIcon,
amount: collectible.supply,
infiniteAmount: collectible.infiniteSupply
})
collectiblePanel.networksModel = this

View File

@ -11,6 +11,11 @@ import SortFilterProxyModel 0.2
StatusComboBox {
id: root
readonly property string currentName: control.currentText
readonly property alias currentAmount: instantiator.amount
readonly property alias currentInfiniteAmount: instantiator.infiniteAmount
readonly property alias currentIcon: instantiator.icon
type: StatusComboBox.Type.Secondary
size: StatusComboBox.Size.Small
@ -42,6 +47,8 @@ StatusComboBox {
readonly property int radius: 8
readonly property int fontSize: 13
readonly property int iconSize: 32
readonly property string infinitySymbol: "∞"
}
component CustomText: StatusBaseText {
@ -87,7 +94,8 @@ StatusComboBox {
id: instantiator
property string icon
property string amount
property int amount
property bool infiniteAmount
model: SortFilterProxyModel {
sourceModel: root.model
@ -100,7 +108,8 @@ StatusComboBox {
component Bind: Binding { target: instantiator }
readonly property list<Binding> bindings: [
Bind { property: "icon"; value: model.icon },
Bind { property: "amount"; value: model.amount }
Bind { property: "amount"; value: model.amount },
Bind { property: "infiniteAmount"; value: model.infiniteAmount }
]
}
}
@ -109,7 +118,10 @@ StatusComboBox {
title: root.control.displayText
iconSource: instantiator.icon
amount: !d.oneItem ? instantiator.amount : ""
amount: !d.oneItem
? (instantiator.infiniteAmount ? d.infinitySymbol
: instantiator.amount)
: ""
cursorShape: d.oneItem ? Qt.ArrowCursor : Qt.PointingHandCursor
onClicked: {
@ -123,7 +135,7 @@ StatusComboBox {
delegate: DelegateItem {
title: model.name
iconSource: model.icon
amount: model.amount
amount: model.infiniteAmount ? d.infinitySymbol : model.amount
width: root.width
height: root.height

View File

@ -73,6 +73,8 @@ ColumnLayout {
}
Loader {
id: networksComboBoxLoader
active: !!root.networksModel
visible: active
@ -81,7 +83,10 @@ ColumnLayout {
Layout.bottomMargin: d.defaultSpacing
sourceComponent: ColumnLayout {
spacing: 10
spacing: 10
property alias currentAmount: inlineNetworksComboBox.currentAmount
property alias currentInfiniteAmount: inlineNetworksComboBox.currentInfiniteAmount
CustomText {
id: networkLabel
@ -94,6 +99,8 @@ ColumnLayout {
}
InlineNetworksComboBox {
id: inlineNetworksComboBox
Layout.fillWidth: true
model: root.networksModel
@ -107,10 +114,18 @@ ColumnLayout {
locale: LocaleUtils.userInputLocale
Layout.fillWidth: true
Layout.bottomMargin: (validationError !== "") ? root.spacing : 0
Layout.bottomMargin: (validationError !== "") ? root.spacing * 2 : 0
customHeight: d.defaultHeight
allowDecimals: true
keepHeight: true
validateMaximumAmount:
!!networksComboBoxLoader.item &&
!networksComboBoxLoader.item.currentInfiniteAmount
maximumAmount: !!networksComboBoxLoader.item
? networksComboBoxLoader.item.currentAmount : 0
onKeyPressed: {
if(!addOrUpdateButton.enabled) return

View File

@ -16,6 +16,9 @@ Input {
readonly property bool valid: validationError.length === 0
property bool allowDecimals: true
property bool validateMaximumAmount: false
property real maximumAmount: 0
validationErrorTopMargin: 8
fontPixelSize: 13
customHeight: 36
@ -28,6 +31,10 @@ Input {
root.text = LocaleUtils.numberToLocaleString(amount, -1, root.locale)
}
onTextChanged: d.validate()
onValidateMaximumAmountChanged: d.validate()
onMaximumAmountChanged: d.validate()
QtObject {
id: d
@ -37,6 +44,33 @@ Input {
const digits = LocaleUtils.getLocalizedDigitsCount(text, root.locale)
return str.startsWith(locale.decimalPoint) ? digits + 1 : digits
}
function validate() {
if (!root.allowDecimals)
root.text = root.text.replace(root.locale.decimalPoint, "")
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 amount = LocaleUtils.numberFromLocaleString(root.text, root.locale)
if (isNaN(amount)) {
d.amount = 0
root.validationError = qsTr("Invalid amount format")
} else if (root.validateMaximumAmount && amount > root.maximumAmount) {
root.validationError = qsTr("Amount exceeds balance")
} else {
d.amount = amount
root.validationError = ""
}
}
}
validator: DoubleValidator {
@ -48,31 +82,6 @@ Input {
locale: root.locale.name
}
onTextChanged: {
if (!allowDecimals)
text = text.replace(root.locale.decimalPoint, "")
if(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
}
let amount = LocaleUtils.numberFromLocaleString(text, root.locale)
if (isNaN(amount)) {
d.amount = 0
root.validationError = qsTr("Invalid amount format")
} else {
d.amount = amount
root.validationError = ""
}
}
StatusBaseText {
id: labelText