mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-17 17:19:02 +00:00
Remove unused RecipientSelector and related components
This commit is contained in:
parent
e864897863
commit
d5a0589591
@ -1,165 +0,0 @@
|
|||||||
import QtQuick 2.14
|
|
||||||
import QtQuick.Controls 2.14
|
|
||||||
|
|
||||||
import shared.controls 1.0
|
|
||||||
import shared.stores 1.0
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
|
|
||||||
Pane {
|
|
||||||
QtObject {
|
|
||||||
id: userProfileInst
|
|
||||||
|
|
||||||
Component.onCompleted: RootStore.userProfileInst = userProfileInst
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: gifsModule
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: mainModule
|
|
||||||
|
|
||||||
signal resolvedENS
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: globalUtilsInst
|
|
||||||
|
|
||||||
function isCompressedPubKey() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCompressedPk(publicKey) {
|
|
||||||
return "zx3sh" + publicKey
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: Utils.globalUtilsInst = globalUtilsInst
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: mainModuleInst
|
|
||||||
|
|
||||||
function isCompressedPubKey() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
function getContactDetailsAsJson() {
|
|
||||||
return JSON.stringify({
|
|
||||||
alias: "alias",
|
|
||||||
isAdded: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: Utils.mainModuleInst = mainModuleInst
|
|
||||||
}
|
|
||||||
|
|
||||||
ContactsListAndSearch {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
community: ({ id: "communityId" })
|
|
||||||
|
|
||||||
contactsStore: QtObject {
|
|
||||||
readonly property ListModel myContactsModel: ListModel {
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x1"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: "l1"
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x2 sdfsd"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x3 xcvxcv"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x4 drt5"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x4 drt5e"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x4 drtew5"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x4 drt5e"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
pubKey: "0x02342342342"
|
|
||||||
isContact: true
|
|
||||||
onlineStatus: true
|
|
||||||
displayName: "x4 drtew5"
|
|
||||||
icon: ""
|
|
||||||
colorId: 0
|
|
||||||
ensName: "ens name"
|
|
||||||
isBlocked: false
|
|
||||||
alias: "some alias"
|
|
||||||
localNickname: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// category: Components
|
|
@ -225,11 +225,6 @@ StatusWindow {
|
|||||||
selected: viewLoader.source.toString().includes(title)
|
selected: viewLoader.source.toString().includes(title)
|
||||||
onClicked: mainPageView.page(title);
|
onClicked: mainPageView.page(title);
|
||||||
}
|
}
|
||||||
StatusNavigationListItem {
|
|
||||||
title: "StatusAccountSelector"
|
|
||||||
selected: viewLoader.source.toString().includes(title)
|
|
||||||
onClicked: mainPageView.page(title);
|
|
||||||
}
|
|
||||||
StatusNavigationListItem {
|
StatusNavigationListItem {
|
||||||
title: "StatusColorSelector"
|
title: "StatusColorSelector"
|
||||||
selected: viewLoader.source.toString().includes(title)
|
selected: viewLoader.source.toString().includes(title)
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
import QtQuick 2.14
|
|
||||||
import QtQuick.Controls 2.14
|
|
||||||
import QtQuick.Layouts 1.14
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
import StatusQ.Controls 0.1
|
|
||||||
import StatusQ.Popups 0.1
|
|
||||||
|
|
||||||
Column {
|
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
StatusAccountSelector {
|
|
||||||
id: selector1
|
|
||||||
width: 300
|
|
||||||
accounts: accountsModel
|
|
||||||
}
|
|
||||||
|
|
||||||
ListModel {
|
|
||||||
id: accountsModel
|
|
||||||
|
|
||||||
ListElement {
|
|
||||||
name: "Pascal"
|
|
||||||
address: "0x1234567891011"
|
|
||||||
path: ""
|
|
||||||
color: "red"
|
|
||||||
publicKey: ""
|
|
||||||
walletType: "generated"
|
|
||||||
isChat: ""
|
|
||||||
currencyBalance: "1199.02"
|
|
||||||
assets: []
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
name: "Boris"
|
|
||||||
address: "0x123"
|
|
||||||
path: ""
|
|
||||||
color: "red"
|
|
||||||
publicKey: ""
|
|
||||||
walletType: "generated"
|
|
||||||
isChat: ""
|
|
||||||
currencyBalance: "42.42"
|
|
||||||
assets: []
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
name: "Alexandra"
|
|
||||||
address: "0x123"
|
|
||||||
path: ""
|
|
||||||
color: "yellow"
|
|
||||||
publicKey: ""
|
|
||||||
walletType: "generated"
|
|
||||||
isChat: ""
|
|
||||||
currencyBalance: "0"
|
|
||||||
assets: []
|
|
||||||
}
|
|
||||||
ListElement {
|
|
||||||
name: "Khushboo"
|
|
||||||
address: "0x123"
|
|
||||||
path: ""
|
|
||||||
color: "blue"
|
|
||||||
publicKey: ""
|
|
||||||
walletType: "watch" // Will be automatically filtered by StatusAccountSelector
|
|
||||||
isChat: ""
|
|
||||||
currencyBalance: "0"
|
|
||||||
assets: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -42,7 +42,6 @@
|
|||||||
<file>images/SRToken.png</file>
|
<file>images/SRToken.png</file>
|
||||||
<file>images/StatusPunks.png</file>
|
<file>images/StatusPunks.png</file>
|
||||||
<file>images/SuperRareCommunityBanner.png</file>
|
<file>images/SuperRareCommunityBanner.png</file>
|
||||||
<file>pages/StatusAccountSelectorPage.qml</file>
|
|
||||||
<file>pages/StatusAddressPage.qml</file>
|
<file>pages/StatusAddressPage.qml</file>
|
||||||
<file>pages/StatusCardPage.qml</file>
|
<file>pages/StatusCardPage.qml</file>
|
||||||
<file>pages/StatusChatCommandButtonPage.qml</file>
|
<file>pages/StatusChatCommandButtonPage.qml</file>
|
||||||
|
@ -1,287 +0,0 @@
|
|||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
import QtQuick.Layouts 1.13
|
|
||||||
import QtQml.Models 2.14
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
import StatusQ.Core.Utils 0.1
|
|
||||||
import StatusQ.Controls 0.1
|
|
||||||
|
|
||||||
import SortFilterProxyModel 0.2
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property string label: qsTr("Choose account")
|
|
||||||
property bool showAccountDetails: !!selectedAccount
|
|
||||||
property var accounts
|
|
||||||
property var selectedAccount
|
|
||||||
property string currency: "USD"
|
|
||||||
|
|
||||||
// set to asset symbol to display asset's balance top right
|
|
||||||
// NOTE: if this asset is not selected as a wallet token in the UI, then
|
|
||||||
// nothing will be displayed
|
|
||||||
property string showBalanceForAssetSymbol: ""
|
|
||||||
property var assetFound
|
|
||||||
property double minRequiredAssetBalance: 0
|
|
||||||
property int dropdownWidth: width
|
|
||||||
property int chainId: 0
|
|
||||||
property bool isValid: true
|
|
||||||
property bool readOnly: false
|
|
||||||
|
|
||||||
|
|
||||||
property var assetBalanceTextFn: function (foundValue) {
|
|
||||||
return qsTr("Balance: %1").arg(parseFloat(foundValue) === 0.0 ? Qt.locale().zeroDigit
|
|
||||||
: LocaleUtils.numberToLocaleString(foundValue))
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property string watchWalletType: "watch"
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
Address,
|
|
||||||
Contact,
|
|
||||||
Account
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate() {
|
|
||||||
if (showBalanceForAssetSymbol == "" || minRequiredAssetBalance == 0 || !assetFound) {
|
|
||||||
return root.isValid
|
|
||||||
}
|
|
||||||
root.isValid = assetFound.totalBalance.amount >= minRequiredAssetBalance
|
|
||||||
return root.isValid
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitWidth: 448
|
|
||||||
implicitHeight: comboBox.height +
|
|
||||||
(selectedAccountDetails.visible ? selectedAccountDetails.height + selectedAccountDetails.anchors.topMargin
|
|
||||||
: 0)
|
|
||||||
|
|
||||||
onSelectedAccountChanged: {
|
|
||||||
if (!selectedAccount) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (selectedAccount.color) {
|
|
||||||
d.selectedIconColor = Utils.getThemeAccountColor(selectedAccount.color, Theme.palette.userCustomizationColors) || Theme.palette.userCustomizationColors[0]
|
|
||||||
}
|
|
||||||
if (selectedAccount.name) {
|
|
||||||
d.selectedText = selectedAccount.name
|
|
||||||
}
|
|
||||||
if (selectedAccount.address) {
|
|
||||||
textSelectedAddress.text = selectedAccount.address
|
|
||||||
}
|
|
||||||
if (selectedAccount.currencyBalance) {
|
|
||||||
textSelectedAddressFiatBalance.text = LocaleUtils.currencyAmountToLocaleString(selectedAccount.currencyBalance)
|
|
||||||
}
|
|
||||||
if (selectedAccount.assets && showBalanceForAssetSymbol) {
|
|
||||||
assetFound = Utils.findAssetByChainAndSymbol(root.chainId, selectedAccount.assets, showBalanceForAssetSymbol)
|
|
||||||
if (!assetFound) {
|
|
||||||
console.warn("Cannot find asset '", showBalanceForAssetSymbol, "'. Ensure this asset has been added to the token list.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!selectedAccount.type) {
|
|
||||||
selectedAccount.type = StatusAccountSelector.Type.Account
|
|
||||||
}
|
|
||||||
validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
onAssetFoundChanged: {
|
|
||||||
if (!assetFound) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
txtAssetBalance.text = root.assetBalanceTextFn(assetFound.totalBalance.amount)
|
|
||||||
txtAssetSymbol.text = " " + assetFound.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: d
|
|
||||||
property color selectedIconColor: "transparent"
|
|
||||||
property string selectedText: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
id: txtAssetBalance
|
|
||||||
visible: root.assetFound !== undefined
|
|
||||||
anchors.bottom: comboBox.top
|
|
||||||
anchors.bottomMargin: -18
|
|
||||||
anchors.right: txtAssetSymbol.left
|
|
||||||
anchors.left: comboBox.left
|
|
||||||
anchors.leftMargin: comboBox.width / 2.5
|
|
||||||
|
|
||||||
color: !root.isValid ? Theme.palette.dangerColor1 : Theme.palette.baseColor1
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font.pixelSize: 13
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
height: 18
|
|
||||||
|
|
||||||
StatusToolTip {
|
|
||||||
enabled: txtAssetBalance.truncated
|
|
||||||
id: assetTooltip
|
|
||||||
text: txtAssetBalance.text
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
enabled: txtAssetBalance.truncated
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: enabled
|
|
||||||
onEntered: assetTooltip.visible = true
|
|
||||||
onExited: assetTooltip.visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
id: txtAssetSymbol
|
|
||||||
visible: txtAssetBalance.visible
|
|
||||||
anchors.top: txtAssetBalance.top
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
color: txtAssetBalance.color
|
|
||||||
font.pixelSize: 13
|
|
||||||
height: txtAssetBalance.height
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusComboBox {
|
|
||||||
id: comboBox
|
|
||||||
|
|
||||||
label: root.label
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
model: SortFilterProxyModel {
|
|
||||||
sourceModel: !!root.accounts ? root.accounts : null
|
|
||||||
filters: [
|
|
||||||
ValueFilter {
|
|
||||||
roleName: "walletType"
|
|
||||||
value: root.watchWalletType
|
|
||||||
inverted: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
contentItem: RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
StatusIcon {
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
Layout.preferredWidth: 20
|
|
||||||
Layout.preferredHeight: 20
|
|
||||||
icon: "filled-account"
|
|
||||||
color: d.selectedIconColor
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
elide: Text.ElideRight
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
font.pixelSize: 15
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
text: d.selectedText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: StatusItemDelegate {
|
|
||||||
highlighted: index === comboBox.control.highlightedIndex
|
|
||||||
width: comboBox.width
|
|
||||||
padding: 16
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
// WARNING: Settings comboBox value from delegate is wrong.
|
|
||||||
// ComboBox must have a single role as "value"
|
|
||||||
// This should be refactored later. Probably roleValue should be 'address'.
|
|
||||||
// All other needed values should be retrived from model by the user of component.
|
|
||||||
root.selectedAccount = { address, name, color: model.color, assets, currencyBalance };
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
// WARNING: Same here, this is wrong, check comment above.
|
|
||||||
if (!root.selectedAccount && index === 0) {
|
|
||||||
root.selectedAccount = { address, name, color: model.color, assets, currencyBalance }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: RowLayout {
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
StatusIcon {
|
|
||||||
id: iconImg
|
|
||||||
Layout.preferredWidth: 20
|
|
||||||
Layout.preferredHeight: 20
|
|
||||||
icon: "filled-account"
|
|
||||||
color: Utils.getThemeAccountColor(model.color, Theme.palette.userCustomizationColors) ||
|
|
||||||
Theme.palette.userCustomizationColors[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: column
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: 14
|
|
||||||
Layout.rightMargin: 8
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
id: accountName
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: model.name
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
id: accountAddress
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.maximumWidth: 80
|
|
||||||
text: address
|
|
||||||
elide: Text.ElideMiddle
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
font.pixelSize: 12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
id: txtFiatBalance
|
|
||||||
Layout.rightMargin: 4
|
|
||||||
font.pixelSize: 15
|
|
||||||
text: LocaleUtils.currencyAmountToLocaleString(currencyBalance, {noSymbol: true})
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
id: fiatCurrencySymbol
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
text: root.currency.toUpperCase()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: selectedAccountDetails
|
|
||||||
visible: root.showAccountDetails
|
|
||||||
anchors.top: comboBox.bottom
|
|
||||||
anchors.topMargin: 8
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 2
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 4
|
|
||||||
|
|
||||||
spacing: 2
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
id: textSelectedAddress
|
|
||||||
Layout.maximumWidth: 80
|
|
||||||
font.pixelSize: 12
|
|
||||||
elide: Text.ElideMiddle
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
font.pixelSize: 12
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
text: "•"
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
id: textSelectedAddressFiatBalance
|
|
||||||
Layout.fillWidth: true
|
|
||||||
font.pixelSize: 12
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,66 +1,65 @@
|
|||||||
module StatusQ.Controls
|
module StatusQ.Controls
|
||||||
|
|
||||||
StatusAccountSelector 0.1 StatusAccountSelector.qml
|
StatusActivityCenterButton 0.1 StatusActivityCenterButton.qml
|
||||||
|
StatusAmountInput 0.1 StatusAmountInput.qml
|
||||||
|
StatusBackButton 0.1 StatusBackButton.qml
|
||||||
StatusBanner 0.1 StatusBanner.qml
|
StatusBanner 0.1 StatusBanner.qml
|
||||||
|
StatusBaseButton 0.1 StatusBaseButton.qml
|
||||||
|
StatusBaseInput 0.1 StatusBaseInput.qml
|
||||||
|
StatusBlockProgressBar 0.1 StatusBlockProgressBar.qml
|
||||||
|
StatusButton 0.1 StatusButton.qml
|
||||||
|
StatusButtonRow 0.1 StatusButtonRow.qml
|
||||||
StatusChatCommandButton 0.1 StatusChatCommandButton.qml
|
StatusChatCommandButton 0.1 StatusChatCommandButton.qml
|
||||||
StatusChatInfoButton 0.1 StatusChatInfoButton.qml
|
StatusChatInfoButton 0.1 StatusChatInfoButton.qml
|
||||||
StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml
|
StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml
|
||||||
StatusClearButton 0.1 StatusClearButton.qml
|
|
||||||
StatusColorSelector 0.1 StatusColorSelector.qml
|
|
||||||
StatusIconTabButton 0.1 StatusIconTabButton.qml
|
|
||||||
StatusIdenticonRing 0.1 StatusIdenticonRing.qml
|
|
||||||
StatusItemPicker 0.1 StatusItemPicker.qml
|
|
||||||
StatusNavigationButton 0.1 StatusNavigationButton.qml
|
|
||||||
StatusNavBarTabButton 0.1 StatusNavBarTabButton.qml
|
|
||||||
StatusTabBarIconButton 0.1 StatusTabBarIconButton.qml
|
|
||||||
StatusToolTip 0.1 StatusToolTip.qml
|
|
||||||
StatusBaseButton 0.1 StatusBaseButton.qml
|
|
||||||
StatusButton 0.1 StatusButton.qml
|
|
||||||
StatusButtonRow 0.1 StatusButtonRow.qml
|
|
||||||
StatusFlatButton 0.1 StatusFlatButton.qml
|
|
||||||
StatusRoundButton 0.1 StatusRoundButton.qml
|
|
||||||
StatusFlatRoundButton 0.1 StatusFlatRoundButton.qml
|
|
||||||
StatusCommunityTag 0.1 StatusCommunityTag.qml
|
|
||||||
StatusSwitch 0.1 StatusSwitch.qml
|
|
||||||
StatusRadioButton 0.1 StatusRadioButton.qml
|
|
||||||
StatusCheckBox 0.1 StatusCheckBox.qml
|
StatusCheckBox 0.1 StatusCheckBox.qml
|
||||||
StatusSlider 0.1 StatusSlider.qml
|
StatusCircularProgressBar 0.1 StatusCircularProgressBar.qml
|
||||||
StatusLabeledSlider 0.1 StatusLabeledSlider.qml
|
StatusClearButton 0.1 StatusClearButton.qml
|
||||||
StatusSelect 0.1 StatusSelect.qml
|
StatusColorRadioButton 0.1 StatusColorRadioButton.qml
|
||||||
StatusBaseInput 0.1 StatusBaseInput.qml
|
StatusColorSelector 0.1 StatusColorSelector.qml
|
||||||
|
StatusColorSelectorGrid 0.1 StatusColorSelectorGrid.qml
|
||||||
|
StatusComboBox 0.1 StatusComboBox.qml
|
||||||
|
StatusCommunityTag 0.1 StatusCommunityTag.qml
|
||||||
|
StatusDropdown 0.1 StatusDropdown.qml
|
||||||
|
StatusFlatButton 0.1 StatusFlatButton.qml
|
||||||
|
StatusFlatRoundButton 0.1 StatusFlatRoundButton.qml
|
||||||
|
StatusIconSwitch 0.1 StatusIconSwitch.qml
|
||||||
|
StatusIconTabButton 0.1 StatusIconTabButton.qml
|
||||||
|
StatusIconTextButton 0.1 StatusIconTextButton.qml
|
||||||
|
StatusIdenticonRing 0.1 StatusIdenticonRing.qml
|
||||||
|
StatusImageCrop 0.1 StatusImageCrop.qml
|
||||||
|
StatusImageSelector 0.1 StatusImageSelector.qml
|
||||||
StatusInput 0.1 StatusInput.qml
|
StatusInput 0.1 StatusInput.qml
|
||||||
StatusAmountInput 0.1 StatusAmountInput.qml
|
StatusItemDelegate 0.1 StatusItemDelegate.qml
|
||||||
|
StatusItemPicker 0.1 StatusItemPicker.qml
|
||||||
|
StatusLabeledSlider 0.1 StatusLabeledSlider.qml
|
||||||
|
StatusLinkText 0.1 StatusLinkText.qml
|
||||||
|
StatusNavBarTabButton 0.1 StatusNavBarTabButton.qml
|
||||||
|
StatusNavigationButton 0.1 StatusNavigationButton.qml
|
||||||
|
StatusPasswordInput 0.1 StatusPasswordInput.qml
|
||||||
|
StatusPasswordStrengthIndicator 0.1 StatusPasswordStrengthIndicator.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
|
||||||
StatusPasswordStrengthIndicator 0.1 StatusPasswordStrengthIndicator.qml
|
StatusRadioButton 0.1 StatusRadioButton.qml
|
||||||
StatusSwitchTabButton 0.1 StatusSwitchTabButton.qml
|
StatusRoundButton 0.1 StatusRoundButton.qml
|
||||||
StatusSwitchTabBar 0.1 StatusSwitchTabBar.qml
|
StatusScrollBar 0.1 StatusScrollBar.qml
|
||||||
|
StatusSeedPhraseInput 0.1 StatusSeedPhraseInput.qml
|
||||||
|
StatusSelect 0.1 StatusSelect.qml
|
||||||
StatusSelectableText 0.1 StatusSelectableText.qml
|
StatusSelectableText 0.1 StatusSelectableText.qml
|
||||||
|
StatusSlider 0.1 StatusSlider.qml
|
||||||
|
StatusSwitch 0.1 StatusSwitch.qml
|
||||||
|
StatusSwitchTabBar 0.1 StatusSwitchTabBar.qml
|
||||||
|
StatusSwitchTabButton 0.1 StatusSwitchTabButton.qml
|
||||||
StatusTabBar 0.1 StatusTabBar.qml
|
StatusTabBar 0.1 StatusTabBar.qml
|
||||||
|
StatusTabBarIconButton 0.1 StatusTabBarIconButton.qml
|
||||||
StatusTabButton 0.1 StatusTabButton.qml
|
StatusTabButton 0.1 StatusTabButton.qml
|
||||||
StatusTagItem 0.1 StatusTagItem.qml
|
StatusTagItem 0.1 StatusTagItem.qml
|
||||||
StatusTokenInlineSelector 0.1 StatusTokenInlineSelector.qml
|
|
||||||
StatusWalletColorButton 0.1 StatusWalletColorButton.qml
|
|
||||||
StatusWalletColorSelect 0.1 StatusWalletColorSelect.qml
|
|
||||||
StatusColorSelectorGrid 0.1 StatusColorSelectorGrid.qml
|
|
||||||
StatusSeedPhraseInput 0.1 StatusSeedPhraseInput.qml
|
|
||||||
StatusImageCrop 0.1 StatusImageCrop.qml
|
|
||||||
StatusActivityCenterButton 0.1 StatusActivityCenterButton.qml
|
|
||||||
StatusDropdown 0.1 StatusDropdown.qml
|
|
||||||
StatusIconTextButton 0.1 StatusIconTextButton.qml
|
|
||||||
StatusScrollBar 0.1 StatusScrollBar.qml
|
|
||||||
StatusComboBox 0.1 StatusComboBox.qml
|
|
||||||
StatusItemDelegate 0.1 StatusItemDelegate.qml
|
|
||||||
StatusTextArea 0.1 StatusTextArea.qml
|
StatusTextArea 0.1 StatusTextArea.qml
|
||||||
StatusTextField 0.1 StatusTextField.qml
|
StatusTextField 0.1 StatusTextField.qml
|
||||||
StatusBackButton 0.1 StatusBackButton.qml
|
|
||||||
StatusPasswordInput 0.1 StatusPasswordInput.qml
|
|
||||||
StatusTextWithLoadingState 0.1 StatusTextWithLoadingState.qml
|
StatusTextWithLoadingState 0.1 StatusTextWithLoadingState.qml
|
||||||
StatusLinkText 0.1 StatusLinkText.qml
|
StatusTokenInlineSelector 0.1 StatusTokenInlineSelector.qml
|
||||||
StatusImageSelector 0.1 StatusImageSelector.qml
|
StatusToolTip 0.1 StatusToolTip.qml
|
||||||
StatusColorRadioButton 0.1 StatusColorRadioButton.qml
|
StatusWalletColorButton 0.1 StatusWalletColorButton.qml
|
||||||
StatusBlockProgressBar 0.1 StatusBlockProgressBar.qml
|
StatusWalletColorSelect 0.1 StatusWalletColorSelect.qml
|
||||||
StatusWarningBox 0.1 StatusWarningBox.qml
|
StatusWarningBox 0.1 StatusWarningBox.qml
|
||||||
StatusIconSwitch 0.1 StatusIconSwitch.qml
|
|
||||||
StatusCircularProgressBar 0.1 StatusCircularProgressBar.qml
|
|
||||||
|
@ -72,10 +72,10 @@
|
|||||||
<file>StatusQ/Components/private/chart/ChartCanvas.qml</file>
|
<file>StatusQ/Components/private/chart/ChartCanvas.qml</file>
|
||||||
<file>StatusQ/Components/private/chart/Library/Animator.qml</file>
|
<file>StatusQ/Components/private/chart/Library/Animator.qml</file>
|
||||||
<file>StatusQ/Components/private/chart/Library/Chart.bundle.js</file>
|
<file>StatusQ/Components/private/chart/Library/Chart.bundle.js</file>
|
||||||
<file>StatusQ/Components/private/chart/Library/chartjs-plugin-crosshair.js</file>
|
|
||||||
<file>StatusQ/Components/private/chart/Library/chartjs-plugin-datalabels.js</file>
|
|
||||||
<file>StatusQ/Components/private/chart/Library/Library.js</file>
|
<file>StatusQ/Components/private/chart/Library/Library.js</file>
|
||||||
<file>StatusQ/Components/private/chart/Library/Polyfills.js</file>
|
<file>StatusQ/Components/private/chart/Library/Polyfills.js</file>
|
||||||
|
<file>StatusQ/Components/private/chart/Library/chartjs-plugin-crosshair.js</file>
|
||||||
|
<file>StatusQ/Components/private/chart/Library/chartjs-plugin-datalabels.js</file>
|
||||||
<file>StatusQ/Components/private/qmldir</file>
|
<file>StatusQ/Components/private/qmldir</file>
|
||||||
<file>StatusQ/Components/private/qwebchannel/helpers.js</file>
|
<file>StatusQ/Components/private/qwebchannel/helpers.js</file>
|
||||||
<file>StatusQ/Components/private/qwebchannel/qwebchannel.js</file>
|
<file>StatusQ/Components/private/qwebchannel/qwebchannel.js</file>
|
||||||
@ -90,8 +90,8 @@
|
|||||||
<file>StatusQ/Components/private/statusMessage/StatusSticker.qml</file>
|
<file>StatusQ/Components/private/statusMessage/StatusSticker.qml</file>
|
||||||
<file>StatusQ/Components/private/statusMessage/StatusTextMessage.qml</file>
|
<file>StatusQ/Components/private/statusMessage/StatusTextMessage.qml</file>
|
||||||
<file>StatusQ/Components/qmldir</file>
|
<file>StatusQ/Components/qmldir</file>
|
||||||
<file>StatusQ/Controls/StatusAccountSelector.qml</file>
|
|
||||||
<file>StatusQ/Controls/StatusActivityCenterButton.qml</file>
|
<file>StatusQ/Controls/StatusActivityCenterButton.qml</file>
|
||||||
|
<file>StatusQ/Controls/StatusAmountInput.qml</file>
|
||||||
<file>StatusQ/Controls/StatusBackButton.qml</file>
|
<file>StatusQ/Controls/StatusBackButton.qml</file>
|
||||||
<file>StatusQ/Controls/StatusBanner.qml</file>
|
<file>StatusQ/Controls/StatusBanner.qml</file>
|
||||||
<file>StatusQ/Controls/StatusBaseButton.qml</file>
|
<file>StatusQ/Controls/StatusBaseButton.qml</file>
|
||||||
@ -120,7 +120,6 @@
|
|||||||
<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>
|
||||||
@ -184,8 +183,8 @@
|
|||||||
<file>StatusQ/Core/StatusModalHeaderSettings.qml</file>
|
<file>StatusQ/Core/StatusModalHeaderSettings.qml</file>
|
||||||
<file>StatusQ/Core/StatusProfileImageSettings.qml</file>
|
<file>StatusQ/Core/StatusProfileImageSettings.qml</file>
|
||||||
<file>StatusQ/Core/StatusRollArea.qml</file>
|
<file>StatusQ/Core/StatusRollArea.qml</file>
|
||||||
<file>StatusQ/Core/StatusSharedUpdateTimer.qml</file>
|
|
||||||
<file>StatusQ/Core/StatusScrollView.qml</file>
|
<file>StatusQ/Core/StatusScrollView.qml</file>
|
||||||
|
<file>StatusQ/Core/StatusSharedUpdateTimer.qml</file>
|
||||||
<file>StatusQ/Core/StatusTooltipSettings.qml</file>
|
<file>StatusQ/Core/StatusTooltipSettings.qml</file>
|
||||||
<file>StatusQ/Core/Theme/StatusColors.qml</file>
|
<file>StatusQ/Core/Theme/StatusColors.qml</file>
|
||||||
<file>StatusQ/Core/Theme/StatusDarkTheme.qml</file>
|
<file>StatusQ/Core/Theme/StatusDarkTheme.qml</file>
|
||||||
@ -254,7 +253,7 @@
|
|||||||
<file>StatusQ/Popups/statusModal/StatusImageWithTitle.qml</file>
|
<file>StatusQ/Popups/statusModal/StatusImageWithTitle.qml</file>
|
||||||
<file>StatusQ/Popups/statusModal/StatusModalFooter.qml</file>
|
<file>StatusQ/Popups/statusModal/StatusModalFooter.qml</file>
|
||||||
<file>StatusQ/Popups/statusModal/StatusModalHeader.qml</file>
|
<file>StatusQ/Popups/statusModal/StatusModalHeader.qml</file>
|
||||||
<file>StatusQ/Validators/qmldir</file>
|
|
||||||
<file>StatusQ/Validators/AmountValidator.qml</file>
|
<file>StatusQ/Validators/AmountValidator.qml</file>
|
||||||
|
<file>StatusQ/Validators/qmldir</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
import QtQuick.Layouts 1.13
|
|
||||||
import QtGraphicalEffects 1.13
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
import "."
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var contactsStore
|
|
||||||
|
|
||||||
property string validationError: "Error"
|
|
||||||
property string ensAsyncValidationError: qsTr("ENS Username not found")
|
|
||||||
property alias input: contactFieldAndList.chatKey
|
|
||||||
property string selectedAddress
|
|
||||||
property bool isValid: false
|
|
||||||
property alias isPending: contactFieldAndList.loading
|
|
||||||
property bool isResolvedAddress: false
|
|
||||||
property int parentWidth
|
|
||||||
property bool addContactEnabled: true
|
|
||||||
property alias wrongInputValidationError: contactFieldAndList.wrongInputValidationError
|
|
||||||
property alias ownAddressError: contactFieldAndList.ownAddressError
|
|
||||||
|
|
||||||
implicitHeight: contactFieldAndList.chatKey.height
|
|
||||||
|
|
||||||
onSelectedAddressChanged: validate()
|
|
||||||
|
|
||||||
function resetInternal() {
|
|
||||||
selectedAddress = ""
|
|
||||||
contactFieldAndList.chatKey.resetInternal()
|
|
||||||
metrics.text = ""
|
|
||||||
isValid = false
|
|
||||||
isPending = false
|
|
||||||
isResolvedAddress = false
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate() {
|
|
||||||
let isValidEns = Utils.isValidEns(input.text)
|
|
||||||
let isValidAddress = Utils.isValidAddress(selectedAddress)
|
|
||||||
let isValid = (isValidEns && !isResolvedAddress) || isPending || isValidAddress
|
|
||||||
contactFieldAndList.chatKey.validationError = ""
|
|
||||||
if (!isValid && input.text !== "") {
|
|
||||||
contactFieldAndList.chatKey.validationError = isResolvedAddress ? ensAsyncValidationError : validationError
|
|
||||||
}
|
|
||||||
root.isValid = isValid
|
|
||||||
return isValid
|
|
||||||
}
|
|
||||||
|
|
||||||
ContactsListAndSearch {
|
|
||||||
id: contactFieldAndList
|
|
||||||
width: parent.width
|
|
||||||
showContactList: false
|
|
||||||
addContactEnabled: root.addContactEnabled
|
|
||||||
|
|
||||||
contactsStore: root.contactsStore
|
|
||||||
|
|
||||||
onUserClicked: function (isContact, pubKey, ensName, address) {
|
|
||||||
chatKey.text = address
|
|
||||||
}
|
|
||||||
searchResultsWidth: parentWidth
|
|
||||||
chatKey.customHeight: 56
|
|
||||||
chatKey.onFocusChanged: {
|
|
||||||
root.validate()
|
|
||||||
if (chatKey.text !== "" && Utils.isValidAddress(metrics.text)) {
|
|
||||||
if (chatKey.focus) {
|
|
||||||
chatKey.text = metrics.text
|
|
||||||
} else {
|
|
||||||
chatKey.text = metrics.elidedText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chatKey.onTextChanged: {
|
|
||||||
metrics.text = chatKey.text
|
|
||||||
if (Utils.isValidAddress(chatKey.text)) {
|
|
||||||
root.selectedAddress = chatKey.text
|
|
||||||
} else {
|
|
||||||
root.selectedAddress = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TextMetrics {
|
|
||||||
id: metrics
|
|
||||||
elideWidth: 97
|
|
||||||
elide: Text.ElideMiddle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*##^##
|
|
||||||
Designer {
|
|
||||||
D{i:0;autoSize:true;height:480;width:640}
|
|
||||||
}
|
|
||||||
##^##*/
|
|
@ -1,202 +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.Components 0.1
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
|
|
||||||
import "../views"
|
|
||||||
import "../panels"
|
|
||||||
import "./"
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
property var contactsStore
|
|
||||||
property var selectedContact
|
|
||||||
property int dropdownWidth: width
|
|
||||||
property string validationError: qsTr("Please select a contact")
|
|
||||||
property bool isValid: false
|
|
||||||
property alias isPending: ensResolver.isPending
|
|
||||||
|
|
||||||
property bool readOnly: false
|
|
||||||
property bool isResolvedAddress: false
|
|
||||||
property string selectAContact: qsTr("Select a contact")
|
|
||||||
property string noEnsAddressMessage: qsTr("Contact does not have an ENS address. Please send a transaction in chat.")
|
|
||||||
|
|
||||||
function resolveEns() {
|
|
||||||
if (selectedContact.ensVerified) {
|
|
||||||
root.isResolvedAddress = false
|
|
||||||
ensResolver.resolveEns(selectedContact.alias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitHeight: comboBox.implicitHeight
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (root.readOnly) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root.selectedContact = { alias: selectAContact }
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelectedContactChanged: validate()
|
|
||||||
|
|
||||||
function validate() {
|
|
||||||
if (!selectedContact) {
|
|
||||||
return root.isValid
|
|
||||||
}
|
|
||||||
let isValidAddress = Utils.isValidAddress(selectedContact.address)
|
|
||||||
let isDefaultValue = selectedContact.alias === selectAContact
|
|
||||||
let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress
|
|
||||||
comboBox.validationError = ""
|
|
||||||
if (!isValid && !isDefaultValue &&
|
|
||||||
(
|
|
||||||
!selectedContact.ensVerified ||
|
|
||||||
(selectedContact.ensVerified && isResolvedAddress)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
comboBox.validationError = !selectedContact.ensVerified ? noEnsAddressMessage : validationError
|
|
||||||
}
|
|
||||||
root.isValid = isValid
|
|
||||||
return isValid
|
|
||||||
}
|
|
||||||
|
|
||||||
Input {
|
|
||||||
id: inpReadOnly
|
|
||||||
visible: root.readOnly
|
|
||||||
width: parent.width
|
|
||||||
text: (root.selectedContact && root.selectedContact.alias) ? root.selectedContact.alias : qsTr("No contact selected")
|
|
||||||
textField.leftPadding: 14
|
|
||||||
textField.topPadding: 18
|
|
||||||
textField.bottomPadding: 18
|
|
||||||
textField.verticalAlignment: TextField.AlignVCenter
|
|
||||||
textField.font.pixelSize: 15
|
|
||||||
textField.color: Style.current.secondaryText
|
|
||||||
readOnly: true
|
|
||||||
validationErrorAlignment: TextEdit.AlignRight
|
|
||||||
validationErrorTopMargin: 8
|
|
||||||
customHeight: 56
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusComboBox {
|
|
||||||
id: comboBox
|
|
||||||
label: ""
|
|
||||||
model: root.contactsStore.myContactsModel
|
|
||||||
width: parent.width
|
|
||||||
visible: !root.readOnly
|
|
||||||
|
|
||||||
control.popup.width: dropdownWidth
|
|
||||||
control.padding: 14
|
|
||||||
|
|
||||||
enabled: control.count > 0
|
|
||||||
|
|
||||||
contentItem: RowLayout {
|
|
||||||
spacing: 4
|
|
||||||
|
|
||||||
StatusSmartIdenticon {
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
asset.width: (!!selectedContact && !!selectedContact.displayIcon) ? 32 : 0
|
|
||||||
asset.height: 32
|
|
||||||
asset.isImage: true
|
|
||||||
asset.name: (!!selectedContact && !!selectedContact.displayIcon) ? selectedContact.displayIcon : ""
|
|
||||||
active: !!selectedContact && !!selectedContact.thumbnailImage
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
id: selectedTextField
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
visible: comboBox.control.count > 0
|
|
||||||
text: !!selectedContact ? selectedContact.alias : ""
|
|
||||||
font.pixelSize: 15
|
|
||||||
height: 22
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
visible: comboBox.control.count == 0
|
|
||||||
text: qsTr("You don’t have any contacts yet")
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: StatusItemDelegate {
|
|
||||||
id: itemContainer
|
|
||||||
|
|
||||||
readonly property var currentContact: Utils.getContactDetailsAsJson(pubKey)
|
|
||||||
|
|
||||||
highlighted: index === comboBox.control.highlightedIndex
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
root.selectedContact = itemContainer.currentContact
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: RowLayout {
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
StatusSmartIdenticon {
|
|
||||||
asset.isImage: true
|
|
||||||
asset.name: currentContact.thumbnailImage
|
|
||||||
}
|
|
||||||
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
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
text: currentContact.name + " • "
|
|
||||||
visible: currentContact.ensVerified
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
font.pixelSize: 12
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
Layout.maximumWidth: 85
|
|
||||||
text: currentContact.publicKey
|
|
||||||
elide: Text.ElideMiddle
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
font.pixelSize: 12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
EnsResolver {
|
|
||||||
id: ensResolver
|
|
||||||
anchors.top: comboBox.bottom
|
|
||||||
anchors.right: comboBox.right
|
|
||||||
anchors.topMargin: Style.current.halfPadding
|
|
||||||
debounceDelay: 0
|
|
||||||
onResolved: {
|
|
||||||
root.isResolvedAddress = true
|
|
||||||
var selectedContact = root.selectedContact
|
|
||||||
selectedContact.address = resolvedAddress
|
|
||||||
root.selectedContact = selectedContact
|
|
||||||
}
|
|
||||||
onIsPendingChanged: {
|
|
||||||
if (isPending) {
|
|
||||||
root.selectedContact.address = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,247 +0,0 @@
|
|||||||
import QtQuick 2.14
|
|
||||||
import QtQuick.Layouts 1.4
|
|
||||||
import QtGraphicalEffects 1.14
|
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
|
||||||
import StatusQ.Core.Backpressure 0.1
|
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
import shared.stores 1.0
|
|
||||||
|
|
||||||
import "../"
|
|
||||||
import "../views"
|
|
||||||
import "../panels"
|
|
||||||
import "../status"
|
|
||||||
import "."
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var rootStore
|
|
||||||
property var contactsStore
|
|
||||||
property var community
|
|
||||||
|
|
||||||
property string validationError: ""
|
|
||||||
property string successMessage: ""
|
|
||||||
property alias chatKey: chatKey
|
|
||||||
property alias existingContacts: existingContacts
|
|
||||||
property alias noContactsRect: noContactsRect
|
|
||||||
property string pubKey : ""
|
|
||||||
property int searchResultsWidth : 0
|
|
||||||
property alias loading : searchResults.loading
|
|
||||||
property string ensUsername : ""
|
|
||||||
property bool showCheckbox: false
|
|
||||||
property bool showContactList: true
|
|
||||||
property bool showSearch: true
|
|
||||||
property var pubKeys: ([])
|
|
||||||
property bool hideCommunityMembers: false
|
|
||||||
property bool addContactEnabled: true
|
|
||||||
property string wrongInputValidationError: qsTr("Enter a valid chat key or ENS username");
|
|
||||||
property string ownAddressError: qsTr("Can't chat with yourself");
|
|
||||||
|
|
||||||
readonly property var resolveENS: Backpressure.debounce(root, 500, function (ensName) {
|
|
||||||
noContactsRect.visible = false
|
|
||||||
searchResults.loading = true
|
|
||||||
searchResults.showProfileNotFoundMessage = false
|
|
||||||
mainModule.resolveENS(ensName, "")
|
|
||||||
});
|
|
||||||
|
|
||||||
function validate() {
|
|
||||||
if (!Utils.isChatKey(chatKey.text) && !Utils.isValidETHNamePrefix(chatKey.text)) {
|
|
||||||
root.validationError = wrongInputValidationError
|
|
||||||
pubKey = ""
|
|
||||||
ensUsername = "";
|
|
||||||
} else if (RootStore.userProfileInst.pubKey === chatKey.text) {
|
|
||||||
root.validationError = ownAddressError;
|
|
||||||
} else {
|
|
||||||
root.validationError = "";
|
|
||||||
}
|
|
||||||
return root.validationError === "";
|
|
||||||
}
|
|
||||||
|
|
||||||
signal userClicked(string pubKey, bool isAddedContact, string name, string address)
|
|
||||||
|
|
||||||
implicitWidth: column.implicitWidth
|
|
||||||
implicitHeight: column.implicitHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: column
|
|
||||||
anchors.fill: parent
|
|
||||||
spacing: Style.current.smallPadding
|
|
||||||
|
|
||||||
Input {
|
|
||||||
id: chatKey
|
|
||||||
|
|
||||||
property bool hasValidSearchResult: false
|
|
||||||
|
|
||||||
placeholderText: qsTr("Enter ENS username or chat key")
|
|
||||||
visible: showSearch
|
|
||||||
textField.anchors.rightMargin: clearBtn.width + Style.current.padding + 2
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
||||||
Keys.onReleased: {
|
|
||||||
successMessage = "";
|
|
||||||
searchResults.pubKey = "";
|
|
||||||
root.validationError = "";
|
|
||||||
searchResults.showProfileNotFoundMessage = false;
|
|
||||||
if (chatKey.text !== "") {
|
|
||||||
if (!validate()) {
|
|
||||||
noContactsRect.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chatKey.text = chatKey.text.trim();
|
|
||||||
|
|
||||||
if (Utils.isChatKey(chatKey.text)) {
|
|
||||||
pubKey = chatKey.text;
|
|
||||||
let contactDetails = Utils.getContactDetailsAsJson(pubKey);
|
|
||||||
if (!contactDetails.isContact) {
|
|
||||||
searchResults.username = contactDetails.alias;
|
|
||||||
searchResults.userAlias = Utils.compactAddress(pubKey, 4);
|
|
||||||
searchResults.pubKey = pubKey;
|
|
||||||
}
|
|
||||||
noContactsRect.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chatKey.hasValidSearchResult = false
|
|
||||||
Qt.callLater(resolveENS, chatKey.text);
|
|
||||||
} else {
|
|
||||||
root.validationError = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: mainModule
|
|
||||||
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
|
|
||||||
chatKey.hasValidSearchResult = false
|
|
||||||
if (chatKey.text == "") {
|
|
||||||
ensUsername.text = "";
|
|
||||||
pubKey = "";
|
|
||||||
} else if(resolvedPubKey == ""){
|
|
||||||
ensUsername.text = "";
|
|
||||||
searchResults.pubKey = pubKey = "";
|
|
||||||
searchResults.address = "";
|
|
||||||
searchResults.showProfileNotFoundMessage = root.showContactList
|
|
||||||
} else {
|
|
||||||
if (userProfile.pubKey === resolvedPubKey) {
|
|
||||||
root.validationError = ownAddressError;
|
|
||||||
} else {
|
|
||||||
chatKey.hasValidSearchResult = true
|
|
||||||
searchResults.username = chatKey.text.trim()
|
|
||||||
let userAlias = globalUtils.generateAlias(resolvedPubKey)
|
|
||||||
userAlias = userAlias.length > 20 ? userAlias.substring(0, 19) + "..." : userAlias
|
|
||||||
searchResults.userAlias = userAlias + " • " + Utils.compactAddress(resolvedPubKey, 4)
|
|
||||||
searchResults.pubKey = pubKey = resolvedPubKey;
|
|
||||||
searchResults.address = resolvedAddress;
|
|
||||||
}
|
|
||||||
searchResults.showProfileNotFoundMessage = false
|
|
||||||
}
|
|
||||||
searchResults.loading = false;
|
|
||||||
noContactsRect.visible = pubKey === "" &&
|
|
||||||
ensUsername.text === "" &&
|
|
||||||
root.contactsStore.myContactsModel.count === 0 &&
|
|
||||||
!profileNotFoundMessage.visible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusFlatRoundButton {
|
|
||||||
id: clearBtn
|
|
||||||
width: 20
|
|
||||||
height: 20
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.current.padding
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
icon.name: "clear"
|
|
||||||
visible: chatKey.text !== "" && !chatKey.readOnly
|
|
||||||
icon.width: 20
|
|
||||||
icon.height: 20
|
|
||||||
type: StatusFlatRoundButton.Type.Tertiary
|
|
||||||
color: "transparent"
|
|
||||||
onClicked: {
|
|
||||||
chatKey.text = "";
|
|
||||||
chatKey.forceActiveFocus(Qt.MouseFocusReason);
|
|
||||||
searchResults.showProfileNotFoundMessage = false;
|
|
||||||
searchResults.pubKey = pubKey = "";
|
|
||||||
noContactsRect.visible = false;
|
|
||||||
searchResults.loading = false;
|
|
||||||
root.validationError = "";
|
|
||||||
chatKey.hasValidSearchResult = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: message
|
|
||||||
text: root.validationError || successMessage
|
|
||||||
visible: root.validationError !== "" || successMessage !== ""
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: !!root.validationError ? Style.current.danger : Style.current.success
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
Layout.preferredHeight: visible ? contentHeight : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
ExistingContacts {
|
|
||||||
id: existingContacts
|
|
||||||
|
|
||||||
rootStore: root.rootStore
|
|
||||||
contactsStore: root.contactsStore
|
|
||||||
communityId: root.community.id
|
|
||||||
|
|
||||||
visible: showContactList
|
|
||||||
hideCommunityMembers: root.hideCommunityMembers
|
|
||||||
showCheckbox: root.showCheckbox
|
|
||||||
filterText: chatKey.text
|
|
||||||
pubKeys: root.pubKeys
|
|
||||||
onContactClicked: function (contact) {
|
|
||||||
if (!contact || typeof contact === "string") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const index = root.pubKeys.indexOf(contact.pubKey)
|
|
||||||
const pubKeysCopy = Object.assign([], root.pubKeys)
|
|
||||||
if (index === -1) {
|
|
||||||
pubKeysCopy.push(contact.pubKey)
|
|
||||||
} else {
|
|
||||||
pubKeysCopy.splice(index, 1)
|
|
||||||
}
|
|
||||||
root.pubKeys = pubKeysCopy
|
|
||||||
|
|
||||||
chatKey.hasValidSearchResult = false
|
|
||||||
userClicked(contact.pubKey, contact.isContact, contact.alias, contact.address)
|
|
||||||
}
|
|
||||||
expanded: !searchResults.loading && pubKey === "" && !searchResults.showProfileNotFoundMessage
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchResults {
|
|
||||||
id: searchResults
|
|
||||||
hasExistingContacts: existingContacts.visible
|
|
||||||
loading: false
|
|
||||||
addContactEnabled: root.addContactEnabled
|
|
||||||
onResultClicked: {
|
|
||||||
chatKey.hasValidSearchResult = false
|
|
||||||
userClicked(pubKey, isAddedContact, username, searchResults.address)
|
|
||||||
if (!validate()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onAddToContactsButtonClicked: {
|
|
||||||
root.contactsStore.addContact(pubKey)
|
|
||||||
}
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.rightMargin: Style.current.padding
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NoFriendsRectangle {
|
|
||||||
id: noContactsRect
|
|
||||||
visible: showContactList && existingContacts.count === 0
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,262 +0,0 @@
|
|||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
import QtQuick.Layouts 1.13
|
|
||||||
import QtGraphicalEffects 1.13
|
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
|
|
||||||
import "."
|
|
||||||
import "../panels"
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var contactsStore
|
|
||||||
|
|
||||||
property var accounts
|
|
||||||
property int inputWidth: 272
|
|
||||||
property int sourceSelectWidth: 150
|
|
||||||
property alias label: txtLabel.text
|
|
||||||
property alias labelFont: txtLabel.font
|
|
||||||
property alias input: inpAddress.input
|
|
||||||
// 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
|
|
||||||
readonly property string addressValidationError: qsTr("Invalid ethereum address")
|
|
||||||
property alias wrongInputValidationError: inpAddress.wrongInputValidationError
|
|
||||||
property alias ownAddressError: inpAddress.ownAddressError
|
|
||||||
property bool isValid: false
|
|
||||||
property bool isSelectorVisible: true
|
|
||||||
property bool addContactEnabled: true
|
|
||||||
property bool isPending: {
|
|
||||||
switch (selAddressSource.currentValue) {
|
|
||||||
case RecipientSelector.Type.Address:
|
|
||||||
return inpAddress.isPending
|
|
||||||
case RecipientSelector.Type.Contact:
|
|
||||||
return selContact.isPending
|
|
||||||
case RecipientSelector.Type.Account:
|
|
||||||
return false // AccountSelector is never pending
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property var sources: [
|
|
||||||
{ text: qsTr("Address"), value: RecipientSelector.Type.Address, visible: true },
|
|
||||||
{ text: qsTr("My account"), value: RecipientSelector.Type.Account, visible: true },
|
|
||||||
{ text: qsTr("Contact"), value: RecipientSelector.Type.Contact, visible: true }
|
|
||||||
]
|
|
||||||
|
|
||||||
property var selectedType: RecipientSelector.Type.Address
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
Address,
|
|
||||||
Contact,
|
|
||||||
Account
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate() {
|
|
||||||
switch (selAddressSource.currentValue) {
|
|
||||||
case RecipientSelector.Type.Address:
|
|
||||||
root.isValid = inpAddress.isValid
|
|
||||||
break
|
|
||||||
case RecipientSelector.Type.Contact:
|
|
||||||
root.isValid = selContact.isValid
|
|
||||||
break
|
|
||||||
case RecipientSelector.Type.Account:
|
|
||||||
root.isValid = selAccount.isValid
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return root.isValid
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateAddressComboBox() {
|
|
||||||
if (selectedType !== undefined) {
|
|
||||||
selAddressSource.control.currentIndex = selAddressSource.control.indexOfValue(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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelectedTypeChanged: {
|
|
||||||
updateAddressComboBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
updateAddressComboBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitHeight: inpAddress.height + txtLabel.height
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: txtLabel
|
|
||||||
visible: label !== ""
|
|
||||||
text: qsTr("Recipient")
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.family: Style.current.baseFont.name
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Style.current.textColor
|
|
||||||
height: 18
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: txtAddlInfo
|
|
||||||
visible: text !== ""
|
|
||||||
text: ""
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.family: Style.current.baseFont.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
|
|
||||||
|
|
||||||
contactsStore: root.contactsStore
|
|
||||||
|
|
||||||
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
|
|
||||||
addContactEnabled: root.addContactEnabled
|
|
||||||
onSelectedAddressChanged: {
|
|
||||||
if (selAddressSource.currentValue !== RecipientSelector.Type.Address)
|
|
||||||
return
|
|
||||||
root.selectedRecipient = { address: selectedAddress, type: RecipientSelector.Type.Address }
|
|
||||||
}
|
|
||||||
onIsValidChanged: root.validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
ContactSelector {
|
|
||||||
id: selContact
|
|
||||||
contactsStore: root.contactsStore
|
|
||||||
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 || !selectedContact.address || selAddressSource.currentValue !== RecipientSelector.Type.Contact)
|
|
||||||
return;
|
|
||||||
const { address, name, alias, pubKey, icon, isContact, ensVerified } = selectedContact
|
|
||||||
root.selectedRecipient = { address, name, alias, pubKey, icon, isContact, ensVerified, type: RecipientSelector.Type.Contact }
|
|
||||||
}
|
|
||||||
onIsValidChanged: root.validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusAccountSelector {
|
|
||||||
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.currentValue !== RecipientSelector.Type.Account)
|
|
||||||
return;
|
|
||||||
const { address, name, color, assets, fiatBalance } = selectedAccount
|
|
||||||
root.selectedRecipient = { address, name, color, assets, fiatBalance, type: RecipientSelector.Type.Account }
|
|
||||||
}
|
|
||||||
onIsValidChanged: root.validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusComboBox {
|
|
||||||
id: selAddressSource
|
|
||||||
visible: isSelectorVisible && !root.readOnly
|
|
||||||
model: root.sources.filter(source => source.visible)
|
|
||||||
width: sourceSelectWidth
|
|
||||||
Layout.preferredWidth: root.sourceSelectWidth
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
|
|
||||||
control.textRole: "text"
|
|
||||||
control.valueRole: "value"
|
|
||||||
|
|
||||||
onCurrentValueChanged: {
|
|
||||||
if (root.readOnly) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let address, name
|
|
||||||
switch (currentValue) {
|
|
||||||
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, ensVerified } = selContact.selectedContact
|
|
||||||
address = selContact.selectedContact.address
|
|
||||||
name = selContact.selectedContact.name
|
|
||||||
root.selectedRecipient = { address, name, alias, isContact, 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 { color, assets, fiatBalance } = selAccount.selectedAccount
|
|
||||||
address = selAccount.selectedAccount.address
|
|
||||||
name = selAccount.selectedAccount.name
|
|
||||||
root.selectedRecipient = { address, name, color, assets, fiatBalance, type: RecipientSelector.Type.Account }
|
|
||||||
if (root.selectedType !== RecipientSelector.Type.Account) root.selectedType = RecipientSelector.Type.Account
|
|
||||||
root.isValid = selAccount.isValid
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -11,7 +11,6 @@ Item {
|
|||||||
|
|
||||||
property var acc
|
property var acc
|
||||||
property string fromAddress
|
property string fromAddress
|
||||||
property var selectedRecipient
|
|
||||||
property var selectedAsset
|
property var selectedAsset
|
||||||
property string selectedAmount
|
property string selectedAmount
|
||||||
property string selectedFiatAmount
|
property string selectedFiatAmount
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
AccountSelector 1.0 AccountSelector.qml
|
AccountSelector 1.0 AccountSelector.qml
|
||||||
AccountSelectorHeader 1.0 AccountSelectorHeader.qml
|
AccountSelectorHeader 1.0 AccountSelectorHeader.qml
|
||||||
AddressInput 1.0 AddressInput.qml
|
|
||||||
AmountInput 1.0 AmountInput.qml
|
AmountInput 1.0 AmountInput.qml
|
||||||
AssetAndAmountInput 1.0 AssetAndAmountInput.qml
|
AssetAndAmountInput 1.0 AssetAndAmountInput.qml
|
||||||
AssetDelegate 1.0 AssetDelegate.qml
|
AssetDelegate 1.0 AssetDelegate.qml
|
||||||
AssetsDetailsHeader 1.0 AssetsDetailsHeader.qml
|
AssetsDetailsHeader 1.0 AssetsDetailsHeader.qml
|
||||||
ContactSelector 1.0 ContactSelector.qml
|
AssetsSectionDelegate 1.0 AssetsSectionDelegate.qml
|
||||||
ContactsListAndSearch 1.0 ContactsListAndSearch.qml
|
|
||||||
CopyButton 1.0 CopyButton.qml
|
CopyButton 1.0 CopyButton.qml
|
||||||
CopyButtonWithCircle 1.0 CopyButtonWithCircle.qml
|
CopyButtonWithCircle 1.0 CopyButtonWithCircle.qml
|
||||||
CopyToClipBoardButton 1.0 CopyToClipBoardButton.qml
|
CopyToClipBoardButton 1.0 CopyToClipBoardButton.qml
|
||||||
|
CountdownPill 1.0 CountdownPill.qml
|
||||||
CurrencyAmountInput 1.0 CurrencyAmountInput.qml
|
CurrencyAmountInput 1.0 CurrencyAmountInput.qml
|
||||||
|
DecoratedListItem 1.0 DecoratedListItem.qml
|
||||||
EmojiHash 1.0 EmojiHash.qml
|
EmojiHash 1.0 EmojiHash.qml
|
||||||
EmptyShapeRectangleFooterListView 1.0 EmptyShapeRectangleFooterListView.qml
|
EmptyShapeRectangleFooterListView 1.0 EmptyShapeRectangleFooterListView.qml
|
||||||
ErrorDetails 1.0 ErrorDetails.qml
|
ErrorDetails 1.0 ErrorDetails.qml
|
||||||
ErrorTag 1.0 ErrorTag.qml
|
ErrorTag 1.0 ErrorTag.qml
|
||||||
|
ExpandableTag 1.0 ExpandableTag.qml
|
||||||
FoldableHeader 1.0 FoldableHeader.qml
|
FoldableHeader 1.0 FoldableHeader.qml
|
||||||
FormGroup 1.0 FormGroup.qml
|
FormGroup 1.0 FormGroup.qml
|
||||||
GetSyncCodeDesktopInstructions 1.0 GetSyncCodeDesktopInstructions.qml
|
GetSyncCodeDesktopInstructions 1.0 GetSyncCodeDesktopInstructions.qml
|
||||||
@ -23,11 +24,13 @@ ImportKeypairInfo 1.0 ImportKeypairInfo.qml
|
|||||||
InformationTag 1.0 InformationTag.qml
|
InformationTag 1.0 InformationTag.qml
|
||||||
InformationTile 1.0 InformationTile.qml
|
InformationTile 1.0 InformationTile.qml
|
||||||
Input 1.0 Input.qml
|
Input 1.0 Input.qml
|
||||||
LoadingTokenDelegate 1.0 LoadingTokenDelegate.qml
|
|
||||||
LinkPreviewDebugView 1.0 LinkPreviewDebugView.qml
|
LinkPreviewDebugView 1.0 LinkPreviewDebugView.qml
|
||||||
|
LoadingTokenDelegate 1.0 LoadingTokenDelegate.qml
|
||||||
|
MockedKeycardReaderStateSelector 1.0 MockedKeycardReaderStateSelector.qml
|
||||||
|
MockedKeycardStateSelector 1.0 MockedKeycardStateSelector.qml
|
||||||
|
Padding 1.0 Padding.qml
|
||||||
ProfilePerspectiveSelector 1.0 ProfilePerspectiveSelector.qml
|
ProfilePerspectiveSelector 1.0 ProfilePerspectiveSelector.qml
|
||||||
RadioButtonSelector 1.0 RadioButtonSelector.qml
|
RadioButtonSelector 1.0 RadioButtonSelector.qml
|
||||||
RecipientSelector 1.0 RecipientSelector.qml
|
|
||||||
SearchBox 1.0 SearchBox.qml
|
SearchBox 1.0 SearchBox.qml
|
||||||
SeedPhraseTextArea 1.0 SeedPhraseTextArea.qml
|
SeedPhraseTextArea 1.0 SeedPhraseTextArea.qml
|
||||||
SendToContractWarning 1.0 SendToContractWarning.qml
|
SendToContractWarning 1.0 SendToContractWarning.qml
|
||||||
@ -48,10 +51,3 @@ TransactionDataTile 1.0 TransactionDataTile.qml
|
|||||||
TransactionDelegate 1.0 TransactionDelegate.qml
|
TransactionDelegate 1.0 TransactionDelegate.qml
|
||||||
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
||||||
WalletAccountListItem 1.0 WalletAccountListItem.qml
|
WalletAccountListItem 1.0 WalletAccountListItem.qml
|
||||||
MockedKeycardReaderStateSelector 1.0 MockedKeycardReaderStateSelector.qml
|
|
||||||
MockedKeycardStateSelector 1.0 MockedKeycardStateSelector.qml
|
|
||||||
AssetsSectionDelegate 1.0 AssetsSectionDelegate.qml
|
|
||||||
ExpandableTag 1.0 ExpandableTag.qml
|
|
||||||
Padding 1.0 Padding.qml
|
|
||||||
DecoratedListItem 1.0 DecoratedListItem.qml
|
|
||||||
CountdownPill 1.0 CountdownPill.qml
|
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
import QtQuick.Layouts 1.13
|
|
||||||
import QtGraphicalEffects 1.13
|
|
||||||
|
|
||||||
import StatusQ.Components 0.1
|
|
||||||
import StatusQ.Core.Backpressure 0.1
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
import shared.stores 1.0
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
property bool isPending: false
|
|
||||||
readonly property string uuid: Utils.uuid()
|
|
||||||
property int debounceDelay: 600
|
|
||||||
|
|
||||||
readonly property var validateAsync: Backpressure.debounce(inpAddress, debounceDelay, function (inputValue) {
|
|
||||||
root.isPending = true
|
|
||||||
var name = inputValue.startsWith("@") ? inputValue.substring(1) : inputValue
|
|
||||||
mainModule.resolveENS(name, uuid)
|
|
||||||
});
|
|
||||||
signal resolved(string resolvedAddress)
|
|
||||||
|
|
||||||
function resolveEns(name) {
|
|
||||||
if (Utils.isValidEns(name)) {
|
|
||||||
root.validateAsync(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
width: 12
|
|
||||||
height: 12
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: loadingIndicator
|
|
||||||
active: root.isPending
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: loadingIndicator
|
|
||||||
StatusLoadingIndicator {
|
|
||||||
width: root.width
|
|
||||||
height: root.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: mainModule
|
|
||||||
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
|
|
||||||
if (uuid !== root.uuid) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root.isPending = false
|
|
||||||
root.resolved(resolvedAddress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,166 +0,0 @@
|
|||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
import QtQuick.Layouts 1.13
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
import shared.stores 1.0
|
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
|
||||||
|
|
||||||
import "../"
|
|
||||||
import "../status"
|
|
||||||
import "../panels"
|
|
||||||
import "./"
|
|
||||||
|
|
||||||
import StatusQ.Components 0.1
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
width: parent.width
|
|
||||||
height: hasExistingContacts ? 64 : 0
|
|
||||||
|
|
||||||
property bool hasExistingContacts: false
|
|
||||||
property bool showProfileNotFoundMessage: false
|
|
||||||
property bool loading: false
|
|
||||||
property string username: ""
|
|
||||||
property string userAlias: ""
|
|
||||||
property string pubKey: ""
|
|
||||||
property string address: ""
|
|
||||||
property bool resultClickable: true
|
|
||||||
property bool addContactEnabled: true
|
|
||||||
property bool isAddedContact: false
|
|
||||||
|
|
||||||
signal resultClicked(string pubKey, bool isAddedContact, string username)
|
|
||||||
signal addToContactsButtonClicked(string pubKey)
|
|
||||||
|
|
||||||
function reset() {
|
|
||||||
hasExistingContacts = false
|
|
||||||
showProfileNotFoundMessage = false
|
|
||||||
username = ""
|
|
||||||
userAlias = ""
|
|
||||||
pubKey = ""
|
|
||||||
isAddedContact = false
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUserAdded() {
|
|
||||||
return root.pubKey != "" ? Utils.getContactDetailsAsJson(root.pubKey).isContactRequestSent : false
|
|
||||||
}
|
|
||||||
|
|
||||||
onPubKeyChanged: {
|
|
||||||
root.isAddedContact = root.isUserAdded()
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: nonContactsLabel
|
|
||||||
text: qsTr("Non contacts")
|
|
||||||
anchors.top: parent.top
|
|
||||||
color: Style.current.secondaryText
|
|
||||||
font.pixelSize: 15
|
|
||||||
visible: root.hasExistingContacts && (root.loading || root.pubKey !== "" || root.showProfileNotFoundMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
active: root.loading
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
sourceComponent: Component {
|
|
||||||
LoadingAnimation {
|
|
||||||
width: 18
|
|
||||||
height: 18
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: foundContact
|
|
||||||
property bool hovered: false
|
|
||||||
anchors.top: nonContactsLabel.visible ? nonContactsLabel.bottom : parent.top
|
|
||||||
color: hovered ? Style.current.backgroundHover : Style.current.background
|
|
||||||
radius: Style.current.radius
|
|
||||||
width: parent.width
|
|
||||||
height: 64
|
|
||||||
visible: root.pubKey !== "" && !root.loading
|
|
||||||
|
|
||||||
StatusSmartIdenticon {
|
|
||||||
id: contactIdenticon
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Style.current.padding
|
|
||||||
name: root.username
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: ensUsername
|
|
||||||
font.pixelSize: 17
|
|
||||||
color: Style.current.textColor
|
|
||||||
anchors.top: contactIdenticon.top
|
|
||||||
anchors.left: contactIdenticon.right
|
|
||||||
anchors.leftMargin: Style.current.padding
|
|
||||||
text: root.username
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: contactAlias
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Style.current.secondaryText
|
|
||||||
anchors.top: ensUsername.bottom
|
|
||||||
anchors.topMargin: 2
|
|
||||||
anchors.left: ensUsername.left
|
|
||||||
text: root.userAlias
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
cursorShape: root.resultClickable ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onEntered: foundContact.hovered = true
|
|
||||||
onExited: foundContact.hovered = false
|
|
||||||
onClicked: {
|
|
||||||
if (root.resultClickable) {
|
|
||||||
root.resultClicked(root.pubKey, root.isAddedContact, root.username)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusFlatRoundButton {
|
|
||||||
id: addContactBtn
|
|
||||||
width: 32
|
|
||||||
height: 32
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.current.padding
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
icon.width: 24
|
|
||||||
icon.height: 24
|
|
||||||
icon.name: "add-contact"
|
|
||||||
backgroundHoverColor: Utils.setColorAlpha(Style.current.buttonHoveredBackgroundColor, 0.2)
|
|
||||||
visible: addContactEnabled && !isAddedContact && !checkIcon.visible
|
|
||||||
onClicked: {
|
|
||||||
root.addToContactsButtonClicked(root.pubKey)
|
|
||||||
mouse.accepted = false
|
|
||||||
}
|
|
||||||
onHoveredChanged: foundContact.hovered = addContactBtn.hovered
|
|
||||||
}
|
|
||||||
|
|
||||||
SVGImage {
|
|
||||||
id: checkIcon
|
|
||||||
source: Style.svg("check-2")
|
|
||||||
width: 19
|
|
||||||
height: 19
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.current.smallPadding * 2
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: foundContact.hovered && isAddedContact
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: profileNotFoundMessage
|
|
||||||
color: Style.current.secondaryText
|
|
||||||
visible: root.showProfileNotFoundMessage
|
|
||||||
font.pixelSize: 15
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: qsTr("No profile found")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -22,7 +22,6 @@ Item {
|
|||||||
property var token
|
property var token
|
||||||
property string tokenAmount
|
property string tokenAmount
|
||||||
property string fiatValue
|
property string fiatValue
|
||||||
property var selectedRecipient
|
|
||||||
property int state: Constants.addressRequested
|
property int state: Constants.addressRequested
|
||||||
|
|
||||||
Separator {
|
Separator {
|
||||||
|
@ -55,15 +55,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property var selectedRecipient: {
|
|
||||||
return {
|
|
||||||
address: transactionParamsObject.address,
|
|
||||||
name: senderDisplayName,
|
|
||||||
type: RecipientSelector.Type.Contact,
|
|
||||||
alias: senderDisplayName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property string tokenAmount: transactionParamsObject.value
|
property string tokenAmount: transactionParamsObject.value
|
||||||
property string tokenSymbol: token.symbol || ""
|
property string tokenSymbol: token.symbol || ""
|
||||||
property string fiatValue: {
|
property string fiatValue: {
|
||||||
@ -211,7 +202,6 @@ Item {
|
|||||||
token: root.token
|
token: root.token
|
||||||
fiatValue: root.fiatValue
|
fiatValue: root.fiatValue
|
||||||
tokenAmount: root.tokenAmount
|
tokenAmount: root.tokenAmount
|
||||||
selectedRecipient: root.selectedRecipient
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +213,6 @@ Item {
|
|||||||
selectedAmount: tokenAmount
|
selectedAmount: tokenAmount
|
||||||
selectedFiatAmount: fiatValue
|
selectedFiatAmount: fiatValue
|
||||||
fromAddress: transactionParamsObject.fromAddress
|
fromAddress: transactionParamsObject.fromAddress
|
||||||
selectedRecipient: root.selectedRecipient
|
|
||||||
onSendTransaction: {
|
onSendTransaction: {
|
||||||
// TODO: https://github.com/status-im/status-desktop/issues/6778
|
// TODO: https://github.com/status-im/status-desktop/issues/6778
|
||||||
console.log("not implemented")
|
console.log("not implemented")
|
||||||
|
@ -3,7 +3,6 @@ AssetsView 1.0 AssetsView.qml
|
|||||||
AssetsViewAdaptor 1.0 AssetsViewAdaptor.qml
|
AssetsViewAdaptor 1.0 AssetsViewAdaptor.qml
|
||||||
ConfirmHideAssetPopup 1.0 ConfirmHideAssetPopup.qml
|
ConfirmHideAssetPopup 1.0 ConfirmHideAssetPopup.qml
|
||||||
ConfirmHideCommunityAssetsPopup 1.0 ConfirmHideCommunityAssetsPopup.qml
|
ConfirmHideCommunityAssetsPopup 1.0 ConfirmHideCommunityAssetsPopup.qml
|
||||||
EnsResolver 1.0 EnsResolver.qml
|
|
||||||
ExistingContacts 1.0 ExistingContacts.qml
|
ExistingContacts 1.0 ExistingContacts.qml
|
||||||
HistoryView 1.0 HistoryView.qml
|
HistoryView 1.0 HistoryView.qml
|
||||||
NoFriendsRectangle 1.0 NoFriendsRectangle.qml
|
NoFriendsRectangle 1.0 NoFriendsRectangle.qml
|
||||||
@ -11,7 +10,6 @@ PasswordConfirmationView 1.0 PasswordConfirmationView.qml
|
|||||||
PasswordView 1.0 PasswordView.qml
|
PasswordView 1.0 PasswordView.qml
|
||||||
PickedContacts 1.0 PickedContacts.qml
|
PickedContacts 1.0 PickedContacts.qml
|
||||||
ProfileDialogView 1.0 ProfileDialogView.qml
|
ProfileDialogView 1.0 ProfileDialogView.qml
|
||||||
SearchResults 1.0 SearchResults.qml
|
|
||||||
SyncingCodeInstructions 1.0 SyncingCodeInstructions.qml
|
SyncingCodeInstructions 1.0 SyncingCodeInstructions.qml
|
||||||
SyncingDeviceView 1.0 SyncingDeviceView.qml
|
SyncingDeviceView 1.0 SyncingDeviceView.qml
|
||||||
SyncingDisplayCode 1.0 SyncingDisplayCode.qml
|
SyncingDisplayCode 1.0 SyncingDisplayCode.qml
|
||||||
|
Loading…
x
Reference in New Issue
Block a user