status-desktop/ui/shared/RecipientSelector.qml
Alexandra Betouni 4ee21ada05 feat(desktop) Added image function in Style
Introduced Style.svg() Style.png() Style.emoji() and
Style.icon() in Style.qml. Those should be used to
set the source in Images instead of using relative
paths. Usage:
Image {
   source: Style.svg("check)
   ....

Also moved all Singletons inside a new "utils"
folder and made it a QML module, to use
import utils 1.0 instead of relative paths

Closes #3678
2021-09-28 15:28:00 -04:00

258 lines
10 KiB
QML

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13
import utils 1.0
Item {
id: root
property var accounts
property var contacts
property int inputWidth: 272
property int sourceSelectWidth: 136
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: inpAddress.height + txtLabel.height
//% "Invalid ethereum address"
readonly property string addressValidationError: qsTrId("invalid-ethereum-address")
property bool isValid: false
property bool isPending: {
if (!selAddressSource.selectedSource) {
return false
}
switch (selAddressSource.selectedSource.value) {
case RecipientSelector.Type.Address:
return inpAddress.isPending
case RecipientSelector.Type.Contact:
return selContact.isPending
case RecipientSelector.Type.Account:
return false // AccountSelector is never pending
}
}
readonly property var sources: [
//% "Address"
{ text: qsTrId("address"), value: RecipientSelector.Type.Address, visible: true },
//% "My account"
{ text: qsTrId("my-account"), value: RecipientSelector.Type.Account, visible: true },
//% "Contact"
{ text: qsTrId("chat-is-a-contact"), value: RecipientSelector.Type.Contact, visible: true }
]
property var selectedType: RecipientSelector.Type.Address
enum Type {
Address,
Contact,
Account
}
function validate() {
let isValid = true
if (!selAddressSource.selectedSource) {
return root.isValid
}
switch (selAddressSource.selectedSource.value) {
case RecipientSelector.Type.Address:
isValid = inpAddress.isValid
break
case RecipientSelector.Type.Contact:
isValid = selContact.isValid
break
case RecipientSelector.Type.Account:
isValid = selAccount.isValid
break
}
root.isValid = isValid
return isValid
}
function getSourceByType(type) {
return root.sources.find(source => source.value === type)
}
onSelectedTypeChanged: {
if (selectedType !== undefined) {
selAddressSource.selectedSource = getSourceByType(selectedType)
}
if (!selectedRecipient) {
return
}
switch (root.selectedType) {
case RecipientSelector.Type.Address:
inpAddress.input.text = selectedRecipient.name || ""
inpAddress.visible = true
selContact.visible = selAccount.visible = false
if(!!selectedRecipient.address){
inpAddress.selectedAddress = selectedRecipient.address
}
break
case RecipientSelector.Type.Contact:
selContact.selectedContact = selectedRecipient
// TODO: we shouldn't have to call resolveEns from the outside.
// It should be handled automatically when selectedContact is
// updated, however, handling it on property change causes an
// infinite loop
selContact.resolveEns()
selContact.visible = true
inpAddress.visible = selAccount.visible = false
break
case RecipientSelector.Type.Account:
selAccount.selectedAccount = selectedRecipient
selAccount.visible = true
inpAddress.visible = selContact.visible = false
break
}
}
Text {
id: txtLabel
visible: label !== ""
//% "Recipient"
text: qsTrId("recipient")
font.pixelSize: 13
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
anchors.left: parent.left
anchors.right: parent.right
spacing: 8
AddressInput {
id: inpAddress
width: root.inputWidth
input.label: ""
input.readOnly: root.readOnly
visible: true
Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
validationError: root.addressValidationError
parentWidth: parent.width
onSelectedAddressChanged: {
if (!selAddressSource.selectedSource || (selAddressSource.selectedSource && selAddressSource.selectedSource.value !== RecipientSelector.Type.Address)) {
return
}
root.selectedRecipient = { address: selectedAddress, type: RecipientSelector.Type.Address }
}
onIsValidChanged: root.validate()
}
ContactSelector {
id: selContact
contacts: root.contacts
visible: false
width: root.inputWidth
dropdownWidth: parent.width
readOnly: root.readOnly
Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
onSelectedContactChanged: {
if (!selectedContact || !selAddressSource.selectedSource || !selectedContact.address || (selAddressSource.selectedSource && selAddressSource.selectedSource.value !== RecipientSelector.Type.Contact)) {
return
}
const { address, name, alias, isContact, identicon, ensVerified } = selectedContact
root.selectedRecipient = { address, name, alias, isContact, identicon, ensVerified, type: RecipientSelector.Type.Contact }
}
onIsValidChanged: root.validate()
}
AccountSelector {
id: selAccount
accounts: root.accounts
visible: false
width: root.inputWidth
dropdownWidth: parent.width
label: ""
Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
onSelectedAccountChanged: {
if (!selectedAccount || !selAddressSource.selectedSource || (selAddressSource.selectedSource && selAddressSource.selectedSource.value !== RecipientSelector.Type.Account)) {
return
}
const { address, name, iconColor, assets, fiatBalance } = selectedAccount
root.selectedRecipient = { address, name, iconColor, assets, fiatBalance, type: RecipientSelector.Type.Account }
}
onIsValidChanged: root.validate()
}
AddressSourceSelector {
id: selAddressSource
visible: !root.readOnly
sources: root.sources.filter(source => source.visible)
width: sourceSelectWidth
Layout.preferredWidth: root.sourceSelectWidth
Layout.alignment: Qt.AlignTop
onSelectedSourceChanged: {
if (root.readOnly || !selectedSource) {
return
}
let address, name
switch (selectedSource.value) {
case RecipientSelector.Type.Address:
inpAddress.visible = true
selContact.visible = selAccount.visible = false
root.height = Qt.binding(function() { return inpAddress.height + txtLabel.height })
root.selectedRecipient = { address: inpAddress.selectedAddress, type: RecipientSelector.Type.Address }
if (root.selectedType !== RecipientSelector.Type.Address) root.selectedType = RecipientSelector.Type.Address
root.isValid = inpAddress.isValid
break;
case RecipientSelector.Type.Contact:
selContact.visible = true
inpAddress.visible = selAccount.visible = false
root.height = Qt.binding(function() { return selContact.height + txtLabel.height })
let { alias, isContact, identicon, ensVerified } = selContact.selectedContact
address = selContact.selectedContact.address
name = selContact.selectedContact.name
root.selectedRecipient = { address, name, alias, isContact, identicon, ensVerified, type: RecipientSelector.Type.Contact }
if (root.selectedType !== RecipientSelector.Type.Contact) root.selectedType = RecipientSelector.Type.Contact
root.isValid = selContact.isValid
break;
case RecipientSelector.Type.Account:
selAccount.visible = true
inpAddress.visible = selContact.visible = false
root.height = Qt.binding(function() { return selAccount.height + txtLabel.height })
const { iconColor, assets, fiatBalance } = selAccount.selectedAccount
address = selAccount.selectedAccount.address
name = selAccount.selectedAccount.name
root.selectedRecipient = { address, name, iconColor, assets, fiatBalance, type: RecipientSelector.Type.Account }
if (root.selectedType !== RecipientSelector.Type.Account) root.selectedType = RecipientSelector.Type.Account
root.isValid = selAccount.isValid
break;
}
}
}
}
}
/*##^##
Designer {
D{i:0;autoSize:true;height:480;width:640}
}
##^##*/