diff --git a/ui/imports/Utils.qml b/ui/imports/Utils.qml index a476b69eeb..b79a0073ae 100644 --- a/ui/imports/Utils.qml +++ b/ui/imports/Utils.qml @@ -5,7 +5,7 @@ import "../shared/xss.js" as XSS QtObject { function isHex(value) { - return /^(-0x|0x)?[0-9a-f]*$/i.test(value) + return /^(-0x|0x)?[0-9a-fA-F]*$/i.test(value) } function startsWith0x(value) { @@ -65,4 +65,8 @@ QtObject { function removeStatusEns(userName){ return userName.endsWith(".stateofus.eth") ? userName.substr(0, userName.length - 14) : userName } + + function isValidAddress(inputValue) { + return /0x[a-fA-F0-9]{40}/.test(inputValue) + } } diff --git a/ui/shared/AddressInput.qml b/ui/shared/AddressInput.qml index e04ec4e603..3211268a65 100644 --- a/ui/shared/AddressInput.qml +++ b/ui/shared/AddressInput.qml @@ -12,9 +12,6 @@ Item { height: inpAddress.height - function isValidAddress(inputValue) { - return /0x[a-fA-F0-9]{40}/.test(inputValue) - } function isValidEns(inputValue) { // TODO: Check if the entered value resolves to an address. Long operation. // Issue tracked: https://github.com/status-im/nim-status-client/issues/718 @@ -26,7 +23,7 @@ Item { function validate(inputValue) { if (!inputValue) inputValue = selectedAddress let isValid = - (inputValue && inputValue.startsWith("0x") && isValidAddress(inputValue)) || + (inputValue && inputValue.startsWith("0x") && Utils.isValidAddress(inputValue)) || isValidEns(inputValue) inpAddress.validationError = isValid ? "" : validationError return isValid @@ -48,7 +45,7 @@ Item { } if (textField.focus) { text = metrics.text - } else if (root.isValidAddress(metrics.text)) { + } else if (Utils.isValidAddress(metrics.text)) { text = metrics.elidedText } } diff --git a/ui/shared/ContactSelector.qml b/ui/shared/ContactSelector.qml index 131cb6b455..f096032e2f 100644 --- a/ui/shared/ContactSelector.qml +++ b/ui/shared/ContactSelector.qml @@ -117,8 +117,8 @@ Item { Text { text: name font.pixelSize: 15 - font.family: Style.current.fontBold.name - font.bold: true + font.family: Style.current.fontRegular.name + font.weight: Font.Medium color: Style.current.textColor height: 22 } diff --git a/ui/shared/RecipientSelector.qml b/ui/shared/RecipientSelector.qml index a309d8eb42..2ea823930f 100644 --- a/ui/shared/RecipientSelector.qml +++ b/ui/shared/RecipientSelector.qml @@ -10,28 +10,52 @@ Item { property var contacts property int inputWidth: 272 property int sourceSelectWidth: 136 - property string label: qsTr("Recipient") - property string selectedRecipient: "" - height: inpAddress.height + txtLabel.height + property alias label: txtLabel.text + // If supplied, additional info will be displayed top-right in danger colour (red) + property alias additionalInfo: txtAddlInfo.text + property var selectedRecipient: { } + property bool readOnly: false + height: (readOnly ? inpReadOnly.height : inpAddress.height) + txtLabel.height + readonly property string addressValidationError: qsTr("Invalid ethereum address") function validate() { - if (selAddressSource.selectedSource === "Address") { - inpAddress.validate() + let isValid = true + if (readOnly) { + isValid = Utils.isValidAddress(selectedRecipient.address) + if (!isValid) { + inpReadOnly.validationError = addressValidationError + } + } else if (selAddressSource.selectedSource === "Address") { + isValid = inpAddress.validate() } else if (selAddressSource.selectedSource === "Contact") { - selContact.validate() + isValid = selContact.validate() } + return isValid } Text { id: txtLabel visible: label !== "" - text: root.label + text: qsTr("Recipient") font.pixelSize: 13 - font.family: Style.current.fontBold.name + font.family: Style.current.fontRegular.name + font.weight: Font.Medium color: Style.current.textColor height: 18 } + Text { + id: txtAddlInfo + visible: text !== "" + text: "" + font.pixelSize: 13 + font.family: Style.current.fontRegular.name + font.weight: Font.Medium + color: Style.current.danger + height: 18 + anchors.right: parent.right + } + RowLayout { anchors.top: txtLabel.bottom anchors.topMargin: 7 @@ -39,16 +63,41 @@ Item { anchors.right: parent.right spacing: 8 + Input { + id: inpReadOnly + visible: root.readOnly + Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true + anchors.left: undefined + anchors.right: undefined + text: (root.selectedRecipient && root.selectedRecipient.name) ? root.selectedRecipient.name : qsTr("No recipient selected") + textField.leftPadding: 14 + textField.topPadding: 18 + textField.bottomPadding: 18 + textField.verticalAlignment: TextField.AlignVCenter + textField.font.pixelSize: 15 + textField.color: Style.current.secondaryText + textField.readOnly: true + validationErrorAlignment: TextEdit.AlignRight + validationErrorTopMargin: 8 + customHeight: 56 + } + AddressInput { id: inpAddress width: root.inputWidth label: "" - Layout.preferredWidth: root.inputWidth + visible: !root.readOnly + Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width Layout.alignment: Qt.AlignTop Layout.fillWidth: true - validationError: qsTr("Invalid ethereum address") + validationError: root.addressValidationError onSelectedAddressChanged: { - root.selectedRecipient = selectedAddress + if (root.readOnly) { + return + } + root.selectedRecipient = { address: selectedAddress } } } @@ -58,12 +107,15 @@ Item { visible: false width: root.inputWidth dropdownWidth: parent.width - Layout.preferredWidth: root.inputWidth + Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width Layout.alignment: Qt.AlignTop Layout.fillWidth: true onSelectedContactChanged: { + if (root.readOnly) { + return + } if(selectedContact && selectedContact.address) { - root.selectedRecipient = selectedContact.address + root.selectedRecipient = { name: selectedContact.name, address: selectedContact.address } } } } @@ -75,21 +127,28 @@ Item { width: root.inputWidth dropdownWidth: parent.width label: "" - Layout.preferredWidth: root.inputWidth + Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width Layout.alignment: Qt.AlignTop Layout.fillWidth: true onSelectedAccountChanged: { - root.selectedRecipient = selectedAccount.address + if (root.readOnly) { + return + } + root.selectedRecipient = { address: selectedAccount.address } } } AddressSourceSelector { id: selAddressSource + visible: !root.readOnly sources: ["Address", "Contact", "My account"] width: sourceSelectWidth Layout.preferredWidth: root.sourceSelectWidth Layout.alignment: Qt.AlignTop onSelectedSourceChanged: { + if (root.readOnly) { + return + } switch (selectedSource) { case "Address": inpAddress.visible = true