status-desktop/ui/imports/shared/panels/StatusAssetSelector.qml

235 lines
7.9 KiB
QML
Raw Normal View History

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import SortFilterProxyModel 0.2
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Backpressure 1.0
import shared.controls 1.0
Item {
id: root
property var assets
property var selectedAsset
property string defaultToken: ""
property string userSelectedToken: ""
property var tokenAssetSourceFn: function (symbol) {
return ""
}
property var searchTokenSymbolByAddressFn: function (address) {
return ""
}
// Define this in the usage to get balance in currency selected by user
property var getCurrencyBalanceString: function (currencyBalance) { return "" }
property string placeholderText
function resetInternal() {
assets = null
selectedAsset = null
}
implicitWidth: comboBox.width
implicitHeight: comboBox.implicitHeight
onSelectedAssetChanged: {
if (selectedAsset && selectedAsset.symbol) {
d.iconSource = tokenAssetSourceFn(selectedAsset.symbol.toUpperCase())
d.text = selectedAsset.symbol.toUpperCase()
}
}
QtObject {
id: d
property string iconSource: ""
property string text: ""
property string searchString
readonly property var updateSearchText: Backpressure.debounce(root, 1000, function(inputText) {
d.searchString = inputText
})
}
StatusComboBox {
id: comboBox
2022-08-09 13:52:17 +00:00
objectName: "assetSelectorButton"
width: control.width
height: parent.height
control.padding: 4
control.popup.width: 342
2022-08-03 13:41:24 +00:00
control.popup.height: 416
control.popup.x: width - control.popup.width
2022-08-09 13:52:17 +00:00
popupContentItemObjectName: "assetSelectorList"
model : SortFilterProxyModel {
sourceModel: root.assets
filters: [
ExpressionFilter {
expression: {
var tokenSymbolByAddress = searchTokenSymbolByAddressFn(d.searchString)
return visibleForNetwork && (
2022-11-03 14:11:13 +00:00
symbol.startsWith(d.searchString.toUpperCase()) || name.toUpperCase().startsWith(d.searchString.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
)
}
}
]
}
control.background: Rectangle {
2022-08-03 13:41:24 +00:00
color: "transparent"
border.width: 1
border.color: comboBox.control.hovered ? Theme.palette.primaryColor2 : Theme.palette.directColor8
radius: 16
width: rowLayout.width
implicitHeight: 48
}
contentItem: RowLayout {
id: rowLayout
2022-08-03 13:41:24 +00:00
spacing: 8
StatusBaseText {
Layout.leftMargin: 8
Layout.alignment: Qt.AlignVCenter
font.pixelSize: 15
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
color: !!root.selectedAsset ? Theme.palette.directColor1: Theme.palette.baseColor1
2022-08-03 13:41:24 +00:00
font.weight: Font.Medium
text: !!root.selectedAsset ? d.text : placeholderText
2022-08-03 13:41:24 +00:00
}
StatusRoundedImage {
2022-08-03 13:41:24 +00:00
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignVCenter
visible: !!d.iconSource
image.source: d.iconSource
image.onStatusChanged: {
if (image.status === Image.Error) {
image.source = defaultToken
}
}
}
Item {
width: 8
height: 0
}
}
2022-08-03 13:41:24 +00:00
control.indicator: null
delegate: StatusItemDelegate {
width: comboBox.control.popup.width
highlighted: index === comboBox.control.highlightedIndex
padding: 16
objectName: "AssetSelector_ItemDelegate_" + symbol
onClicked: {
// WARNING: Wrong ComboBox value processing. Check `StatusAccountSelector` for more info.
root.userSelectedToken = symbol
root.selectedAsset = {name: name, symbol: symbol, totalBalance: totalBalance, totalCurrencyBalance: totalCurrencyBalance, balances: balances, decimals: decimals}
}
// WARNING: Wrong ComboBox value processing. Check `StatusAccountSelector` for more info.
Component.onCompleted: {
if (symbol === userSelectedToken)
root.selectedAsset = { name: name, symbol: symbol, totalBalance: totalBalance, totalCurrencyBalance: totalCurrencyBalance, balances: balances, decimals: decimals}
}
contentItem: RowLayout {
spacing: 0
StatusRoundedImage {
image.source: root.tokenAssetSourceFn(symbol.toUpperCase())
image.onStatusChanged: {
if (image.status === Image.Error) {
image.source = defaultToken
}
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.leftMargin: 12
spacing: 0
RowLayout {
Layout.fillWidth: true
StatusBaseText {
Layout.fillWidth: true
text: symbol.toUpperCase()
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusBaseText {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
font.pixelSize: 15
text: parseFloat(totalBalance).toLocaleCurrencyString(Qt.locale(), symbol)
}
}
RowLayout {
Layout.fillWidth: true
StatusBaseText {
Layout.fillWidth: true
2022-08-03 13:41:24 +00:00
elide: Text.ElideRight
text: name
color: Theme.palette.baseColor1
font.pixelSize: 15
}
StatusBaseText {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
font.pixelSize: 15
text: getCurrencyBalanceString(totalCurrencyBalance)
color: Theme.palette.baseColor1
}
}
}
}
}
Component.onCompleted: {
control.currentIndex = -1
control.popup.contentItem.header = searchBox
}
control.popup.onOpened: {
control.currentIndex = -1
}
}
Component {
id: searchBox
StatusInput {
width: parent.width
input.showBackground: false
placeholderText: qsTr("Search for token or enter token address")
onTextChanged: Qt.callLater(d.updateSearchText, text)
input.clearable: true
leftPadding: 0
rightPadding: 0
input.rightComponent: StatusIcon {
width: 24
height: 24
color: Theme.palette.baseColor1
icon: "search"
}
Rectangle {
anchors.bottom: parent.bottom
height: 1
width: parent.width
color: Theme.palette.baseColor2
}
}
}
}