chore(Wallet): AssetView replaced with the refactored version
Closes: #14704 Closes: #14939
This commit is contained in:
parent
38914df0f0
commit
d700a1ad53
|
@ -1,271 +0,0 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import shared.views 1.0
|
||||
import utils 1.0
|
||||
|
||||
import Storybook 1.0
|
||||
|
||||
import Qt.labs.settings 1.1
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
ListModel {
|
||||
id: assetsModel
|
||||
|
||||
function format(amount, symbol) {
|
||||
return `${amount.toLocaleString(Qt.locale())} ${symbol}`
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
const data = [
|
||||
{
|
||||
key: "key_ETH",
|
||||
symbol: "ETH",
|
||||
name: "Ether",
|
||||
icon: Constants.tokenIcon("ETH", false),
|
||||
balance: 10.0,
|
||||
balanceText: format(10.0, "ETH"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: true,
|
||||
marketPrice: 0,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 2,
|
||||
canBeHidden: false
|
||||
},
|
||||
{
|
||||
key: "key_SNT",
|
||||
symbol: "SNT",
|
||||
name: "Status",
|
||||
icon: Constants.tokenIcon("SNT", false),
|
||||
balance: 20023.0,
|
||||
balanceText: format(20023.0, "SNT"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 50.23,
|
||||
marketChangePct24hour: 12,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 1,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_MCT",
|
||||
symbol: "MCT",
|
||||
name: "My custom token",
|
||||
icon: Constants.tokenIcon("ZRX", false),
|
||||
balance: 102.4,
|
||||
balanceText: format(102.4, "MCT"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: false,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 0,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "34",
|
||||
communityName: "Crypto Kitties",
|
||||
communityIcon: Constants.tokenIcon("DAI", false),
|
||||
|
||||
position: 4,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_DAI",
|
||||
symbol: "DAI",
|
||||
name: "Dai",
|
||||
icon: Constants.tokenIcon("DAI", false),
|
||||
balance: 123.24,
|
||||
balanceText: format(123.24, "DAI"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 23.23,
|
||||
marketChangePct24hour: 2.3,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 3,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_USDT",
|
||||
symbol: "USDT",
|
||||
name: "USDT",
|
||||
icon: Constants.tokenIcon("USDT", false),
|
||||
balance: 15.24,
|
||||
balanceText: format(15.24, "USDT"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 0.99,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 5,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_TBT",
|
||||
symbol: "TBT",
|
||||
name: "The best token",
|
||||
icon: Constants.tokenIcon("UNI", false),
|
||||
balance: 102,
|
||||
balanceText: format(102, "TBT"),
|
||||
error: "Pocket Network (POKT) & Infura are currently both "
|
||||
+ "unavailable for %1. %1 balances are as of %2."
|
||||
.arg("TBT").arg("10/06/2024"),
|
||||
|
||||
marketDetailsAvailable: false,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 0,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "3423",
|
||||
communityName: "Best tokens",
|
||||
communityIcon: Constants.tokenIcon("UNI", false),
|
||||
|
||||
position: 6,
|
||||
canBeHidden: true
|
||||
}
|
||||
]
|
||||
|
||||
append(data)
|
||||
}
|
||||
}
|
||||
|
||||
SplitView {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
orientation: Qt.Vertical
|
||||
|
||||
Pane {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
AssetsViewNew {
|
||||
anchors.fill: parent
|
||||
|
||||
loading: loadingCheckBox.checked
|
||||
sorterVisible: sorterVisibleCheckBox.checked
|
||||
customOrderAvailable: customOrderAvailableCheckBox.checked
|
||||
|
||||
sendEnabled: sendEnabledCheckBox.checked
|
||||
swapEnabled: swapEnabledCheckBox.checked
|
||||
swapVisible: swapVisibleCheckBox.checked
|
||||
|
||||
balanceError: balanceErrorCheckBox.checked
|
||||
? "Balance error!" : ""
|
||||
|
||||
marketDataError: marketDataErrorCheckBox.checked
|
||||
? "Market data error!" : ""
|
||||
|
||||
model: assetsModel
|
||||
|
||||
onSendRequested: logs.logEvent(`send requested: ${key}`)
|
||||
onReceiveRequested: logs.logEvent(`receive requested: ${key}`)
|
||||
onSwapRequested: logs.logEvent(`swap requested: ${key}`)
|
||||
onAssetClicked: logs.logEvent(`asset clicked: ${key}`)
|
||||
|
||||
onHideRequested: logs.logEvent(`hide requested: ${key}`)
|
||||
onHideCommunityAssets: logs.logEvent(`hide community assets requested: ${communityKey}`)
|
||||
onManageTokensRequested: logs.logEvent(`manage tokens requested`)
|
||||
}
|
||||
}
|
||||
|
||||
Logs {
|
||||
id: logs
|
||||
}
|
||||
|
||||
LogsView {
|
||||
clip: true
|
||||
|
||||
SplitView.preferredHeight: 150
|
||||
SplitView.fillWidth: true
|
||||
|
||||
logText: logs.logText
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
SplitView.preferredWidth: 300
|
||||
|
||||
ColumnLayout {
|
||||
CheckBox {
|
||||
id: loadingCheckBox
|
||||
|
||||
text: "loading"
|
||||
}
|
||||
CheckBox {
|
||||
id: sorterVisibleCheckBox
|
||||
|
||||
text: "sorter visible"
|
||||
}
|
||||
CheckBox {
|
||||
id: customOrderAvailableCheckBox
|
||||
|
||||
text: "custom order available"
|
||||
}
|
||||
CheckBox {
|
||||
id: sendEnabledCheckBox
|
||||
|
||||
text: "send enabled"
|
||||
}
|
||||
CheckBox {
|
||||
id: swapEnabledCheckBox
|
||||
|
||||
text: "swap enabled"
|
||||
}
|
||||
CheckBox {
|
||||
id: swapVisibleCheckBox
|
||||
|
||||
text: "swap visible"
|
||||
}
|
||||
CheckBox {
|
||||
id: balanceErrorCheckBox
|
||||
|
||||
text: "balance error"
|
||||
}
|
||||
CheckBox {
|
||||
id: marketDataErrorCheckBox
|
||||
|
||||
text: "market data error"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Settings {
|
||||
property alias loading: loadingCheckBox.checked
|
||||
property alias filterVisible: sorterVisibleCheckBox.checked
|
||||
property alias customOrderAvailable: customOrderAvailableCheckBox.checked
|
||||
property alias sendEnabled: sendEnabledCheckBox.checked
|
||||
property alias swapEnabled: swapEnabledCheckBox.checked
|
||||
property alias swapVisible: swapVisibleCheckBox.checked
|
||||
property alias balanceError: balanceErrorCheckBox.checked
|
||||
property alias marketDataError: marketDataErrorCheckBox.checked
|
||||
}
|
||||
}
|
||||
|
||||
// category: Views
|
|
@ -1,248 +1,271 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Models 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
|
||||
import mainui 1.0
|
||||
import shared.views 1.0
|
||||
import utils 1.0
|
||||
|
||||
import shared.controls 1.0
|
||||
import shared.views 1.0
|
||||
import shared.stores 1.0
|
||||
|
||||
import Storybook 1.0
|
||||
import Models 1.0
|
||||
|
||||
import AppLayouts.Wallet.views 1.0
|
||||
import AppLayouts.Wallet.stores 1.0
|
||||
|
||||
import Qt.labs.settings 1.1
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
Logs { id: logs }
|
||||
ListModel {
|
||||
id: assetsModel
|
||||
|
||||
orientation: Qt.Horizontal
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property string networksChainsCurrentlySelected: {
|
||||
let supportedNwChains = []
|
||||
for (let i = 0; i< networksRepeater.count; i++) {
|
||||
if (networksRepeater.itemAt(i).checked && networksRepeater.itemAt(i).visible)
|
||||
supportedNwChains.push(networksRepeater.itemAt(i).chainID)
|
||||
}
|
||||
return supportedNwChains.join(":")
|
||||
function format(amount, symbol) {
|
||||
return `${amount.toLocaleString(Qt.locale())} ${symbol}`
|
||||
}
|
||||
|
||||
readonly property string addressesSelected: {
|
||||
let supportedAddresses = []
|
||||
for (let i = 0; i< accountsRepeater.count; i++) {
|
||||
if (accountsRepeater.itemAt(i).checked && accountsRepeater.itemAt(i).visible)
|
||||
supportedAddresses.push(accountsRepeater.itemAt(i).address)
|
||||
}
|
||||
return supportedAddresses.join(":")
|
||||
}
|
||||
Component.onCompleted: {
|
||||
const data = [
|
||||
{
|
||||
key: "key_ETH",
|
||||
symbol: "ETH",
|
||||
name: "Ether",
|
||||
icon: Constants.tokenIcon("ETH", false),
|
||||
balance: 10.0,
|
||||
balanceText: format(10.0, "ETH"),
|
||||
error: "",
|
||||
|
||||
readonly property var currencyStore: CurrenciesStore {}
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: true,
|
||||
marketPrice: 0,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
property WalletAssetsStore walletAssetStore: WalletAssetsStore {
|
||||
assetsWithFilteredBalances: d.assetsWithFilteredBalances
|
||||
assetsController: assetsView.controller
|
||||
}
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
// Added this here simply because the network and address filtering wont work in Storybook applied in AssetsView
|
||||
readonly property SubmodelProxyModel assetsWithFilteredBalances: SubmodelProxyModel {
|
||||
sourceModel: d.walletAssetStore.groupedAccountsAssetsModel
|
||||
submodelRoleName: "balances"
|
||||
delegateModel: SortFilterProxyModel {
|
||||
sourceModel: submodel
|
||||
filters: FastExpressionFilter {
|
||||
expression: {
|
||||
d.networksChainsCurrentlySelected
|
||||
return d.networksChainsCurrentlySelected.split(":").includes(model.chainId+"")
|
||||
}
|
||||
expectedRoles: ["chainId"]
|
||||
}
|
||||
position: 2,
|
||||
canBeHidden: false
|
||||
},
|
||||
{
|
||||
key: "key_SNT",
|
||||
symbol: "SNT",
|
||||
name: "Status",
|
||||
icon: Constants.tokenIcon("SNT", false),
|
||||
balance: 20023.0,
|
||||
balanceText: format(20023.0, "SNT"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 50.23,
|
||||
marketChangePct24hour: 12,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 1,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_MCT",
|
||||
symbol: "MCT",
|
||||
name: "My custom token",
|
||||
icon: Constants.tokenIcon("ZRX", false),
|
||||
balance: 102.4,
|
||||
balanceText: format(102.4, "MCT"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: false,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 0,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "34",
|
||||
communityName: "Crypto Kitties",
|
||||
communityIcon: Constants.tokenIcon("DAI", false),
|
||||
|
||||
position: 4,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_DAI",
|
||||
symbol: "DAI",
|
||||
name: "Dai",
|
||||
icon: Constants.tokenIcon("DAI", false),
|
||||
balance: 123.24,
|
||||
balanceText: format(123.24, "DAI"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 23.23,
|
||||
marketChangePct24hour: 2.3,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 3,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_USDT",
|
||||
symbol: "USDT",
|
||||
name: "USDT",
|
||||
icon: Constants.tokenIcon("USDT", false),
|
||||
balance: 15.24,
|
||||
balanceText: format(15.24, "USDT"),
|
||||
error: "",
|
||||
|
||||
marketDetailsAvailable: true,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 0.99,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "",
|
||||
communityName: "",
|
||||
communityIcon: Qt.resolvedUrl(""),
|
||||
|
||||
position: 5,
|
||||
canBeHidden: true
|
||||
},
|
||||
{
|
||||
key: "key_TBT",
|
||||
symbol: "TBT",
|
||||
name: "The best token",
|
||||
icon: Constants.tokenIcon("UNI", false),
|
||||
balance: 102,
|
||||
balanceText: format(102, "TBT"),
|
||||
error: "Pocket Network (POKT) & Infura are currently both "
|
||||
+ "unavailable for %1. %1 balances are as of %2."
|
||||
.arg("TBT").arg("10/06/2024"),
|
||||
|
||||
marketDetailsAvailable: false,
|
||||
marketDetailsLoading: false,
|
||||
marketPrice: 0,
|
||||
marketChangePct24hour: 0,
|
||||
|
||||
communityId: "3423",
|
||||
communityName: "Best tokens",
|
||||
communityIcon: Constants.tokenIcon("UNI", false),
|
||||
|
||||
position: 6,
|
||||
canBeHidden: true
|
||||
}
|
||||
]
|
||||
|
||||
append(data)
|
||||
}
|
||||
}
|
||||
|
||||
Popups {
|
||||
popupParent: root
|
||||
rootStore: QtObject {}
|
||||
communityTokensStore: QtObject {}
|
||||
walletAssetsStore: d.walletAssetStore
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stack
|
||||
SplitView {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
currentIndex: 0
|
||||
orientation: Qt.Vertical
|
||||
|
||||
Pane {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
AssetsView {
|
||||
id: assetsView
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
areAssetsLoading: loadingCheckbox.checked
|
||||
controller: ManageTokensController {
|
||||
sourceModel: d.walletAssetStore.groupedAccountAssetsModel
|
||||
settingsKey: "WalletAssets"
|
||||
serializeAsCollectibles: false
|
||||
anchors.fill: parent
|
||||
|
||||
onRequestSaveSettings: (jsonData) => {
|
||||
savingStarted()
|
||||
settingsStore.setValue(settingsKey, jsonData)
|
||||
savingFinished()
|
||||
}
|
||||
onRequestLoadSettings: {
|
||||
loadingStarted()
|
||||
const jsonData = settingsStore.value(settingsKey, null)
|
||||
loadingFinished(jsonData)
|
||||
}
|
||||
onRequestClearSettings: {
|
||||
settingsStore.setValue(settingsKey, null)
|
||||
}
|
||||
loading: loadingCheckBox.checked
|
||||
sorterVisible: sorterVisibleCheckBox.checked
|
||||
customOrderAvailable: customOrderAvailableCheckBox.checked
|
||||
|
||||
onTokenHidden: (symbol, name) => Global.displayToastMessage(
|
||||
qsTr("%1 (%2) was successfully hidden").arg(name).arg(symbol), "", "checkmark-circle",
|
||||
false, Constants.ephemeralNotificationType.success, "")
|
||||
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
||||
qsTr("%1 community assets successfully hidden").arg(communityName), "", "checkmark-circle",
|
||||
false, Constants.ephemeralNotificationType.success, "")
|
||||
onTokenShown: (symbol, name) => Global.displayToastMessage(qsTr("%1 is now visible").arg(name), "", "checkmark-circle",
|
||||
false, Constants.ephemeralNotificationType.success, "")
|
||||
onCommunityTokenGroupShown: (communityName) => Global.displayToastMessage(
|
||||
qsTr("%1 community assets are now visible").arg(communityName), "", "checkmark-circle",
|
||||
false, Constants.ephemeralNotificationType.success, "")
|
||||
}
|
||||
filterVisible: ctrlFilterVisible.checked
|
||||
currencyStore: d.currencyStore
|
||||
tokensStore: TokensStore {
|
||||
displayAssetsBelowBalance: ctrlBalanceThresholdSwitch.checked
|
||||
getDisplayAssetsBelowBalanceThresholdDisplayAmount: () => ctrlBalanceThreshold.value
|
||||
}
|
||||
networkFilters: d.networksChainsCurrentlySelected
|
||||
addressFilters: d.addressesSelected
|
||||
onAssetClicked: {
|
||||
stack.currentIndex = 1
|
||||
detailsView.token = token
|
||||
logs.logEvent("onAssetClicked", ["token"], [token.symbol, token.communityId])
|
||||
}
|
||||
onSendRequested: logs.logEvent("onSendRequested", ["symbol"], arguments)
|
||||
onReceiveRequested: logs.logEvent("onReceiveRequested", ["symbol"], arguments)
|
||||
onSwitchToCommunityRequested: logs.logEvent("onSwitchToCommunityRequested", ["communityId"], arguments)
|
||||
onManageTokensRequested: logs.logEvent("onManageTokensRequested")
|
||||
sendEnabled: sendEnabledCheckBox.checked
|
||||
swapEnabled: swapEnabledCheckBox.checked
|
||||
swapVisible: swapVisibleCheckBox.checked
|
||||
|
||||
Settings {
|
||||
id: settingsStore
|
||||
category: "ManageTokens-" + assetsView.controller.settingsKey
|
||||
balanceError: balanceErrorCheckBox.checked
|
||||
? "Balance error!" : ""
|
||||
|
||||
marketDataError: marketDataErrorCheckBox.checked
|
||||
? "Market data error!" : ""
|
||||
|
||||
model: assetsModel
|
||||
|
||||
onSendRequested: logs.logEvent(`send requested: ${key}`)
|
||||
onReceiveRequested: logs.logEvent(`receive requested: ${key}`)
|
||||
onSwapRequested: logs.logEvent(`swap requested: ${key}`)
|
||||
onAssetClicked: logs.logEvent(`asset clicked: ${key}`)
|
||||
|
||||
onHideRequested: logs.logEvent(`hide requested: ${key}`)
|
||||
onHideCommunityAssets: logs.logEvent(`hide community assets requested: ${communityKey}`)
|
||||
onManageTokensRequested: logs.logEvent(`manage tokens requested`)
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Button {
|
||||
text: "go back"
|
||||
onClicked: stack.currentIndex = 0
|
||||
}
|
||||
AssetsDetailView {
|
||||
id: detailsView
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
currencyStore: d.currencyStore
|
||||
allNetworksModel: NetworksModel.flatNetworks
|
||||
networkFilters: d.networksChainsCurrentlySelected
|
||||
Logs {
|
||||
id: logs
|
||||
}
|
||||
|
||||
LogsView {
|
||||
clip: true
|
||||
|
||||
SplitView.preferredHeight: 150
|
||||
SplitView.fillWidth: true
|
||||
|
||||
logText: logs.logText
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
SplitView.preferredWidth: 250
|
||||
SplitView.preferredWidth: 300
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 12
|
||||
anchors.fill: parent
|
||||
|
||||
Switch {
|
||||
id: ctrlFilterVisible
|
||||
text: "Filter visible"
|
||||
checked: true
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: loadingCheckbox
|
||||
checked: false
|
||||
id: loadingCheckBox
|
||||
|
||||
text: "loading"
|
||||
}
|
||||
CheckBox {
|
||||
id: sorterVisibleCheckBox
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
text: "select supported network(s)"
|
||||
text: "sorter visible"
|
||||
}
|
||||
Repeater {
|
||||
id: networksRepeater
|
||||
model: NetworksModel.flatNetworks
|
||||
delegate: CheckBox {
|
||||
readonly property int chainID: chainId
|
||||
width: parent.width
|
||||
text: chainName
|
||||
visible: isTest
|
||||
checked: true
|
||||
onToggled: {
|
||||
isEnabled = checked
|
||||
CheckBox {
|
||||
id: customOrderAvailableCheckBox
|
||||
|
||||
text: "custom order available"
|
||||
}
|
||||
CheckBox {
|
||||
id: sendEnabledCheckBox
|
||||
|
||||
text: "send enabled"
|
||||
}
|
||||
CheckBox {
|
||||
id: swapEnabledCheckBox
|
||||
|
||||
text: "swap enabled"
|
||||
}
|
||||
CheckBox {
|
||||
id: swapVisibleCheckBox
|
||||
|
||||
text: "swap visible"
|
||||
}
|
||||
CheckBox {
|
||||
id: balanceErrorCheckBox
|
||||
|
||||
text: "balance error"
|
||||
}
|
||||
CheckBox {
|
||||
id: marketDataErrorCheckBox
|
||||
|
||||
text: "market data error"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
text: "select account(s)"
|
||||
}
|
||||
Repeater {
|
||||
id: accountsRepeater
|
||||
model: WalletAccountsModel {}
|
||||
delegate: CheckBox {
|
||||
readonly property string address: model.address
|
||||
checked: true
|
||||
visible: index<2
|
||||
width: parent.width
|
||||
text: name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Switch {
|
||||
id: ctrlBalanceThresholdSwitch
|
||||
text: qsTr("Currency balance threshold")
|
||||
checked: false
|
||||
}
|
||||
CurrencyAmountInput {
|
||||
id: ctrlBalanceThreshold
|
||||
value: 10.1
|
||||
}
|
||||
}
|
||||
}
|
||||
Settings {
|
||||
property alias loading: loadingCheckBox.checked
|
||||
property alias filterVisible: sorterVisibleCheckBox.checked
|
||||
property alias customOrderAvailable: customOrderAvailableCheckBox.checked
|
||||
property alias sendEnabled: sendEnabledCheckBox.checked
|
||||
property alias swapEnabled: swapEnabledCheckBox.checked
|
||||
property alias swapVisible: swapVisibleCheckBox.checked
|
||||
property alias balanceError: balanceErrorCheckBox.checked
|
||||
property alias marketDataError: marketDataErrorCheckBox.checked
|
||||
}
|
||||
}
|
||||
|
||||
// category: Views
|
||||
// https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?type=design&node-id=17159-67977&mode=design&t=s5EXsh6Vi4nTNYUh-0
|
||||
// https://www.figma.com/file/FkFClTCYKf83RJWoifWgoX/Wallet-v2?type=design&node-id=17171-285559&mode=design&t=s5EXsh6Vi4nTNYUh-0
|
||||
|
|
|
@ -14,7 +14,7 @@ SplitView {
|
|||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
TokenDelegateNew {
|
||||
TokenDelegate {
|
||||
anchors.centerIn: parent
|
||||
|
||||
name: nameTextFiled.text
|
||||
|
|
|
@ -206,12 +206,14 @@ Dialog {
|
|||
anchors.bottom: parent.bottom
|
||||
currentIndex: walletTabBar.currentIndex
|
||||
|
||||
AssetsView {
|
||||
id: assetsTab
|
||||
controller: popup.assetsStore.assetsController
|
||||
currencyStore: popup.currencyStore
|
||||
tokensStore: popup.tokensStore
|
||||
}
|
||||
// Disable because the refactored version of AssetView requires specific
|
||||
// integration but the old version was not working properly neither.
|
||||
//AssetsView {
|
||||
// id: assetsTab
|
||||
// controller: popup.assetsStore.assetsController
|
||||
// currencyStore: popup.currencyStore
|
||||
// tokensStore: popup.tokensStore
|
||||
//}
|
||||
HistoryView {
|
||||
id: historyTab
|
||||
overview: WalletStore.dappBrowserAccount
|
||||
|
|
|
@ -143,8 +143,7 @@ RightTabBaseView {
|
|||
Component {
|
||||
id: assetsView
|
||||
|
||||
AssetsViewNew {
|
||||
|
||||
AssetsView {
|
||||
AssetsViewAdaptor {
|
||||
id: assetsViewAdaptor
|
||||
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
TokenDelegate {
|
||||
id: root
|
||||
|
||||
title: Constants.dummyText
|
||||
subTitle: Constants.dummyText
|
||||
asset.name: Constants.dummyText
|
||||
|
||||
currencyBalance.text: Constants.dummyText
|
||||
currencyBalance.loading: true
|
||||
change24HourPercentage.text: Constants.dummyText
|
||||
change24HourPercentage.loading: true
|
||||
currencyPrice.text: Constants.dummyText
|
||||
currencyPrice.loading: true
|
||||
|
||||
statusListItemSubTitle.loading: true
|
||||
statusListItemTitle.loading: true
|
||||
statusListItemIcon.loading: true
|
||||
|
||||
textColor: Theme.palette.baseColor1
|
||||
marketDetailsAvailable: true
|
||||
marketDetailsLoading: true
|
||||
|
||||
enabled: false
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import utils 1.0
|
||||
|
||||
TokenDelegateNew {
|
||||
title: Constants.dummyText
|
||||
subTitle: Constants.dummyText
|
||||
asset.name: Constants.dummyText
|
||||
|
||||
statusListItemSubTitle.loading: true
|
||||
statusListItemTitle.loading: true
|
||||
statusListItemIcon.loading: true
|
||||
|
||||
marketDetailsAvailable: true
|
||||
marketDetailsLoading: true
|
||||
|
||||
enabled: false
|
||||
}
|
|
@ -7,67 +7,63 @@ import StatusQ.Core 0.1
|
|||
import StatusQ.Controls 0.1
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
// expected roles: name, symbol, currencyPrice, changePct24hour, communityId, communityName, communityImage
|
||||
property string name
|
||||
property url icon
|
||||
property string balance
|
||||
|
||||
property alias currencyBalance: currencyBalance
|
||||
property alias change24HourPercentage: change24HourPercentageText
|
||||
property alias currencyPrice: currencyPrice
|
||||
property bool marketDetailsAvailable: false
|
||||
property string marketBalance
|
||||
property bool marketDetailsLoading: false
|
||||
property string marketCurrencyPrice
|
||||
property real marketChangePct24hour
|
||||
|
||||
property string currentCurrencySymbol
|
||||
property string textColor: {
|
||||
if (!modelData || !modelData.marketDetails) {
|
||||
return Theme.palette.successColor1
|
||||
}
|
||||
return modelData.marketDetails.changePct24hour === undefined ?
|
||||
Theme.palette.baseColor1 :
|
||||
modelData.marketDetails.changePct24hour === 0 ?
|
||||
Theme.palette.baseColor1 :
|
||||
modelData.marketDetails.changePct24hour < 0 ?
|
||||
Theme.palette.dangerColor1 :
|
||||
Theme.palette.successColor1
|
||||
}
|
||||
property string communityId
|
||||
property string communityName
|
||||
property url communityIcon
|
||||
|
||||
property string errorTooltipText_1
|
||||
property string errorTooltipText_2
|
||||
|
||||
readonly property bool isCommunityToken: !!modelData && !!modelData.communityId
|
||||
readonly property string symbolUrl: {
|
||||
if (!modelData)
|
||||
return ""
|
||||
if (modelData.image)
|
||||
return modelData.image
|
||||
if (modelData.symbol)
|
||||
return Constants.tokenIcon(modelData.symbol, false)
|
||||
return ""
|
||||
signal communityClicked(string communityId)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property bool isCommunityToken: !!root.communityId
|
||||
|
||||
readonly property string textColor: {
|
||||
if (!root.marketDetailsAvailable)
|
||||
return Theme.palette.successColor1
|
||||
|
||||
if (root.marketChangePct24hour === 0)
|
||||
return Theme.palette.baseColor1
|
||||
|
||||
return root.marketChangePct24hour < 0
|
||||
? Theme.palette.dangerColor1
|
||||
: Theme.palette.successColor1
|
||||
}
|
||||
|
||||
readonly property string upDownTriangle: {
|
||||
if (!modelData || !modelData.marketDetails)
|
||||
return ""
|
||||
if (modelData.marketDetails.changePct24hour < 0)
|
||||
return "▾"
|
||||
if (modelData.marketDetails.changePct24hour > 0)
|
||||
return "▴"
|
||||
if (root.marketChangePct24hour === 0)
|
||||
return ""
|
||||
|
||||
return root.marketChangePct24hour < 0 ? "▾" : "▴"
|
||||
}
|
||||
}
|
||||
readonly property bool isUndefined: modelData && !modelData.marketDetailsLoading && title === ""
|
||||
|
||||
signal switchToCommunityRequested(string communityId)
|
||||
|
||||
title: modelData ? modelData.name : ""
|
||||
subTitle: LocaleUtils.currencyAmountToLocaleString(modelData.enabledNetworkBalance)
|
||||
asset.name: symbolUrl
|
||||
title: root.name
|
||||
subTitle: root.balance
|
||||
asset.name: root.icon
|
||||
asset.isImage: true
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
errorIcon.tooltip.maxWidth: 300
|
||||
height: isUndefined ? 0 : implicitHeight
|
||||
visible: !isUndefined
|
||||
height: implicitHeight
|
||||
|
||||
statusListItemTitleIcons.sourceComponent: StatusFlatRoundButton {
|
||||
width: 14
|
||||
|
@ -94,26 +90,32 @@ StatusListItem {
|
|||
icon.color: Theme.palette.dangerColor1
|
||||
tooltip.text: root.errorTooltipText_2
|
||||
tooltip.maxWidth: 200
|
||||
visible: !!tooltip.text
|
||||
visible: root.marketDetailsAvailable && !!tooltip.text
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
id: currencyBalance
|
||||
|
||||
anchors.right: parent.right
|
||||
loading: modelData && modelData.marketDetailsLoading
|
||||
visible: !errorIcon.visible && !root.isCommunityToken
|
||||
visible: !errorIcon.visible && root.marketDetailsAvailable
|
||||
|
||||
loading: root.marketDetailsLoading
|
||||
text: loading ? Constants.dummyText : root.marketBalance
|
||||
}
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
spacing: 6
|
||||
visible: !errorIcon.visible && !root.isCommunityToken
|
||||
visible: !errorIcon.visible && root.marketDetailsAvailable
|
||||
|
||||
StatusTextWithLoadingState {
|
||||
id: change24HourPercentageText
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
customColor: root.textColor
|
||||
customColor: d.textColor
|
||||
font.pixelSize: 13
|
||||
loading: modelData && modelData.marketDetailsLoading
|
||||
text: modelData && modelData.marketDetails && modelData.marketDetails.changePct24hour !== undefined ? "%1 %2%".arg(root.upDownTriangle).arg(LocaleUtils.numberToLocaleString(modelData.marketDetails.changePct24hour, 2))
|
||||
: "---"
|
||||
loading: root.marketDetailsLoading
|
||||
|
||||
text: qsTr("%1 %2%", "[up/down/none character depending on value sign] [localized percentage value]%")
|
||||
.arg(d.upDownTriangle).arg(LocaleUtils.numberToLocaleString(root.marketChangePct24hour, 2))
|
||||
}
|
||||
Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
@ -123,39 +125,45 @@ StatusListItem {
|
|||
}
|
||||
StatusTextWithLoadingState {
|
||||
id: currencyPrice
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
customColor: root.textColor
|
||||
customColor: d.textColor
|
||||
font.pixelSize: 13
|
||||
loading: modelData && modelData.marketDetailsLoading
|
||||
text: modelData && modelData.marketDetails ? LocaleUtils.currencyAmountToLocaleString(modelData.marketDetails.currencyPrice) : ""
|
||||
loading: root.marketDetailsLoading
|
||||
text: loading ? Constants.dummyText : root.marketCurrencyPrice
|
||||
}
|
||||
}
|
||||
ManageTokensCommunityTag {
|
||||
|
||||
Loader {
|
||||
active: d.isCommunityToken
|
||||
|
||||
sourceComponent: ManageTokensCommunityTag {
|
||||
anchors.right: parent.right
|
||||
communityImage: !!modelData ? modelData.communityImage : ""
|
||||
communityName: !!modelData && !!modelData.communityName ? modelData.communityName: ""
|
||||
communityId: !!modelData && !!modelData.communityId ? modelData.communityId : ""
|
||||
|
||||
communityImage: root.communityIcon
|
||||
communityName: root.communityName
|
||||
communityId: root.communityId
|
||||
|
||||
asset.letterSize: 12
|
||||
visible: root.isCommunityToken
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onSingleTapped: root.switchToCommunityRequested(modelData.communityId)
|
||||
onSingleTapped: root.communityClicked(root.communityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
states: [
|
||||
State {
|
||||
states: State {
|
||||
name: "unknownToken"
|
||||
when: !root.symbolUrl
|
||||
when: !root.icon.toString()
|
||||
|
||||
PropertyChanges {
|
||||
target: root.asset
|
||||
isLetterIdenticon: true
|
||||
color: Theme.palette.miscColor5
|
||||
name: !!modelData && modelData.symbol ? modelData.symbol : ""
|
||||
name: root.name
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
import utils 1.0
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
property string name
|
||||
property url icon
|
||||
property string balance
|
||||
|
||||
property bool marketDetailsAvailable: false
|
||||
property string marketBalance
|
||||
property bool marketDetailsLoading: false
|
||||
property string marketCurrencyPrice
|
||||
property real marketChangePct24hour
|
||||
|
||||
property string communityId
|
||||
property string communityName
|
||||
property url communityIcon
|
||||
|
||||
property string errorTooltipText_1
|
||||
property string errorTooltipText_2
|
||||
|
||||
signal communityClicked(string communityId)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property bool isCommunityToken: !!root.communityId
|
||||
|
||||
readonly property string textColor: {
|
||||
if (!root.marketDetailsAvailable)
|
||||
return Theme.palette.successColor1
|
||||
|
||||
if (root.marketChangePct24hour === 0)
|
||||
return Theme.palette.baseColor1
|
||||
|
||||
return root.marketChangePct24hour < 0
|
||||
? Theme.palette.dangerColor1
|
||||
: Theme.palette.successColor1
|
||||
}
|
||||
|
||||
readonly property string upDownTriangle: {
|
||||
if (root.marketChangePct24hour === 0)
|
||||
return ""
|
||||
|
||||
return root.marketChangePct24hour < 0 ? "▾" : "▴"
|
||||
}
|
||||
}
|
||||
|
||||
title: root.name
|
||||
subTitle: root.balance
|
||||
asset.name: root.icon
|
||||
asset.isImage: true
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
errorIcon.tooltip.maxWidth: 300
|
||||
height: implicitHeight
|
||||
|
||||
statusListItemTitleIcons.sourceComponent: StatusFlatRoundButton {
|
||||
width: 14
|
||||
height: visible ? 14 : 0
|
||||
icon.width: 14
|
||||
icon.height: 14
|
||||
icon.name: "tiny/warning"
|
||||
icon.color: Theme.palette.dangerColor1
|
||||
tooltip.text: root.errorTooltipText_1
|
||||
tooltip.maxWidth: 300
|
||||
visible: !!tooltip.text
|
||||
}
|
||||
|
||||
components: [
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
StatusFlatRoundButton {
|
||||
id: errorIcon
|
||||
width: 14
|
||||
height: visible ? 14 : 0
|
||||
icon.width: 14
|
||||
icon.height: 14
|
||||
icon.name: "tiny/warning"
|
||||
icon.color: Theme.palette.dangerColor1
|
||||
tooltip.text: root.errorTooltipText_2
|
||||
tooltip.maxWidth: 200
|
||||
visible: root.marketDetailsAvailable && !!tooltip.text
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
id: currencyBalance
|
||||
|
||||
anchors.right: parent.right
|
||||
visible: !errorIcon.visible && root.marketDetailsAvailable
|
||||
|
||||
loading: root.marketDetailsLoading
|
||||
text: loading ? Constants.dummyText : root.marketBalance
|
||||
}
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
spacing: 6
|
||||
visible: !errorIcon.visible && root.marketDetailsAvailable
|
||||
|
||||
StatusTextWithLoadingState {
|
||||
id: change24HourPercentageText
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
customColor: d.textColor
|
||||
font.pixelSize: 13
|
||||
loading: root.marketDetailsLoading
|
||||
|
||||
text: qsTr("%1 %2%", "[up/down/none character depending on value sign] [localized percentage value]%")
|
||||
.arg(d.upDownTriangle).arg(LocaleUtils.numberToLocaleString(root.marketChangePct24hour, 2))
|
||||
}
|
||||
Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 1
|
||||
height: 12
|
||||
color: Theme.palette.directColor9
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
id: currencyPrice
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
customColor: d.textColor
|
||||
font.pixelSize: 13
|
||||
loading: root.marketDetailsLoading
|
||||
text: loading ? Constants.dummyText : root.marketCurrencyPrice
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: d.isCommunityToken
|
||||
|
||||
sourceComponent: ManageTokensCommunityTag {
|
||||
anchors.right: parent.right
|
||||
|
||||
communityImage: root.communityIcon
|
||||
communityName: root.communityName
|
||||
communityId: root.communityId
|
||||
|
||||
asset.letterSize: 12
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onSingleTapped: root.communityClicked(root.communityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
states: State {
|
||||
name: "unknownToken"
|
||||
when: !root.icon.toString()
|
||||
|
||||
PropertyChanges {
|
||||
target: root.asset
|
||||
isLetterIdenticon: true
|
||||
color: Theme.palette.miscColor5
|
||||
name: root.name
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@ InformationTag 1.0 InformationTag.qml
|
|||
InformationTile 1.0 InformationTile.qml
|
||||
Input 1.0 Input.qml
|
||||
LoadingTokenDelegate 1.0 LoadingTokenDelegate.qml
|
||||
LoadingTokenDelegateNew 1.0 LoadingTokenDelegateNew.qml
|
||||
LinkPreviewDebugView 1.0 LinkPreviewDebugView.qml
|
||||
ProfilePerspectiveSelector 1.0 ProfilePerspectiveSelector.qml
|
||||
RadioButtonSelector 1.0 RadioButtonSelector.qml
|
||||
|
@ -44,7 +43,6 @@ StyledTextEditWithLoadingState 1.0 StyledTextEditWithLoadingState.qml
|
|||
StyledTextField 1.0 StyledTextField.qml
|
||||
Timer 1.0 Timer.qml
|
||||
TokenDelegate 1.0 TokenDelegate.qml
|
||||
TokenDelegateNew 1.0 TokenDelegateNew.qml
|
||||
TransactionAddress 1.0 TransactionAddress.qml
|
||||
TransactionAddressTile 1.0 TransactionAddressTile.qml
|
||||
TransactionDataTile 1.0 TransactionDataTile.qml
|
||||
|
|
|
@ -1,197 +1,147 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import Qt.labs.settings 1.1
|
||||
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Models 0.1
|
||||
import StatusQ.Internal 0.1
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.popups 1.0
|
||||
import utils 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import shared.stores 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.popups 1.0
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
|
||||
ColumnLayout {
|
||||
Control {
|
||||
id: root
|
||||
|
||||
// expected roles: name, symbol, balances, currencyPrice, changePct24hour, communityId, communityName, communityImage
|
||||
required property var controller
|
||||
/**
|
||||
Expected model structure:
|
||||
|
||||
property var currencyStore
|
||||
property var networkConnectionStore
|
||||
required property var tokensStore
|
||||
property var overview
|
||||
property bool assetDetailsLaunched: false
|
||||
property bool filterVisible
|
||||
property bool areAssetsLoading: false
|
||||
property string addressFilters
|
||||
property string networkFilters
|
||||
key [string] - unique identifier of a token, e.g "0x3234235"
|
||||
symbol [string] - token's symbol e.g. "ETH" or "SNT"
|
||||
name [string] - token's name e.g. "Ether" or "Dai"
|
||||
icon [url] - token's icon url
|
||||
balance [double] - tokens balance is the commonly used unit, e.g. 1.2 for 1.2 ETH, used
|
||||
for sorting and computing market value
|
||||
balanceText [string] - formatted and localized balance. This is not done internally because
|
||||
it may depend on many external factors
|
||||
error [string] - error message related to balance
|
||||
|
||||
signal assetClicked(var token)
|
||||
signal sendRequested(string symbol)
|
||||
signal receiveRequested(string symbol)
|
||||
signal launchSwapModal(string tokensKey)
|
||||
signal switchToCommunityRequested(string communityId)
|
||||
signal manageTokensRequested()
|
||||
marketDetailsAvailable [bool] - specifies if market datails are available for given token
|
||||
marketDetailsLoading [bool] - specifies if market datails are available for given token
|
||||
marketPrice [double] - specifies market price in currently used currency
|
||||
marketChangePct24hour [double] - percentage price change in last 24 hours, e.g. 0.5 for 0.5% of price change
|
||||
|
||||
spacing: 0
|
||||
communityId [string] - for community assets, unique identifier of a community, e.g. "0x6734235"
|
||||
communityName [string] - for community assets, name of a community e.g. "Crypto Kitties"
|
||||
communityIcon [url] - for community assets, community's icon url
|
||||
|
||||
position [int] - if custom order available, display position defined by the user via token management
|
||||
canBeHidden [bool] - specifies if given token can be hidden (e.g. ETH should be always visible)
|
||||
**/
|
||||
property var model
|
||||
|
||||
// enables global loading state useful when real data are not yet available
|
||||
property bool loading
|
||||
|
||||
// shows/hides list sorter
|
||||
property bool sorterVisible
|
||||
|
||||
// allows/disables choosing custom sort order from a sorter
|
||||
property bool customOrderAvailable
|
||||
|
||||
// switches configuring right click menu
|
||||
property bool sendEnabled: true
|
||||
property bool swapEnabled: true
|
||||
property bool swapVisible: true
|
||||
|
||||
property string balanceError
|
||||
|
||||
// global market data error, presented for all tokens expecting market data
|
||||
property string marketDataError
|
||||
|
||||
// formatting function for fiat currency values
|
||||
property var formatFiat: balance => `${balance.toLocaleString(Qt.locale())} XYZ`
|
||||
|
||||
signal sendRequested(string key)
|
||||
signal receiveRequested(string key)
|
||||
signal swapRequested(string key)
|
||||
signal assetClicked(string key)
|
||||
signal communityClicked(string communityKey)
|
||||
signal hideRequested(string key)
|
||||
signal hideCommunityAssets(string communityKey)
|
||||
signal manageTokensRequested
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int selectedAssetIndex: -1
|
||||
|
||||
readonly property int loadingItemsCount: 25
|
||||
|
||||
readonly property bool isCustomView: cmbTokenOrder.currentValue === SortOrderComboBox.TokenOrderCustom
|
||||
|
||||
function tokenIsVisible(symbol, currentCurrencyBalance, isCommunityAsset) {
|
||||
// NOTE Backend returns ETH, SNT, STT and DAI by default
|
||||
if (!root.controller.filterAcceptsSymbol(symbol)) // explicitely hidden
|
||||
return false
|
||||
if (isCommunityAsset)
|
||||
return true
|
||||
// Received tokens can have 0 balance, which indicate previously owned token
|
||||
if (root.tokensStore.displayAssetsBelowBalance) {
|
||||
const threshold = root.tokensStore.getDisplayAssetsBelowBalanceThresholdDisplayAmount()
|
||||
if (threshold > 0)
|
||||
return currentCurrencyBalance > threshold
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function getTotalBalance(balances, decimals, key) {
|
||||
let totalBalance = 0
|
||||
let nwFilters = root.networkFilters.split(":")
|
||||
let addrFilters = root.addressFilters.split(":")
|
||||
for(let i=0; i<balances.count; i++) {
|
||||
let balancePerAddressPerChain = SQUtils.ModelUtils.get(balances, i)
|
||||
if (nwFilters.includes(balancePerAddressPerChain.chainId+"") &&
|
||||
addrFilters.includes(balancePerAddressPerChain.account)) {
|
||||
totalBalance+=SQUtils.AmountsArithmetic.toNumber(balancePerAddressPerChain[key], decimals)
|
||||
}
|
||||
}
|
||||
return totalBalance
|
||||
}
|
||||
SortFilterProxyModel {
|
||||
id: sfpm
|
||||
|
||||
sourceModel: root.model ?? null
|
||||
|
||||
property SortFilterProxyModel customSFPM: SortFilterProxyModel {
|
||||
sourceModel: root.controller.sourceModel
|
||||
proxyRoles: [
|
||||
// helper role for rendering section delegate
|
||||
FastExpressionRole {
|
||||
name: "currentBalance"
|
||||
expression: d.getTotalBalance(model.balances, model.decimals, "balance")
|
||||
expectedRoles: ["balances", "decimals"]
|
||||
name: "isCommunity"
|
||||
expression: !!communityId ? "community" : ""
|
||||
expectedRoles: ["communityId"]
|
||||
},
|
||||
FastExpressionRole {
|
||||
name: "currentCurrencyBalance"
|
||||
expression: {
|
||||
if(!model.communityId) {
|
||||
if (!!model.marketDetails) {
|
||||
return model.currentBalance * model.marketDetails.currencyPrice.amount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return model.currentBalance
|
||||
}
|
||||
expectedRoles: ["marketDetails", "communityId", "currentBalance"]
|
||||
},
|
||||
FastExpressionRole {
|
||||
name: "tokenPrice"
|
||||
expression: model.marketDetails.currencyPrice.amount
|
||||
expectedRoles: ["marketDetails"]
|
||||
name: "marketBalance"
|
||||
expression: balance * marketPrice
|
||||
expectedRoles: ["balance", "marketPrice"]
|
||||
},
|
||||
FastExpressionRole {
|
||||
name: "change1DayFiat"
|
||||
expression: {
|
||||
if (!model.isCommunityAsset && !!model.marketDetails) {
|
||||
const balance1DayAgo = d.getTotalBalance(model.balances, model.decimals, "balance1DayAgo")
|
||||
const change = (model.currentBalance * model.marketDetails.currencyPrice.amount) - (balance1DayAgo * (model.marketDetails.currencyPrice.amount - model.marketDetails.change24hour))
|
||||
return change
|
||||
}
|
||||
return 0
|
||||
}
|
||||
expectedRoles: ["marketDetails", "balances", "decimals", "currentBalance", "isCommunityAsset"]
|
||||
},
|
||||
FastExpressionRole {
|
||||
name: "isCommunityAsset"
|
||||
expression: !!model.communityId
|
||||
expectedRoles: ["communityId"]
|
||||
}
|
||||
]
|
||||
filters: [
|
||||
FastExpressionFilter {
|
||||
expression: {
|
||||
root.controller.revision
|
||||
root.tokensStore.displayAssetsBelowBalance
|
||||
return d.tokenIsVisible(model.symbol, model.currentCurrencyBalance, model.isCommunityAsset)
|
||||
}
|
||||
expectedRoles: ["symbol", "currentCurrencyBalance", "isCommunityAsset"]
|
||||
expression: marketBalance * (1 - (1 / (marketChangePct24hour / 100 + 1)))
|
||||
expectedRoles: ["marketBalance", "marketChangePct24hour"]
|
||||
}
|
||||
]
|
||||
|
||||
sorters: [
|
||||
RoleSorter {
|
||||
roleName: "isCommunityAsset"
|
||||
},
|
||||
FastExpressionSorter {
|
||||
expression: {
|
||||
root.controller.revision
|
||||
return root.controller.compareTokens(modelLeft.symbol, modelRight.symbol)
|
||||
}
|
||||
enabled: d.isCustomView
|
||||
expectedRoles: ["symbol"]
|
||||
roleName: "isCommunity"
|
||||
},
|
||||
RoleSorter {
|
||||
roleName: cmbTokenOrder.currentSortRoleName
|
||||
sortOrder: cmbTokenOrder.currentSortOrder
|
||||
enabled: !d.isCustomView
|
||||
roleName: sortOrderComboBox.currentSortRoleName
|
||||
sortOrder: sortOrderComboBox.currentSortOrder
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
category: "AssetsViewSortSettings"
|
||||
property int currentSortValue: SortOrderComboBox.TokenOrderCurrencyBalance
|
||||
property alias currentSortOrder: cmbTokenOrder.currentSortOrder
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
settings.sync()
|
||||
cmbTokenOrder.currentIndex = cmbTokenOrder.indexOfValue(settings.currentSortValue)
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
settings.currentSortValue = cmbTokenOrder.currentValue
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.filterVisible ? implicitHeight : 0
|
||||
Layout.fillHeight: false
|
||||
Layout.preferredHeight: root.sorterVisible ? implicitHeight : 0
|
||||
|
||||
opacity: root.sorterVisible ? 1 : 0
|
||||
spacing: 20
|
||||
opacity: root.filterVisible ? 1 : 0
|
||||
visible: opacity > 0
|
||||
|
||||
Behavior on Layout.preferredHeight { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
|
||||
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
|
||||
|
||||
StatusDialogDivider {
|
||||
Layout.fillWidth: true
|
||||
Behavior on Layout.preferredHeight {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
StatusDialogDivider { Layout.fillWidth: true }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: false
|
||||
|
||||
spacing: Style.current.halfPadding
|
||||
|
||||
StatusBaseText {
|
||||
|
@ -201,18 +151,28 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
SortOrderComboBox {
|
||||
id: cmbTokenOrder
|
||||
id: sortOrderComboBox
|
||||
|
||||
objectName: "cmbTokenOrder"
|
||||
hasCustomOrderDefined: root.controller.hasSettings
|
||||
hasCustomOrderDefined: root.customOrderAvailable
|
||||
|
||||
model: [
|
||||
{ value: SortOrderComboBox.TokenOrderCurrencyBalance, text: qsTr("Asset balance value"), icon: "", sortRoleName: "currentCurrencyBalance" }, // custom SFPM ExpressionRole on "enabledNetworkCurrencyBalance" amount
|
||||
{ value: SortOrderComboBox.TokenOrderBalance, text: qsTr("Asset balance"), icon: "", sortRoleName: "currentBalance" }, // custom SFPM ExpressionRole on "enabledNetworkBalance" amount
|
||||
{ value: SortOrderComboBox.TokenOrderCurrencyPrice, text: qsTr("Asset value"), icon: "", sortRoleName: "tokenPrice" }, // custom SFPM ExpressionRole on "currencyPrice" amount
|
||||
{ value: SortOrderComboBox.TokenOrder1DChange, text: qsTr("1d change: balance value"), icon: "", sortRoleName: "change1DayFiat" }, // custom SFPM ExpressionRole
|
||||
{ value: SortOrderComboBox.TokenOrderAlpha, text: qsTr("Asset name"), icon: "", sortRoleName: "name" },
|
||||
{ value: SortOrderComboBox.TokenOrderCustom, text: qsTr("Custom order"), icon: "", sortRoleName: "" },
|
||||
{ value: SortOrderComboBox.TokenOrderNone, text: "---", icon: "", sortRoleName: "" }, // separator
|
||||
{ value: SortOrderComboBox.TokenOrderCreateCustom, text: hasCustomOrderDefined ? qsTr("Edit custom order →") : qsTr("Create custom order →"),
|
||||
{ value: SortOrderComboBox.TokenOrderCurrencyBalance,
|
||||
text: qsTr("Asset balance value"), icon: "", sortRoleName: "marketBalance" },
|
||||
{ value: SortOrderComboBox.TokenOrderBalance,
|
||||
text: qsTr("Asset balance"), icon: "", sortRoleName: "balance" },
|
||||
{ value: SortOrderComboBox.TokenOrderCurrencyPrice,
|
||||
text: qsTr("Asset value"), icon: "", sortRoleName: "marketPrice" },
|
||||
{ value: SortOrderComboBox.TokenOrder1DChange,
|
||||
text: qsTr("1d change: balance value"), icon: "", sortRoleName: "change1DayFiat" },
|
||||
{ value: SortOrderComboBox.TokenOrderAlpha,
|
||||
text: qsTr("Asset name"), icon: "", sortRoleName: "name" },
|
||||
{ value: SortOrderComboBox.TokenOrderCustom,
|
||||
text: qsTr("Custom order"), icon: "", sortRoleName: "position" },
|
||||
{ value: SortOrderComboBox.TokenOrderNone,
|
||||
text: "---", icon: "", sortRoleName: "" }, // separator
|
||||
{ value: SortOrderComboBox.TokenOrderCreateCustom,
|
||||
text: hasCustomOrderDefined ? qsTr("Edit custom order →") : qsTr("Create custom order →"),
|
||||
icon: "", sortRoleName: "" }
|
||||
]
|
||||
onCreateOrEditRequested: {
|
||||
|
@ -221,95 +181,78 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
StatusDialogDivider {
|
||||
Layout.fillWidth: true
|
||||
StatusDialogDivider { Layout.fillWidth: true }
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: regularModel
|
||||
|
||||
model: sfpm
|
||||
|
||||
delegate: TokenDelegate {
|
||||
objectName: `AssetView_TokenListItem_${model.symbol}`
|
||||
|
||||
width: ListView.view.width
|
||||
|
||||
name: model.name
|
||||
icon: model.icon
|
||||
balance: model.balanceText
|
||||
marketBalance: root.formatFiat(model.marketBalance)
|
||||
|
||||
marketDetailsAvailable: model.marketDetailsAvailable
|
||||
marketDetailsLoading: model.marketDetailsLoading
|
||||
marketCurrencyPrice: root.formatFiat(model.change1DayFiat)
|
||||
marketChangePct24hour: model.marketChangePct24hour
|
||||
|
||||
communityId: model.communityId
|
||||
communityName: model.communityName ?? ""
|
||||
communityIcon: model.communityIcon ?? ""
|
||||
|
||||
errorTooltipText_1: model.error
|
||||
errorTooltipText_2: root.marketDataError
|
||||
|
||||
errorMode: !!root.balanceError
|
||||
errorIcon.tooltip.text: root.balanceError
|
||||
|
||||
onClicked: {
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
root.assetClicked(model.key)
|
||||
else if (mouse.button === Qt.RightButton)
|
||||
tokenContextMenu.createObject(this, { model }).popup(mouse)
|
||||
}
|
||||
|
||||
onCommunityClicked: root.communityClicked(model.communityId)
|
||||
}
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: loadingModel
|
||||
|
||||
model: d.loadingItemsCount
|
||||
|
||||
delegate: LoadingTokenDelegate {
|
||||
objectName: `AssetView_LoadingTokenDelegate_${model.index}`
|
||||
|
||||
width: ListView.view.width
|
||||
}
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
id: assetsListView
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.padding
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.fillHeight: true
|
||||
objectName: "assetViewStatusListView"
|
||||
model: root.areAssetsLoading ? d.loadingItemsCount : d.customSFPM
|
||||
delegate: delegateLoader
|
||||
section {
|
||||
property: "isCommunityAsset"
|
||||
delegate: Loader {
|
||||
width: ListView.view.width
|
||||
required property string section
|
||||
sourceComponent: section === "true" ? sectionDelegate : null
|
||||
}
|
||||
}
|
||||
}
|
||||
id: listView
|
||||
|
||||
Component {
|
||||
id: sectionDelegate
|
||||
AssetsSectionDelegate {
|
||||
objectName: "assetViewStatusListView"
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
model: root.loading ? loadingModel : regularModel
|
||||
|
||||
section {
|
||||
property: "isCommunity"
|
||||
delegate: AssetsSectionDelegate {
|
||||
width: parent.width
|
||||
text: qsTr("Community minted")
|
||||
onInfoButtonClicked: Global.openPopup(communityInfoPopupCmp)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: delegateLoader
|
||||
Loader {
|
||||
property var modelData: model
|
||||
property int delegateIndex: index
|
||||
width: ListView.view.width
|
||||
sourceComponent: root.areAssetsLoading ? loadingTokenDelegate : tokenDelegate
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loadingTokenDelegate
|
||||
LoadingTokenDelegate {
|
||||
objectName: "AssetView_LoadingTokenDelegate_" + delegateIndex
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: tokenDelegate
|
||||
TokenDelegate {
|
||||
objectName: "AssetView_TokenListItem_" + (!!modelData ? modelData.symbol : "")
|
||||
readonly property string balance: !!modelData && !!modelData.currentBalance ? "%1".arg(modelData.currentBalance) : "" // Needed for the tests
|
||||
errorTooltipText_1: !!modelData && !!networkConnectionStore ? networkConnectionStore.getBlockchainNetworkDownTextForToken(modelData.balances) : ""
|
||||
errorTooltipText_2: !!networkConnectionStore ? networkConnectionStore.getMarketNetworkDownText() : ""
|
||||
subTitle: {
|
||||
if (!modelData || !modelData.symbol) {
|
||||
return ""
|
||||
}
|
||||
if (networkConnectionStore && networkConnectionStore.noTokenBalanceAvailable) {
|
||||
return ""
|
||||
}
|
||||
return LocaleUtils.currencyAmountToLocaleString(root.currencyStore.getCurrencyAmount(modelData.currentBalance, modelData.symbol))
|
||||
}
|
||||
currencyBalance.text: {
|
||||
let totalCurrencyBalance = modelData && modelData.currentCurrencyBalance ? modelData.currentCurrencyBalance : 0
|
||||
return currencyStore.formatCurrencyAmount(totalCurrencyBalance, currencyStore.currentCurrency)
|
||||
}
|
||||
errorMode: !!networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCache && !networkConnectionStore.noMarketConnectionAndNoCache : false
|
||||
errorIcon.tooltip.text: !!networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCacheText : ""
|
||||
onClicked: (itemId, mouse) => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
RootStore.getHistoricalDataForToken(modelData.symbol, root.currencyStore.currentCurrency)
|
||||
d.selectedAssetIndex = delegateIndex
|
||||
assetClicked(assetsListView.model.get(delegateIndex))
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
Global.openMenu(tokenContextMenu, this,
|
||||
{symbol: modelData.symbol, assetName: modelData.name, assetImage: symbolUrl,
|
||||
communityId: modelData.communityId, communityName: modelData.communityName,
|
||||
communityImage: modelData.communityImage, tokensKey: modelData.tokensKey})
|
||||
}
|
||||
}
|
||||
onSwitchToCommunityRequested: root.switchToCommunityRequested(communityId)
|
||||
Component.onCompleted: {
|
||||
// on Model reset if the detail view is shown, update the data in background.
|
||||
if(root.assetDetailsLaunched && delegateIndex === d.selectedAssetIndex) {
|
||||
assetClicked(assetsListView.model.get(delegateIndex))
|
||||
onInfoButtonClicked: communityInfoPopup.createObject(this).open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,92 +260,73 @@ ColumnLayout {
|
|||
|
||||
Component {
|
||||
id: tokenContextMenu
|
||||
StatusMenu {
|
||||
|
||||
AssetContextMenu {
|
||||
required property var model
|
||||
|
||||
readonly property string key: model.key
|
||||
readonly property string communityKey: model.communityId
|
||||
|
||||
onClosed: destroy()
|
||||
|
||||
property string tokensKey
|
||||
property string symbol
|
||||
property string assetName
|
||||
property string assetImage
|
||||
property string communityId
|
||||
property string communityName
|
||||
property string communityImage
|
||||
sendEnabled: root.sendEnabled
|
||||
swapEnabled: root.swapEnabled
|
||||
swapVisible: root.swapVisible
|
||||
hideVisible: model.canBeHidden
|
||||
communityHideVisible: !!model.isCommunity
|
||||
|
||||
StatusAction {
|
||||
enabled: root.networkConnectionStore.sendBuyBridgeEnabled && !root.overview.isWatchOnlyAccount && root.overview.canSend
|
||||
visibleOnDisabled: true
|
||||
icon.name: "send"
|
||||
text: qsTr("Send")
|
||||
onTriggered: root.sendRequested(symbol)
|
||||
}
|
||||
StatusAction {
|
||||
icon.name: "receive"
|
||||
text: qsTr("Receive")
|
||||
onTriggered: root.receiveRequested(symbol)
|
||||
}
|
||||
StatusAction {
|
||||
icon.name: "swap"
|
||||
text: qsTr("Swap")
|
||||
enabled: Global.featureFlags.swapEnabled && !root.overview.isWatchOnlyAccount
|
||||
visibleOnDisabled: Global.featureFlags.swapEnabled
|
||||
onTriggered: root.launchSwapModal(tokensKey)
|
||||
}
|
||||
StatusMenuSeparator {}
|
||||
StatusAction {
|
||||
icon.name: "settings"
|
||||
text: qsTr("Manage tokens")
|
||||
onTriggered: root.manageTokensRequested()
|
||||
}
|
||||
StatusAction {
|
||||
enabled: symbol !== Constants.ethToken
|
||||
type: StatusAction.Type.Danger
|
||||
icon.name: "hide"
|
||||
text: qsTr("Hide asset")
|
||||
onTriggered: Global.openConfirmHideAssetPopup(symbol, assetName, assetImage, !!communityId)
|
||||
}
|
||||
StatusAction {
|
||||
enabled: !!communityId
|
||||
type: StatusAction.Type.Danger
|
||||
icon.name: "hide"
|
||||
text: qsTr("Hide all assets from this community")
|
||||
onTriggered: Global.openPopup(confirmHideCommunityAssetsPopup, {communityId, communityName, communityImage})
|
||||
}
|
||||
onSendRequested: root.sendRequested(key)
|
||||
onReceiveRequested: root.receiveRequested(key)
|
||||
onSwapRequested: root.swapRequested(key)
|
||||
|
||||
onHideRequested:
|
||||
confirmHideAssetPopup.createObject(parent, { model }).open()
|
||||
onCommunityHideRequested:
|
||||
confirmHideCommunityAssetsPopup.createObject(parent, { model }).open()
|
||||
|
||||
onManageTokensRequested: root.manageTokensRequested()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: communityInfoPopupCmp
|
||||
CommunityAssetsInfoPopup {}
|
||||
id: communityInfoPopup
|
||||
|
||||
CommunityAssetsInfoPopup {
|
||||
destroyOnClose: true
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: confirmHideAssetPopup
|
||||
|
||||
ConfirmHideAssetPopup {
|
||||
destroyOnClose: true
|
||||
|
||||
required property var model
|
||||
|
||||
symbol: model.symbol
|
||||
name: model.name
|
||||
icon: model.icon
|
||||
|
||||
onConfirmButtonClicked: {
|
||||
root.hideRequested(model.key)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: confirmHideCommunityAssetsPopup
|
||||
ConfirmationDialog {
|
||||
property string communityId
|
||||
property string communityName
|
||||
property string communityImage
|
||||
|
||||
width: 520
|
||||
destroyOnClose: true
|
||||
confirmButtonLabel: qsTr("Hide '%1' assets").arg(communityName)
|
||||
cancelBtnType: ""
|
||||
showCancelButton: true
|
||||
headerSettings.title: qsTr("Hide %1 community assets").arg(communityName)
|
||||
headerSettings.asset.name: communityImage
|
||||
confirmationText: qsTr("Are you sure you want to hide all community assets minted by %1? You will no longer see or be able to interact with these assets anywhere inside Status.").arg(communityName)
|
||||
onCancelButtonClicked: close()
|
||||
ConfirmHideCommunityAssetsPopup {
|
||||
required property var model
|
||||
|
||||
name: model.communityName
|
||||
icon: model.communityIcon
|
||||
|
||||
onConfirmButtonClicked: {
|
||||
root.controller.showHideGroup(communityId, false)
|
||||
close()
|
||||
Global.displayToastMessage(
|
||||
qsTr("%1 community assets were successfully hidden. You can toggle asset visibility via %2.").arg(communityName)
|
||||
.arg(`<a style="text-decoration:none" href="#${Constants.appSection.profile}/${Constants.settingsSubsection.wallet}/${Constants.walletSettingsSubsection.manageAssets}">` + qsTr("Settings", "Go to Settings") + "</a>"),
|
||||
"",
|
||||
"checkmark-circle",
|
||||
false,
|
||||
Constants.ephemeralNotificationType.success,
|
||||
""
|
||||
)
|
||||
root.hideCommunityAssets(model.communityId)
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,333 +0,0 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.popups 1.0
|
||||
import utils 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
/**
|
||||
Expected model structure:
|
||||
|
||||
key [string] - unique identifier of a token, e.g "0x3234235"
|
||||
symbol [string] - token's symbol e.g. "ETH" or "SNT"
|
||||
name [string] - token's name e.g. "Ether" or "Dai"
|
||||
icon [url] - token's icon url
|
||||
balance [double] - tokens balance is the commonly used unit, e.g. 1.2 for 1.2 ETH, used
|
||||
for sorting and computing market value
|
||||
balanceText [string] - formatted and localized balance. This is not done internally because
|
||||
it may depend on many external factors
|
||||
error [string] - error message related to balance
|
||||
|
||||
marketDetailsAvailable [bool] - specifies if market datails are available for given token
|
||||
marketDetailsLoading [bool] - specifies if market datails are available for given token
|
||||
marketPrice [double] - specifies market price in currently used currency
|
||||
marketChangePct24hour [double] - percentage price change in last 24 hours, e.g. 0.5 for 0.5% of price change
|
||||
|
||||
communityId [string] - for community assets, unique identifier of a community, e.g. "0x6734235"
|
||||
communityName [string] - for community assets, name of a community e.g. "Crypto Kitties"
|
||||
communityIcon [url] - for community assets, community's icon url
|
||||
|
||||
position [int] - if custom order available, display position defined by the user via token management
|
||||
canBeHidden [bool] - specifies if given token can be hidden (e.g. ETH should be always visible)
|
||||
**/
|
||||
property var model
|
||||
|
||||
// enables global loading state useful when real data are not yet available
|
||||
property bool loading
|
||||
|
||||
// shows/hides list sorter
|
||||
property bool sorterVisible
|
||||
|
||||
// allows/disables choosing custom sort order from a sorter
|
||||
property bool customOrderAvailable
|
||||
|
||||
// switches configuring right click menu
|
||||
property bool sendEnabled: true
|
||||
property bool swapEnabled: true
|
||||
property bool swapVisible: true
|
||||
|
||||
property string balanceError
|
||||
|
||||
// global market data error, presented for all tokens expecting market data
|
||||
property string marketDataError
|
||||
|
||||
// formatting function for fiat currency values
|
||||
property var formatFiat: balance => `${balance.toLocaleString(Qt.locale())} XYZ`
|
||||
|
||||
signal sendRequested(string key)
|
||||
signal receiveRequested(string key)
|
||||
signal swapRequested(string key)
|
||||
signal assetClicked(string key)
|
||||
signal communityClicked(string communityKey)
|
||||
signal hideRequested(string key)
|
||||
signal hideCommunityAssets(string communityKey)
|
||||
signal manageTokensRequested
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int loadingItemsCount: 25
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: sfpm
|
||||
|
||||
sourceModel: root.model
|
||||
|
||||
proxyRoles: [
|
||||
// helper role for rendering section delegate
|
||||
FastExpressionRole {
|
||||
name: "isCommunity"
|
||||
expression: !!communityId ? "community" : ""
|
||||
expectedRoles: ["communityId"]
|
||||
},
|
||||
FastExpressionRole {
|
||||
name: "marketBalance"
|
||||
expression: balance * marketPrice
|
||||
expectedRoles: ["balance", "marketPrice"]
|
||||
},
|
||||
FastExpressionRole {
|
||||
name: "change1DayFiat"
|
||||
expression: marketBalance * (1 - (1 / (marketChangePct24hour / 100 + 1)))
|
||||
expectedRoles: ["marketBalance", "marketChangePct24hour"]
|
||||
}
|
||||
]
|
||||
|
||||
sorters: [
|
||||
RoleSorter {
|
||||
roleName: "isCommunity"
|
||||
},
|
||||
RoleSorter {
|
||||
roleName: sortOrderComboBox.currentSortRoleName
|
||||
sortOrder: sortOrderComboBox.currentSortOrder
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
ColumnLayout {
|
||||
Layout.fillHeight: false
|
||||
Layout.preferredHeight: root.sorterVisible ? implicitHeight : 0
|
||||
|
||||
opacity: root.sorterVisible ? 1 : 0
|
||||
spacing: 20
|
||||
visible: opacity > 0
|
||||
|
||||
Behavior on Layout.preferredHeight {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
StatusDialogDivider { Layout.fillWidth: true }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: false
|
||||
|
||||
spacing: Style.current.halfPadding
|
||||
|
||||
StatusBaseText {
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: Style.current.additionalTextSize
|
||||
text: qsTr("Sort by:")
|
||||
}
|
||||
|
||||
SortOrderComboBox {
|
||||
id: sortOrderComboBox
|
||||
|
||||
objectName: "cmbTokenOrder"
|
||||
hasCustomOrderDefined: root.customOrderAvailable
|
||||
|
||||
model: [
|
||||
{ value: SortOrderComboBox.TokenOrderCurrencyBalance,
|
||||
text: qsTr("Asset balance value"), icon: "", sortRoleName: "marketBalance" },
|
||||
{ value: SortOrderComboBox.TokenOrderBalance,
|
||||
text: qsTr("Asset balance"), icon: "", sortRoleName: "balance" },
|
||||
{ value: SortOrderComboBox.TokenOrderCurrencyPrice,
|
||||
text: qsTr("Asset value"), icon: "", sortRoleName: "marketPrice" },
|
||||
{ value: SortOrderComboBox.TokenOrder1DChange,
|
||||
text: qsTr("1d change: balance value"), icon: "", sortRoleName: "change1DayFiat" },
|
||||
{ value: SortOrderComboBox.TokenOrderAlpha,
|
||||
text: qsTr("Asset name"), icon: "", sortRoleName: "name" },
|
||||
{ value: SortOrderComboBox.TokenOrderCustom,
|
||||
text: qsTr("Custom order"), icon: "", sortRoleName: "position" },
|
||||
{ value: SortOrderComboBox.TokenOrderNone,
|
||||
text: "---", icon: "", sortRoleName: "" }, // separator
|
||||
{ value: SortOrderComboBox.TokenOrderCreateCustom,
|
||||
text: hasCustomOrderDefined ? qsTr("Edit custom order →") : qsTr("Create custom order →"),
|
||||
icon: "", sortRoleName: "" }
|
||||
]
|
||||
onCreateOrEditRequested: {
|
||||
root.manageTokensRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusDialogDivider { Layout.fillWidth: true }
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: regularModel
|
||||
|
||||
model: sfpm
|
||||
|
||||
delegate: TokenDelegateNew {
|
||||
objectName: `AssetView_TokenListItem_${model.symbol}`
|
||||
|
||||
width: ListView.view.width
|
||||
|
||||
name: model.name
|
||||
icon: model.icon
|
||||
balance: model.balanceText
|
||||
marketBalance: root.formatFiat(model.marketBalance)
|
||||
|
||||
marketDetailsAvailable: model.marketDetailsAvailable
|
||||
marketDetailsLoading: model.marketDetailsLoading
|
||||
marketCurrencyPrice: root.formatFiat(model.change1DayFiat)
|
||||
marketChangePct24hour: model.marketChangePct24hour
|
||||
|
||||
communityId: model.communityId
|
||||
communityName: model.communityName ?? ""
|
||||
communityIcon: model.communityIcon ?? ""
|
||||
|
||||
errorTooltipText_1: model.error
|
||||
errorTooltipText_2: root.marketDataError
|
||||
|
||||
errorMode: !!root.balanceError
|
||||
errorIcon.tooltip.text: root.balanceError
|
||||
|
||||
onClicked: {
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
root.assetClicked(model.key)
|
||||
else if (mouse.button === Qt.RightButton)
|
||||
tokenContextMenu.createObject(this, { model }).popup(mouse)
|
||||
}
|
||||
|
||||
onCommunityClicked: root.communityClicked(model.communityId)
|
||||
}
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: loadingModel
|
||||
|
||||
model: d.loadingItemsCount
|
||||
|
||||
delegate: LoadingTokenDelegateNew {
|
||||
objectName: `AssetView_LoadingTokenDelegate_${model.index}`
|
||||
|
||||
width: ListView.view.width
|
||||
}
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
id: listView
|
||||
|
||||
objectName: "assetViewStatusListView"
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
model: root.loading ? loadingModel : regularModel
|
||||
|
||||
section {
|
||||
property: "isCommunity"
|
||||
delegate: AssetsSectionDelegate {
|
||||
width: parent.width
|
||||
text: qsTr("Community minted")
|
||||
onInfoButtonClicked: communityInfoPopup.createObject(this).open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: tokenContextMenu
|
||||
|
||||
AssetContextMenu {
|
||||
required property var model
|
||||
|
||||
readonly property string key: model.key
|
||||
readonly property string communityKey: model.communityId
|
||||
|
||||
onClosed: destroy()
|
||||
|
||||
sendEnabled: root.sendEnabled
|
||||
swapEnabled: root.swapEnabled
|
||||
swapVisible: root.swapVisible
|
||||
hideVisible: model.canBeHidden
|
||||
communityHideVisible: !!model.isCommunity
|
||||
|
||||
onSendRequested: root.sendRequested(key)
|
||||
onReceiveRequested: root.receiveRequested(key)
|
||||
onSwapRequested: root.swapRequested(key)
|
||||
|
||||
onHideRequested:
|
||||
confirmHideAssetPopup.createObject(parent, { model }).open()
|
||||
onCommunityHideRequested:
|
||||
confirmHideCommunityAssetsPopup.createObject(parent, { model }).open()
|
||||
|
||||
onManageTokensRequested: root.manageTokensRequested()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: communityInfoPopup
|
||||
|
||||
CommunityAssetsInfoPopup {
|
||||
destroyOnClose: true
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: confirmHideAssetPopup
|
||||
|
||||
ConfirmHideAssetPopup {
|
||||
destroyOnClose: true
|
||||
|
||||
required property var model
|
||||
|
||||
symbol: model.symbol
|
||||
name: model.name
|
||||
icon: model.icon
|
||||
|
||||
onConfirmButtonClicked: {
|
||||
root.hideRequested(model.key)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: confirmHideCommunityAssetsPopup
|
||||
|
||||
ConfirmHideCommunityAssetsPopup {
|
||||
required property var model
|
||||
|
||||
name: model.communityName
|
||||
icon: model.communityIcon
|
||||
|
||||
onConfirmButtonClicked: {
|
||||
root.hideCommunityAssets(model.communityId)
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
AssetContextMenu 1.0 AssetContextMenu.qml
|
||||
AssetsView 1.0 AssetsView.qml
|
||||
AssetsViewAdaptor 1.0 AssetsViewAdaptor.qml
|
||||
AssetsViewNew 1.0 AssetsViewNew.qml
|
||||
ConfirmHideAssetPopup 1.0 ConfirmHideAssetPopup.qml
|
||||
ConfirmHideCommunityAssetsPopup 1.0 ConfirmHideCommunityAssetsPopup.qml
|
||||
EnsResolver 1.0 EnsResolver.qml
|
||||
|
|
Loading…
Reference in New Issue