fix: Reimplemented selectors using `StatusComboBox`

This commit is contained in:
Igor Sirotin 2022-07-31 10:17:07 +03:00 committed by Lukáš Tinkl
parent be6240e41c
commit 5fb2be95ef
6 changed files with 101 additions and 170 deletions

@ -1 +1 @@
Subproject commit f4bf830ae7af5979255b383920980bf4d3a4b251 Subproject commit 63ff9b82d1f13c063dddbb244a255a9886705fc7

View File

@ -686,15 +686,6 @@ Assets won&#8217;t be sent yet.</source>
Assets won&#8217;t be sent yet.</translation> Assets won&#8217;t be sent yet.</translation>
</message> </message>
</context> </context>
<context>
<name>AddressSourceSelector</name>
<message>
<location filename="../imports/shared/controls/AddressSourceSelector.qml" line="29" />
<location filename="../imports/shared/controls/AddressSourceSelector.qml" line="29" />
<source>Invalid source</source>
<translation>Invalid source</translation>
</message>
</context>
<context> <context>
<name>AdvancedAddAccountView</name> <name>AdvancedAddAccountView</name>
<message> <message>

View File

@ -1,49 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
import utils 1.0
Item {
id: root
property var sources: []
property var selectedSource: sources.length ? sources[0] : null
property int dropdownWidth: 220
height: select.height
StatusSelect {
id: select
anchors.left: parent.left
anchors.right: parent.right
model: root.sources
selectedItemComponent: Item {
anchors.fill: parent
StatusBaseText {
id: selectedTextField
text: !!root.selectedSource ? root.selectedSource.text : qsTr("Invalid source")
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15
verticalAlignment: Text.AlignVCenter
height: 24
color: Theme.palette.directColor1
}
}
selectMenu.delegate: StatusMenuItemDelegate {
statusPopupMenu: select
action: StatusMenuItem {
text: root.sources[index].text
onTriggered: function () {
root.selectedSource = root.sources[index]
}
}
}
}
}

View File

@ -18,10 +18,9 @@ Item {
id: root id: root
property var contactsStore property var contactsStore
property var selectedContact property var selectedContact
height: select.height
property int dropdownWidth: width property int dropdownWidth: width
property string validationError: qsTr("Please select a contact") property string validationError: qsTr("Please select a contact")
property alias validationErrorAlignment: select.validationErrorAlignment // property alias validationErrorAlignment: comboBox.validationErrorAlignment
property bool isValid: false property bool isValid: false
property alias isPending: ensResolver.isPending property alias isPending: ensResolver.isPending
@ -37,6 +36,8 @@ Item {
} }
} }
implicitHeight: comboBox.implicitHeight
Component.onCompleted: { Component.onCompleted: {
if (root.readOnly) { if (root.readOnly) {
return return
@ -53,14 +54,14 @@ Item {
let isValidAddress = Utils.isValidAddress(selectedContact.address) let isValidAddress = Utils.isValidAddress(selectedContact.address)
let isDefaultValue = selectedContact.alias === selectAContact let isDefaultValue = selectedContact.alias === selectAContact
let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress
select.validationError = "" comboBox.validationError = ""
if (!isValid && !isDefaultValue && if (!isValid && !isDefaultValue &&
( (
!selectedContact.ensVerified || !selectedContact.ensVerified ||
(selectedContact.ensVerified && isResolvedAddress) (selectedContact.ensVerified && isResolvedAddress)
) )
) { ) {
select.validationError = !selectedContact.ensVerified ? noEnsAddressMessage : validationError comboBox.validationError = !selectedContact.ensVerified ? noEnsAddressMessage : validationError
} }
root.isValid = isValid root.isValid = isValid
return isValid return isValid
@ -83,20 +84,22 @@ Item {
customHeight: 56 customHeight: 56
} }
StatusSelect { StatusComboBox {
id: select id: comboBox
label: "" label: ""
model: root.contactsStore.myContactsModel model: root.contactsStore.myContactsModel
width: parent.width width: parent.width
visible: !root.readOnly visible: !root.readOnly
menuAlignment: StatusSelect.MenuAlignment.Left
selectedItemComponent: Item { control.popup.width: dropdownWidth
anchors.fill: parent control.padding: 14
enabled: control.count > 0
contentItem: RowLayout {
spacing: 4
StatusSmartIdenticon { StatusSmartIdenticon {
id: iconImg
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
image.width: (!!selectedContact && !!selectedContact.displayIcon) ? 32 : 0 image.width: (!!selectedContact && !!selectedContact.displayIcon) ? 32 : 0
image.height: 32 image.height: 32
image.source: (!!selectedContact && !!selectedContact.displayIcon) ? selectedContact.displayIcon : "" image.source: (!!selectedContact && !!selectedContact.displayIcon) ? selectedContact.displayIcon : ""
@ -104,37 +107,77 @@ Item {
} }
StatusBaseText { StatusBaseText {
id: selectedTextField id: selectedTextField
visible: comboBox.control.count > 0
text: !!selectedContact ? selectedContact.alias : "" text: !!selectedContact ? selectedContact.alias : ""
anchors.left: iconImg.right
anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15 font.pixelSize: 15
height: 22 height: 22
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: Theme.palette.directColor1 color: Theme.palette.directColor1
} }
}
zeroItemsView: Item {
height: 186
StatusBaseText { StatusBaseText {
anchors.fill: parent visible: comboBox.control.count == 0
text: qsTr("You dont have any contacts yet") text: qsTr("You dont have any contacts yet")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 13 font.pixelSize: 13
height: 18
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
} }
} }
selectMenu.delegate: menuItem delegate: StatusItemDelegate {
selectMenu.width: dropdownWidth id: itemContainer
property var currentContact: Utils.getContactDetailsAsJson(pubKey)
highlighted: index === comboBox.control.highlightedIndex
width: parent.width
onClicked: {
root.selectedContact = itemContainer.currentContact
}
contentItem: RowLayout {
spacing: 12
StatusSmartIdenticon {
image.source: currentContact.displayIcon
}
ColumnLayout {
Layout.fillWidth: true
StatusBaseText {
Layout.fillWidth: true
text: currentContact.alias
font.pixelSize: 15
color: Theme.palette.directColor1
}
RowLayout {
Layout.fillWidth: true
StatusBaseText {
Layout.fillWidth: true
text: currentContact.name + " • "
visible: currentContact.ensVerified
color: Theme.palette.baseColor1
font.pixelSize: 12
}
StatusBaseText {
Layout.fillWidth: true
Layout.maximumWidth: 85
text: currentContact.publicKey
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
font.pixelSize: 12
}
}
}
}
}
} }
EnsResolver { EnsResolver {
id: ensResolver id: ensResolver
anchors.top: select.bottom anchors.top: comboBox.bottom
anchors.right: select.right anchors.right: comboBox.right
anchors.topMargin: Style.current.halfPadding anchors.topMargin: Style.current.halfPadding
debounceDelay: 0 debounceDelay: 0
onResolved: { onResolved: {
@ -149,67 +192,4 @@ Item {
} }
} }
} }
Component {
id: menuItem
MenuItem {
id: itemContainer
property bool isFirstItem: index === 0
property bool isLastItem: index === root.contactsStore.myContactsModel.count - 1
property var currentContact: Utils.getContactDetailsAsJson(pubKey)
width: parent.width
height: visible ? 72 : 0
StatusSmartIdenticon {
id: iconImg
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
image.source: currentContact.displayIcon
}
Column {
anchors.left: iconImg.right
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
StatusBaseText {
text: currentContact.alias
font.pixelSize: 15
color: Theme.palette.directColor1
height: 22
}
Row {
StatusBaseText {
text: currentContact.name + " • "
visible: currentContact.ensVerified
color: Theme.palette.baseColor1
font.pixelSize: 12
height: 16
}
StatusBaseText {
text: currentContact.publicKey
width: 85
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
font.pixelSize: 12
height: 16
}
}
}
background: Rectangle {
color: itemContainer.highlighted ? Theme.palette.statusSelect.menuItemHoverBackgroundColor : Theme.palette.statusSelect.menuItemBackgroundColor
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: itemContainer
onClicked: {
root.selectedContact = itemContainer.currentContact
resolveEns()
select.selectMenu.close()
}
}
}
}
} }

View File

@ -17,7 +17,7 @@ Item {
property var accounts property var accounts
property int inputWidth: 272 property int inputWidth: 272
property int sourceSelectWidth: 136 property int sourceSelectWidth: 150
property alias label: txtLabel.text property alias label: txtLabel.text
property alias labelFont: txtLabel.font property alias labelFont: txtLabel.font
property alias input: inpAddress.input property alias input: inpAddress.input
@ -31,10 +31,10 @@ Item {
property bool isSelectorVisible: true property bool isSelectorVisible: true
property bool addContactEnabled: true property bool addContactEnabled: true
property bool isPending: { property bool isPending: {
if (!selAddressSource.selectedSource) { if (!selAddressSource.currentValue) {
return false return false
} }
switch (selAddressSource.selectedSource.value) { switch (selAddressSource.currentValue.value) {
case RecipientSelector.Type.Address: case RecipientSelector.Type.Address:
return inpAddress.isPending return inpAddress.isPending
case RecipientSelector.Type.Contact: case RecipientSelector.Type.Contact:
@ -42,12 +42,15 @@ Item {
case RecipientSelector.Type.Account: case RecipientSelector.Type.Account:
return false // AccountSelector is never pending return false // AccountSelector is never pending
} }
return false;
} }
readonly property var sources: [ readonly property var sources: [
{ text: qsTr("Address"), value: RecipientSelector.Type.Address, visible: true }, { text: qsTr("Address"), value: RecipientSelector.Type.Address, visible: true },
{ text: qsTr("My account"), value: RecipientSelector.Type.Account, visible: true }, { text: qsTr("My account"), value: RecipientSelector.Type.Account, visible: true },
{ text: qsTr("Contact"), value: RecipientSelector.Type.Contact, visible: true } { text: qsTr("Contact"), value: RecipientSelector.Type.Contact, visible: true }
] ]
property var selectedType: RecipientSelector.Type.Address property var selectedType: RecipientSelector.Type.Address
enum Type { enum Type {
@ -58,10 +61,10 @@ Item {
function validate() { function validate() {
let isValid = true let isValid = true
if (!selAddressSource.selectedSource) { if (!selAddressSource.currentValue) {
return root.isValid return root.isValid
} }
switch (selAddressSource.selectedSource.value) { switch (selAddressSource.currentValue.value) {
case RecipientSelector.Type.Address: case RecipientSelector.Type.Address:
isValid = inpAddress.isValid isValid = inpAddress.isValid
break break
@ -76,13 +79,9 @@ Item {
return isValid return isValid
} }
function getSourceByType(type) { function updateAddressComboBox() {
return root.sources.find(source => source.value === type)
}
onSelectedTypeChanged: {
if (selectedType !== undefined) { if (selectedType !== undefined) {
selAddressSource.selectedSource = getSourceByType(selectedType) selAddressSource.control.currentIndex = selAddressSource.control.indexOfValue(selectedType)
} }
if (!selectedRecipient) { if (!selectedRecipient) {
return return
@ -114,6 +113,14 @@ Item {
} }
} }
onSelectedTypeChanged: {
updateAddressComboBox();
}
Component.onCompleted: {
updateAddressComboBox();
}
implicitHeight: inpAddress.height + txtLabel.height implicitHeight: inpAddress.height + txtLabel.height
Text { Text {
@ -162,7 +169,7 @@ Item {
parentWidth: parent.width parentWidth: parent.width
addContactEnabled: root.addContactEnabled addContactEnabled: root.addContactEnabled
onSelectedAddressChanged: { onSelectedAddressChanged: {
if (!selAddressSource.selectedSource || (selAddressSource.selectedSource && selAddressSource.selectedSource.value !== RecipientSelector.Type.Address)) { if (!selAddressSource.currentValue || (selAddressSource.currentValue && selAddressSource.currentValue.value !== RecipientSelector.Type.Address)) {
return return
} }
@ -182,7 +189,7 @@ Item {
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true Layout.fillWidth: true
onSelectedContactChanged: { onSelectedContactChanged: {
if (!selectedContact || !selAddressSource.selectedSource || !selectedContact.address || (selAddressSource.selectedSource && selAddressSource.selectedSource.value !== RecipientSelector.Type.Contact)) { if (!selectedContact || !selAddressSource.currentValue || !selectedContact.address || (selAddressSource.currentValue && selAddressSource.currentValue.value !== RecipientSelector.Type.Contact)) {
return return
} }
const { address, name, alias, pubKey, icon, isContact, ensVerified } = selectedContact const { address, name, alias, pubKey, icon, isContact, ensVerified } = selectedContact
@ -202,7 +209,7 @@ Item {
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true Layout.fillWidth: true
onSelectedAccountChanged: { onSelectedAccountChanged: {
if (!selectedAccount || !selAddressSource.selectedSource || (selAddressSource.selectedSource && selAddressSource.selectedSource.value !== RecipientSelector.Type.Account)) { if (!selectedAccount || !selAddressSource.currentValue || (selAddressSource.currentValue && selAddressSource.currentValue.value !== RecipientSelector.Type.Account)) {
return return
} }
const { address, name, color, assets, fiatBalance } = selectedAccount const { address, name, color, assets, fiatBalance } = selectedAccount
@ -210,20 +217,23 @@ Item {
} }
onIsValidChanged: root.validate() onIsValidChanged: root.validate()
} }
AddressSourceSelector { StatusComboBox {
id: selAddressSource id: selAddressSource
visible: isSelectorVisible && !root.readOnly visible: isSelectorVisible && !root.readOnly
sources: root.sources.filter(source => source.visible) model: root.sources.filter(source => source.visible)
width: sourceSelectWidth width: sourceSelectWidth
Layout.preferredWidth: root.sourceSelectWidth Layout.preferredWidth: root.sourceSelectWidth
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
onSelectedSourceChanged: { control.textRole: "text"
if (root.readOnly || !selectedSource) { control.valueRole: "value"
onCurrentValueChanged: {
if (root.readOnly || !currentValue) {
return return
} }
let address, name let address, name
switch (selectedSource.value) { switch (currentValue) {
case RecipientSelector.Type.Address: case RecipientSelector.Type.Address:
inpAddress.visible = true inpAddress.visible = true
selContact.visible = selAccount.visible = false selContact.visible = selAccount.visible = false

View File

@ -1,5 +1,4 @@
AddressInput 1.0 AddressInput.qml AddressInput 1.0 AddressInput.qml
AddressSourceSelector 1.0 AddressSourceSelector.qml
AssetAndAmountInput 1.0 AssetAndAmountInput.qml AssetAndAmountInput 1.0 AssetAndAmountInput.qml
AssetDelegate 1.0 AssetDelegate.qml AssetDelegate 1.0 AssetDelegate.qml
ContactSelector 1.0 ContactSelector.qml ContactSelector 1.0 ContactSelector.qml