Old version of TokenSelector removed

This commit is contained in:
Michał Cieślak 2024-09-18 13:18:03 +02:00 committed by Michał
parent c8b8d1ee9d
commit 9f40251588
8 changed files with 0 additions and 1060 deletions

View File

@ -1,208 +0,0 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import StatusQ.Core.Theme 0.1
import Storybook 1.0
import Models 1.0
import SortFilterProxyModel 0.2
import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
import shared.stores 1.0
import utils 1.0
SplitView {
id: root
orientation: Qt.Vertical
Logs { id: logs }
ListModel {
id: plainTokensModel
ListElement {
key: "aave"
name: "Aave"
symbol: "AAVE"
image: "https://cryptologos.cc/logos/aave-aave-logo.png"
communityId: ""
}
ListElement {
key: "usdc"
name: "USDC"
symbol: "USDC"
image: ""
communityId: ""
}
ListElement {
key: "hst"
name: "Decision Token"
symbol: "HST"
image: "https://etherscan.io/token/images/horizonstate2_28.png"
communityId: ""
}
// DAI should be filtered out
ListElement {
key: "DAI"
name: "Dai Stablecoin"
symbol: "DAI"
image: ""
communityId: ""
}
}
QtObject {
id: d
readonly property var flatNetworks: NetworksModel.flatNetworks
readonly property var currencyStore: CurrenciesStore {}
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
readonly property var walletAccountsModel: WalletAccountsModel {}
readonly property var adaptor: TokenSelectorViewAdaptor {
assetsModel: d.assetsStore.groupedAccountAssetsModel
plainTokensBySymbolModel: plainTokensModel
flatNetworksModel: d.flatNetworks
currentCurrency: d.currencyStore.currentCurrency
showAllTokens: ctrlShowAllTokens.checked
enabledChainIds: ctrlNetwork.currentValue ? [ctrlNetwork.currentValue] : []
accountAddress: ctrlAccount.currentValue ?? ""
showCommunityAssets: ctrlShowCommunityAssets.checked
searchString: tokenSelector.searchString
}
}
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
background: Rectangle {
color: Theme.palette.baseColor3
}
TokenSelector {
id: tokenSelector
anchors.centerIn: parent
nonInteractiveDelegateKey: ctrlNonInteractiveDelegateKey.text
model: d.adaptor.outputAssetsModel
onTokenSelected: (tokensKey) => {
console.warn("!!! TOKEN SELECTED:", tokensKey)
logs.logEvent("TokenSelector::onTokenSelected", ["tokensKey"], arguments)
}
onActivated: ctrlSelectedAsset.currentIndex = ctrlSelectedAsset.indexOfValue(currentTokensKey)
}
}
LogsAndControlsPanel {
SplitView.minimumHeight: 340
SplitView.preferredHeight: 340
logsView.logText: logs.logText
RowLayout {
anchors.fill: parent
ColumnLayout {
RowLayout {
Layout.fillWidth: true
Label { text: "Selected asset:" }
ComboBox {
Layout.fillWidth: true
id: ctrlSelectedAsset
model: d.assetsStore.groupedAccountAssetsModel
textRole: "name"
valueRole: "tokensKey"
displayText: currentText || "N/A"
onActivated: tokenSelector.selectToken(currentValue)
}
TextField {
id: ctrlNonInteractiveDelegateKey
placeholderText: "Non interactive delegate token key"
}
}
Button {
text: "Reset"
onClicked: {
tokenSelector.reset()
ctrlSelectedAsset.currentIndex = -1
ctrlNonInteractiveDelegateKey.clear()
}
}
Switch {
id: ctrlShowAllTokens
text: "Show all tokens"
onToggled: {
// NB: ComboBox doesn't like changing models at runtime
tokenSelector.model = null
tokenSelector.model = d.adaptor.outputAssetsModel
}
}
Switch {
id: ctrlShowCommunityAssets
text: "Show community assets"
}
RowLayout {
Layout.fillWidth: true
Label { text: "Network:" }
ComboBox {
Layout.fillWidth: true
id: ctrlNetwork
textRole: "chainName"
valueRole: "chainId"
displayText: currentText || "All networks"
model: d.flatNetworks
currentIndex: -1
}
}
Label {
Layout.alignment: Qt.AlignRight
text: "Selected: %1".arg(ctrlNetwork.currentValue ? ctrlNetwork.currentValue.toString() : "All")
}
RowLayout {
Layout.fillWidth: true
Label { text: "Account:" }
ComboBox {
Layout.fillWidth: true
id: ctrlAccount
textRole: "name"
valueRole: "address"
displayText: currentText || "All accounts"
model: SortFilterProxyModel {
sourceModel: d.walletAccountsModel
sorters: RoleSorter { roleName: "position" }
}
currentIndex: -1
}
}
Label {
Layout.alignment: Qt.AlignRight
text: "Selected: %1".arg(ctrlAccount.currentValue ?? "all")
}
Item { Layout.fillHeight: true }
}
}
}
}
// category: Controls
// https://www.figma.com/design/TS0eQX9dAZXqZtELiwKIoK/Swap---Milestone-1?node-id=3406-231273&t=Ncl9lN1umbGEMxOn-0

View File

@ -1,244 +0,0 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import Storybook 1.0
import Models 1.0
import SortFilterProxyModel 0.2
import AppLayouts.Wallet.views 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
import shared.stores 1.0
import utils 1.0
SplitView {
id: root
orientation: Qt.Vertical
Logs { id: logs }
ListModel {
id: plainTokensModel
ListElement {
key: "aave"
name: "Aave"
symbol: "AAVE"
image: "https://cryptologos.cc/logos/aave-aave-logo.png"
communityId: ""
}
ListElement {
key: "usdc"
name: "USDC"
symbol: "USDC"
image: ""
communityId: ""
}
ListElement {
key: "hst"
name: "Decision Token"
symbol: "HST"
image: "https://etherscan.io/token/images/horizonstate2_28.png"
communityId: ""
}
}
QtObject {
id: d
property var enabledChainIds: []
function addFilter(chainId) {
if (d.enabledChainIds.includes(chainId))
return
const newFilters = d.enabledChainIds.concat(chainId)
d.enabledChainIds = newFilters
}
function removeFilter(chainId) {
const newFilters = d.enabledChainIds.filter((filter) => filter !== chainId)
d.enabledChainIds = newFilters
}
function rebuildFilter() {
let newFilters = []
for (let i = 0; i < chainIdsRepeater.count; i++) {
const item = chainIdsRepeater.itemAt(i)
if (!!item && item.checked) {
newFilters.push(item.chainId)
}
}
d.enabledChainIds = newFilters
}
readonly property string enabledChainIdsString: enabledChainIds.join(":")
readonly property var flatNetworks: NetworksModel.flatNetworks
readonly property var currencyStore: CurrenciesStore {}
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
readonly property var walletAccountsModel: WalletAccountsModel {}
readonly property var adaptor: TokenSelectorViewAdaptor {
assetsModel: d.assetsStore.groupedAccountAssetsModel
plainTokensBySymbolModel: plainTokensModel
flatNetworksModel: d.flatNetworks
enabledChainIds: d.enabledChainIds
currentCurrency: d.currencyStore.currentCurrency
showAllTokens: ctrlShowAllTokens.checked
accountAddress: ctrlAccount.currentValue ?? ""
showCommunityAssets: ctrlShowCommunityAssets.checked
searchString: ctrlSearch.text
}
}
Component.onCompleted: d.rebuildFilter()
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
background: Rectangle {
color: Theme.palette.baseColor3
}
Rectangle {
width: 380
height: 200
color: Theme.palette.statusListItem.backgroundColor
border.color: Theme.palette.primaryColor1
border.width: 1
anchors.centerIn: parent
// tokensKey, name, symbol, decimals, currentCurrencyBalance (computed), marketDetails, balances -> [ chainId, address, balance, iconUrl ]
TokenSelectorView {
id: tokenSelector
anchors.fill: parent
model: d.adaptor.outputAssetsModel
onTokenSelected: (tokensKey) => {
console.warn("!!! TOKEN SELECTED:", tokensKey)
logs.logEvent("TokenSelectorView::onTokenSelected", ["tokensKey"], arguments)
}
}
}
}
LogsAndControlsPanel {
SplitView.minimumHeight: 400
SplitView.preferredHeight: 400
logsView.logText: logs.logText
RowLayout {
anchors.fill: parent
ColumnLayout {
CheckBox {
id: ctrlTestNetworks
text: "Test networks enabled"
tristate: true
checkState: Qt.PartiallyChecked
onClicked: d.rebuildFilter()
}
Repeater {
id: chainIdsRepeater
model: SortFilterProxyModel {
sourceModel: d.flatNetworks
filters: ValueFilter {
roleName: "isTest"
value: ctrlTestNetworks.checked
enabled: ctrlTestNetworks.checkState !== Qt.PartiallyChecked
}
}
delegate: CheckBox {
required property int chainId
required property string chainName
required property string shortName
required property bool isEnabled
checked: isEnabled
opacity: enabled ? 1 : 0.3
text: "%1 (%2) - %3".arg(chainName).arg(shortName).arg(chainId)
onToggled: {
if (checked)
d.addFilter(chainId)
else
d.removeFilter(chainId)
}
}
}
Label {
Layout.fillWidth: true
text: "Enabled chain ids: %1".arg(d.enabledChainIdsString)
}
}
ColumnLayout {
RowLayout {
Layout.fillWidth: true
Label { text: "Search:" }
TextField {
Layout.fillWidth: true
id: ctrlSearch
placeholderText: "Token name or symbol"
}
}
Switch {
id: ctrlShowAllTokens
text: "Show all tokens"
checked: true
onToggled: {
// NB: ListView doesn't like changing models at runtime
tokenSelector.model = null
tokenSelector.model = d.adaptor.outputAssetsModel
}
}
Switch {
id: ctrlShowCommunityAssets
text: "Show community assets"
}
RowLayout {
Layout.fillWidth: true
Label { text: "Account:" }
ComboBox {
Layout.fillWidth: true
id: ctrlAccount
textRole: "name"
valueRole: "address"
displayText: currentIndex === -1 ? "All accounts" : currentText
model: SortFilterProxyModel {
sourceModel: d.walletAccountsModel
sorters: RoleSorter { roleName: "position" }
}
currentIndex: -1
}
}
Label {
Layout.alignment: Qt.AlignRight
text: "Selected: %1".arg(ctrlAccount.currentValue ?? "all")
}
Item { Layout.fillHeight: true }
}
}
}
}
// category: Views

View File

@ -1,260 +0,0 @@
import QtQuick 2.15
import QtTest 1.15
import QtQml 2.15
import Models 1.0
import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
Item {
id: root
width: 600
height: 400
ListModel {
id: plainTokensModel
ListElement {
key: "aave"
name: "Aave"
symbol: "AAVE"
image: "https://cryptologos.cc/logos/aave-aave-logo.png"
communityId: ""
}
}
QtObject {
id: d
readonly property var flatNetworks: NetworksModel.flatNetworks
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
readonly property var adaptor: TokenSelectorViewAdaptor {
assetsModel: d.assetsStore.groupedAccountAssetsModel
plainTokensBySymbolModel: plainTokensModel
flatNetworksModel: d.flatNetworks
currentCurrency: "USD"
enabledChainIds: [420]
Binding on searchString {
value: controlUnderTest ? controlUnderTest.searchString : ""
restoreMode: Binding.RestoreNone
}
}
}
Component {
id: componentUnderTest
TokenSelector {
anchors.centerIn: parent
model: d.adaptor.outputAssetsModel
}
}
SignalSpy {
id: signalSpy
target: controlUnderTest
signalName: "tokenSelected"
}
property TokenSelector controlUnderTest: null
TestCase {
name: "TokenSelector"
when: windowShown
function init() {
controlUnderTest = createTemporaryObject(componentUnderTest, root)
signalSpy.clear()
}
function test_basicGeometry() {
verify(!!controlUnderTest)
verify(controlUnderTest.width > 0)
verify(controlUnderTest.height > 0)
}
function test_clickEthToken() {
verify(!!controlUnderTest)
mouseClick(controlUnderTest)
waitForItemPolished(controlUnderTest)
const listview = findChild(controlUnderTest.popup.contentItem, "tokenSelectorListview")
verify(!!listview)
waitForItemPolished(listview)
const tokensKey = "ETH"
const delegate = findChild(listview, "tokenSelectorAssetDelegate_%1".arg(tokensKey))
verify(!!delegate)
tryCompare(delegate, "tokensKey", tokensKey)
// click the delegate, verify the signal has been fired and has the correct "tokensKey" as argument
mouseClick(delegate)
tryCompare(signalSpy, "count", 1)
compare(signalSpy.signalArguments[0][0], tokensKey)
compare(controlUnderTest.currentTokensKey, tokensKey)
// close the popup, reopen and verify our token is highlighted
controlUnderTest.popup.close()
mouseClick(controlUnderTest)
tryCompare(controlUnderTest.popup, "opened", true)
tryCompare(delegate, "highlighted", true)
}
function test_clickNonInteractiveToken() {
verify(!!controlUnderTest)
const tokensKey = "STT"
controlUnderTest.nonInteractiveDelegateKey = tokensKey
mouseClick(controlUnderTest)
waitForItemPolished(controlUnderTest)
const listview = findChild(controlUnderTest.popup.contentItem, "tokenSelectorListview")
verify(!!listview)
waitForItemPolished(listview)
const delegate = findChild(listview, "tokenSelectorAssetDelegate_%1".arg(tokensKey))
verify(!!delegate)
tryCompare(delegate, "tokensKey", tokensKey)
tryCompare(delegate, "interactive", false)
mouseClick(delegate)
tryCompare(signalSpy, "count", 0)
tryCompare(controlUnderTest, "currentTokensKey", "")
}
function test_selectToken() {
verify(!!controlUnderTest)
const tokensKey = "STT"
controlUnderTest.selectToken(tokensKey)
tryCompare(signalSpy, "count", 1)
compare(signalSpy.signalArguments[0][0], tokensKey)
tryCompare(controlUnderTest, "currentTokensKey", tokensKey)
const listview = findChild(controlUnderTest.popup.contentItem, "tokenSelectorListview")
verify(!!listview)
mouseClick(controlUnderTest)
const delegate = findChild(listview, "tokenSelectorAssetDelegate_%1".arg(tokensKey))
verify(!!delegate)
tryCompare(delegate, "tokensKey", tokensKey)
tryCompare(delegate, "highlighted", true)
}
function test_selectNonexistingToken() {
verify(!!controlUnderTest)
const tokensKey = "0x6b175474e89094c44da98b954eedeac495271d0f" // MET
// not available by default
controlUnderTest.selectToken(tokensKey)
tryCompare(signalSpy, "count", 1)
compare(signalSpy.signalArguments[0][0], "")
tryCompare(controlUnderTest, "currentTokensKey", "")
// enable community assets, now should be available, try to select it
d.adaptor.showCommunityAssets = true
controlUnderTest.selectToken(tokensKey)
tryCompare(signalSpy, "count", 2)
compare(signalSpy.signalArguments[1][0], tokensKey)
tryCompare(controlUnderTest, "currentTokensKey", tokensKey)
// disable community assets to simulate token gone
d.adaptor.showCommunityAssets = false
// control should reset itself back
tryCompare(signalSpy, "count", 3)
compare(signalSpy.signalArguments[2][0], "")
tryCompare(controlUnderTest, "currentTokensKey", "")
}
function test_search() {
verify(!!controlUnderTest)
mouseClick(controlUnderTest)
waitForItemPolished(controlUnderTest)
const originalCount = controlUnderTest.count
verify(originalCount > 0)
// verify the search box has focus
const searchBox = findChild(controlUnderTest.popup.contentItem, "searchBox")
verify(!!searchBox)
tryCompare(searchBox.input.edit, "focus", true)
// type "dAi"
keyClick(Qt.Key_D)
keyClick(Qt.Key_A, Qt.ShiftModifier)
keyClick(Qt.Key_I)
// search yields 1 result
waitForItemPolished(controlUnderTest)
tryCompare(controlUnderTest, "count", 1)
// closing the popup should clear the search and put the view back to original count
controlUnderTest.popup.close()
mouseClick(controlUnderTest)
tryCompare(searchBox.input.edit, "text", "")
tryCompare(controlUnderTest, "count", originalCount)
}
function test_sections() {
verify(!!controlUnderTest)
d.adaptor.enabledChainIds = [10] // filter Optimism chain only
mouseClick(controlUnderTest)
waitForItemPolished(controlUnderTest)
const listview = findChild(controlUnderTest.popup.contentItem, "tokenSelectorListview")
verify(!!listview)
waitForItemPolished(listview)
const sttDelegate = findChild(listview, "tokenSelectorAssetDelegate_STT")
verify(!!sttDelegate)
tryCompare(sttDelegate, "tokensKey", "STT")
compare(sttDelegate.ListView.section, "Your assets on Optimism")
const ethDelegate = findChild(listview, "tokenSelectorAssetDelegate_ETH")
verify(!!ethDelegate)
tryCompare(ethDelegate, "tokensKey", "ETH")
compare(ethDelegate.ListView.section, "Popular assets")
}
function test_plainTokenDelegate() {
verify(!!controlUnderTest)
d.adaptor.showAllTokens = true
const tokensKey = "aave"
mouseClick(controlUnderTest)
waitForItemPolished(controlUnderTest)
const listview = findChild(controlUnderTest.popup.contentItem, "tokenSelectorListview")
verify(!!listview)
waitForItemPolished(listview)
const delegate = findChild(listview, "tokenSelectorAssetDelegate_%1".arg(tokensKey))
verify(!!delegate)
tryCompare(delegate, "tokensKey", tokensKey)
tryCompare(delegate, "currencyBalanceAsString", "")
// click the delegate, verify the signal has been fired and has the correct "tokensKey" as argument
mouseClick(delegate)
tryCompare(signalSpy, "count", 1)
compare(signalSpy.signalArguments[0][0], tokensKey)
compare(controlUnderTest.currentTokensKey, tokensKey)
d.adaptor.showAllTokens = false
}
}
}

View File

@ -1,81 +0,0 @@
import QtQuick 2.15
import QtTest 1.15
import Models 1.0
import AppLayouts.Wallet.views 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
Item {
id: root
width: 600
height: 400
QtObject {
id: d
readonly property var flatNetworks: NetworksModel.flatNetworks
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
readonly property var adaptor: TokenSelectorViewAdaptor {
assetsModel: d.assetsStore.groupedAccountAssetsModel
flatNetworksModel: d.flatNetworks
currentCurrency: "USD"
enabledChainIds: ModelUtils.modelToFlatArray(d.flatNetworks, "chainId")
}
}
Component {
id: componentUnderTest
TokenSelectorView {
anchors.fill: parent
model: d.adaptor.outputAssetsModel
}
}
SignalSpy {
id: signalSpy
target: controlUnderTest
signalName: "tokenSelected"
}
property TokenSelectorView controlUnderTest: null
TestCase {
name: "TokenSelectorView"
when: windowShown
function init() {
controlUnderTest = createTemporaryObject(componentUnderTest, root)
signalSpy.clear()
}
function test_basicGeometry() {
verify(!!controlUnderTest)
verify(controlUnderTest.width > 0)
verify(controlUnderTest.height > 0)
}
function test_clickEthToken() {
verify(!!controlUnderTest)
const tokensKey = "ETH"
const delegate = findChild(controlUnderTest, "tokenSelectorAssetDelegate_%1".arg(tokensKey))
verify(!!delegate)
// click the delegate, verify the signal has been fired and has the correct "tokensKey" as argument
mouseClick(delegate)
tryCompare(signalSpy, "count", 1)
compare(signalSpy.signalArguments[0][0], tokensKey)
}
}
}

View File

@ -1,232 +0,0 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtGraphicalEffects 1.0
import StatusQ 0.1
import StatusQ.Components 0.1
import StatusQ.Components.private 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups.Dialog 0.1
import AppLayouts.Wallet.views 1.0
import utils 1.0
import shared.controls 1.0
ComboBox {
id: root
// expected model structure:
// tokensKey, name, symbol, decimals, currencyBalanceAsString (computed), marketDetails, balances -> [ chainId, address, balance, iconUrl ]
// input API
property string nonInteractiveDelegateKey
// output API
readonly property string currentTokensKey: d.currentTokensKey
readonly property alias searchString: searchBox.text
/**
Emitted when a token gets selected
*/
signal tokenSelected(string tokensKey)
// manipulation
function selectToken(tokensKey) {
const idx = ModelUtils.indexOf(model, "tokensKey", tokensKey)
if (idx === -1) {
console.warn("TokenSelector::selectToken: unknown tokensKey:", tokensKey)
tokensKey = ""
}
currentIndex = idx
d.currentTokensKey = tokensKey
root.tokenSelected(tokensKey)
}
function reset() {
selectToken("")
}
QtObject {
id: d
// NB: internal tracking; the ComboBox currentValue is not persistent,
// i.e. relying on currentValue is not safe
property string currentTokensKey
readonly property bool isTokenSelected: !!currentTokensKey
// NB: handle cases when our currently selected token disappears from the model -> reset
readonly property Connections _conn: Connections {
target: model ?? null
function onModelReset() {
if (d.isTokenSelected && !root.popup.opened)
root.selectToken(d.currentTokensKey)
}
function onRowsRemoved() {
if (d.isTokenSelected && !root.popup.opened)
root.selectToken(d.currentTokensKey)
}
}
}
font.family: Theme.palette.baseFont.name
font.pixelSize: Style.current.additionalTextSize
spacing: Style.current.halfPadding
verticalPadding: 10
leftPadding: 12
rightPadding: leftPadding + indicator.width + spacing
opacity: enabled ? 1 : 0.3
popup.width: 380
popup.height: 380
popup.x: root.width - popup.width
popup.margins: Style.current.xlPadding*2
popup.background: Rectangle {
color: Theme.palette.statusSelect.menuItemBackgroundColor
radius: Style.current.radius
layer.enabled: true
layer.effect: DropShadow {
horizontalOffset: 0
verticalOffset: 4
radius: 12
samples: 25
spread: 0.2
color: Theme.palette.dropShadow
}
}
popup.contentItem: ColumnLayout {
Connections {
target: root.popup
function onOpened() {
listview.positionViewAtBeginning()
}
}
spacing: 0
SearchBox {
Layout.fillWidth: true
id: searchBox
objectName: "searchBox"
input.leftPadding: root.leftPadding
input.rightPadding: root.leftPadding
minimumHeight: 56
maximumHeight: 56
placeholderText: qsTr("Search asset name or symbol")
input.showBackground: false
focus: visible
onVisibleChanged: if (!visible) input.edit.clear()
}
StatusDialogDivider {
Layout.fillWidth: true
}
StatusListView {
id: listview
objectName: "tokenSelectorListview"
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
Layout.fillHeight: true
model: root.popup.visible ? root.delegateModel : null
currentIndex: root.highlightedIndex
section.property: "sectionName"
section.delegate: StatusBaseText {
required property string section
visible: searchBox.text === ""
width: parent.width
elide: Text.ElideRight
text: visible ? section : ""
color: Theme.palette.baseColor1
padding: Style.current.padding
}
}
StatusBaseText {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignCenter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: listview.count === 0
color: Theme.palette.baseColor1
text: qsTr("No assets found")
}
}
background: StatusComboboxBackground {
border.width: 0
color: {
if (d.isTokenSelected)
return "transparent"
return root.hovered ? Theme.palette.primaryColor2 : Theme.palette.primaryColor3
}
}
contentItem: Loader {
height: 40 // by design
sourceComponent: d.isTokenSelected ? iconTextContentItem : textContentItem
}
indicator: StatusComboboxIndicator {
anchors.right: parent.right
anchors.rightMargin: root.leftPadding
anchors.verticalCenter: parent.verticalCenter
color: Theme.palette.primaryColor1
}
delegate: TokenSelectorAssetDelegate {
objectName: "tokenSelectorAssetDelegate_" + model.tokensKey
required property var model
required property int index
width: ListView.view.width
highlighted: model.tokensKey === d.currentTokensKey
enabled: model.tokensKey !== root.nonInteractiveDelegateKey
balancesListInteractive: !ListView.view.moving
name: model.name
symbol: model.symbol
currencyBalanceAsString: model.currencyBalanceAsString ?? ""
iconSource: model.iconSource
balancesModel: model.balances
onClicked: root.selectToken(model.tokensKey)
}
Component {
id: textContentItem
StatusBaseText {
objectName: "tokenSelectorContentItemText"
font.pixelSize: root.font.pixelSize
font.weight: Font.Medium
color: Theme.palette.primaryColor1
text: qsTr("Select asset")
}
}
Component {
id: iconTextContentItem
RowLayout {
spacing: root.spacing
StatusRoundedImage {
objectName: "tokenSelectorIcon"
Layout.preferredWidth: 20
Layout.preferredHeight: 20
image.source: ModelUtils.getByKey(model, "tokensKey", d.currentTokensKey, "iconSource")
}
StatusBaseText {
objectName: "tokenSelectorContentItemText"
font.pixelSize: 28
color: root.hovered ? Theme.palette.blue : Theme.palette.darkBlue
text: ModelUtils.getByKey(model, "tokensKey", d.currentTokensKey, "symbol")
}
}
}
}

View File

@ -23,7 +23,6 @@ StatusNetworkListItemTag 1.0 StatusNetworkListItemTag.qml
StatusTxProgressBar 1.0 StatusTxProgressBar.qml
SwapExchangeButton 1.0 SwapExchangeButton.qml
SwapProvidersTermsAndConditionsText 1.0 SwapProvidersTermsAndConditionsText.qml
TokenSelector 1.0 TokenSelector.qml
TokenSelectorButton 1.0 TokenSelectorButton.qml
TokenSelectorCompactButton 1.0 TokenSelectorCompactButton.qml
TokenSelectorNew 1.0 TokenSelectorNew.qml

View File

@ -1,33 +0,0 @@
import QtQuick 2.15
import StatusQ.Core 0.1
StatusListView {
id: root
// expected model structure:
// tokensKey, name, symbol, decimals, currencyBalanceAsString (computed), iconSource, marketDetails, balances -> [ chainId, address, balance, iconUrl ]
// output API
signal tokenSelected(string tokensKey)
currentIndex: -1
delegate: TokenSelectorAssetDelegate {
objectName: "tokenSelectorAssetDelegate_" + model.tokensKey
required property var model
required property int index
width: ListView.view.width
balancesListInteractive: !ListView.view.moving
name: model.name
symbol: model.symbol
currencyBalanceAsString: model.currencyBalanceAsString ?? ""
iconSource: model.iconSource
balancesModel: model.balances
onClicked: root.tokenSelected(model.tokensKey)
}
}

View File

@ -6,5 +6,4 @@ SavedAddresses 1.0 SavedAddresses.qml
TokenSelectorAssetDelegate 1.0 TokenSelectorAssetDelegate.qml
TokenSelectorCollectibleDelegate 1.0 TokenSelectorCollectibleDelegate.qml
TokenSelectorSectionDelegate 1.0 TokenSelectorSectionDelegate.qml
TokenSelectorView 1.0 TokenSelectorView.qml
AccountContextMenu 1.0 AccountContextMenu.qml