fix(@desktop/wallet): Prepare send modal to display community assets
fixes #12378
This commit is contained in:
parent
6f25499380
commit
7dcc704d29
|
@ -31,8 +31,9 @@ SplitView {
|
||||||
submodelRoleName: "balances"
|
submodelRoleName: "balances"
|
||||||
delegateModel: SortFilterProxyModel {
|
delegateModel: SortFilterProxyModel {
|
||||||
sourceModel: submodel
|
sourceModel: submodel
|
||||||
filters: ExpressionFilter {
|
filters: FastExpressionFilter {
|
||||||
expression: txStore.selectedSenderAccount.address === account
|
expression: txStore.selectedSenderAccount.address === model.account
|
||||||
|
expectedRoles: ["account"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +41,9 @@ SplitView {
|
||||||
TransactionStore {
|
TransactionStore {
|
||||||
id: txStore
|
id: txStore
|
||||||
walletAssetStore: root.walletAssetStore
|
walletAssetStore: root.walletAssetStore
|
||||||
|
showCommunityAssetsInSend: showCommunityAssetsCheckBox.checked
|
||||||
|
balanceThresholdEnabled: balanceThresholdCheckbox.checked
|
||||||
|
balanceThresholdAmount: Number(balanceThresholdValue.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
@ -274,6 +278,32 @@ SplitView {
|
||||||
loader.item.open()
|
loader.item.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: showCommunityAssetsCheckBox
|
||||||
|
text: "Show community assets when sending tokens"
|
||||||
|
checked: true
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: balanceThresholdCheckbox
|
||||||
|
text: "Turn on balance threshold"
|
||||||
|
checked: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
border.width: 1
|
||||||
|
Layout.preferredWidth: 100
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
color: "lightgrey"
|
||||||
|
TextInput {
|
||||||
|
id: balanceThresholdValue
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: balanceThresholdCheckbox.checked
|
||||||
|
text: "0.10"
|
||||||
|
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,25 @@ import AppLayouts.Wallet.stores 1.0
|
||||||
|
|
||||||
import StatusQ.Core.Utils 0.1
|
import StatusQ.Core.Utils 0.1
|
||||||
|
|
||||||
|
import shared.stores 1.0
|
||||||
|
import shared.stores.send 1.0
|
||||||
|
|
||||||
SplitView {
|
SplitView {
|
||||||
|
id: root
|
||||||
|
|
||||||
orientation: Qt.Vertical
|
orientation: Qt.Vertical
|
||||||
|
|
||||||
readonly property WalletAssetsStore walletAssetStore: WalletAssetsStore {
|
readonly property WalletAssetsStore walletAssetStore: WalletAssetsStore {
|
||||||
assetsWithFilteredBalances: groupedAccountsAssetsModel
|
assetsWithFilteredBalances: groupedAccountsAssetsModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransactionStore {
|
||||||
|
id: txStore
|
||||||
|
walletAssetStore: root.walletAssetStore
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property CurrenciesStore currencyStore: CurrenciesStore {}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
SplitView.fillHeight: true
|
SplitView.fillHeight: true
|
||||||
|
@ -31,26 +43,16 @@ SplitView {
|
||||||
|
|
||||||
width: 400
|
width: 400
|
||||||
|
|
||||||
assets: walletAssetStore.groupedAccountAssetsModel
|
assets: txStore.processedAssetsModel
|
||||||
collectibles: WalletNestedCollectiblesModel {}
|
collectibles: WalletNestedCollectiblesModel {}
|
||||||
networksModel: NetworksModel.allNetworks
|
networksModel: NetworksModel.allNetworks
|
||||||
getCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
formatCurrentCurrencyAmount: function(balance){
|
||||||
let bigIntBalance = AmountsArithmetic.fromString(balance)
|
return currencyStore.formatCurrencyAmount(balance, "USD")
|
||||||
let balance123 = AmountsArithmetic.toNumber(bigIntBalance, decimals)
|
|
||||||
return ({
|
|
||||||
amount: balance123,
|
|
||||||
symbol: symbol,
|
|
||||||
displayDecimals: 2,
|
|
||||||
stripTrailingZeroes: false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
getCurrentCurrencyAmount: function(balance){
|
formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
||||||
return ({
|
let bigIntBalance = AmountsArithmetic.fromString(balance)
|
||||||
amount: balance,
|
let decimalBalance = AmountsArithmetic.toNumber(bigIntBalance, decimals)
|
||||||
symbol: "USD",
|
return currencyStore.formatCurrencyAmount(decimalBalance, symbol)
|
||||||
displayDecimals: 2,
|
|
||||||
stripTrailingZeroes: false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ ListModel {
|
||||||
addressPerChain: [
|
addressPerChain: [
|
||||||
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271e0f"}
|
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271e0f"}
|
||||||
],
|
],
|
||||||
decimals: 18,
|
decimals: 0,
|
||||||
type: 1,
|
type: 1,
|
||||||
communityId: "ddls",
|
communityId: "ddls",
|
||||||
description: "",
|
description: "",
|
||||||
|
@ -130,7 +130,7 @@ ListModel {
|
||||||
addressPerChain: [
|
addressPerChain: [
|
||||||
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271p0f"}
|
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271p0f"}
|
||||||
],
|
],
|
||||||
decimals: 18,
|
decimals: 0,
|
||||||
type: 1,
|
type: 1,
|
||||||
communityId: "sox",
|
communityId: "sox",
|
||||||
description: "",
|
description: "",
|
||||||
|
@ -156,7 +156,7 @@ ListModel {
|
||||||
addressPerChain: [
|
addressPerChain: [
|
||||||
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271d0f"}
|
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271d0f"}
|
||||||
],
|
],
|
||||||
decimals: 18,
|
decimals: 0,
|
||||||
type: 1,
|
type: 1,
|
||||||
communityId: "ddls",
|
communityId: "ddls",
|
||||||
description: "",
|
description: "",
|
||||||
|
@ -182,7 +182,7 @@ ListModel {
|
||||||
addressPerChain: [
|
addressPerChain: [
|
||||||
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271a0f"}
|
{ chainId: 420, address: "0x6b175474e89094c44da98b954eedeac495271a0f"}
|
||||||
],
|
],
|
||||||
decimals: 18,
|
decimals: 0,
|
||||||
type: 1,
|
type: 1,
|
||||||
communityId: "ast",
|
communityId: "ast",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
@ -7,7 +9,11 @@ QtObject {
|
||||||
property string currentCurrencySymbol: "$"
|
property string currentCurrencySymbol: "$"
|
||||||
|
|
||||||
function formatCurrencyAmount(amount, symbol, options = null, locale = null) {
|
function formatCurrencyAmount(amount, symbol, options = null, locale = null) {
|
||||||
return amount
|
if (isNaN(amount)) {
|
||||||
|
return "N/A"
|
||||||
|
}
|
||||||
|
var currencyAmount = getCurrencyAmount(amount, symbol)
|
||||||
|
return LocaleUtils.currencyAmountToLocaleString(currencyAmount, options, locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
||||||
|
|
|
@ -90,7 +90,7 @@ QtObject {
|
||||||
|
|
||||||
function getHolding(holdingId, holdingType) {
|
function getHolding(holdingId, holdingType) {
|
||||||
if (holdingType === Constants.TokenType.ERC20) {
|
if (holdingType === Constants.TokenType.ERC20) {
|
||||||
return getAsset(walletAssetStore.groupedAccountAssetsModel, holdingId)
|
return getAsset(processedAssetsModel, holdingId)
|
||||||
} else if (holdingType === Constants.TokenType.ERC721) {
|
} else if (holdingType === Constants.TokenType.ERC721) {
|
||||||
return getCollectible(holdingId)
|
return getCollectible(holdingId)
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,7 +100,7 @@ QtObject {
|
||||||
|
|
||||||
function getSelectorHolding(holdingId, holdingType) {
|
function getSelectorHolding(holdingId, holdingType) {
|
||||||
if (holdingType === Constants.TokenType.ERC20) {
|
if (holdingType === Constants.TokenType.ERC20) {
|
||||||
return getAsset(walletAssetStore.groupedAccountAssetsModel, holdingId)
|
return getAsset(processedAssetsModel, holdingId)
|
||||||
} else if (holdingType === Constants.TokenType.ERC721) {
|
} else if (holdingType === Constants.TokenType.ERC721) {
|
||||||
return getSelectorCollectible(holdingId)
|
return getSelectorCollectible(holdingId)
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,14 +255,96 @@ QtObject {
|
||||||
return SQUtils.ModelUtils.getByKey(NetworksModel.allNetworks, "chainId", chainId, "chainName")
|
return SQUtils.ModelUtils.getByKey(NetworksModel.allNetworks, "chainId", chainId, "chainName")
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrencyAmountFromBigInt(balance, symbol, decimals) {
|
function formatCurrencyAmountFromBigInt(balance, symbol, decimals) {
|
||||||
let bigIntBalance = SQUtils.AmountsArithmetic.fromString(balance)
|
let bigIntBalance = SQUtils.AmountsArithmetic.fromString(balance)
|
||||||
let balance123 = SQUtils.AmountsArithmetic.toNumber(bigIntBalance, decimals)
|
let decimalBalance = SQUtils.AmountsArithmetic.toNumber(bigIntBalance, decimals)
|
||||||
return currencyStore.getCurrencyAmount(balance123, symbol)
|
return currencyStore.formatCurrencyAmount(decimalBalance, symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentCurrencyAmount(balance) {
|
// Property and methods below are used to apply advanced token management settings to the SendModal
|
||||||
return currencyStore.getCurrencyAmount(balance, currencyStore.currentCurrency)
|
property bool showCommunityAssetsInSend: true
|
||||||
|
property bool balanceThresholdEnabled: true
|
||||||
|
property real balanceThresholdAmount
|
||||||
|
|
||||||
|
// Property set from TokenLIstView and HoldingSelector to search token by name, symbol or contract address
|
||||||
|
property string assetSearchString
|
||||||
|
|
||||||
|
// Model prepared to provide filtered and sorted assets as per the advanced Settings in token management
|
||||||
|
property var processedAssetsModel: SortFilterProxyModel {
|
||||||
|
sourceModel: walletAssetStore.groupedAccountAssetsModel
|
||||||
|
proxyRoles: [
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "isCommunityAsset"
|
||||||
|
expression: !!model.communityId
|
||||||
|
expectedRoles: ["communityId"]
|
||||||
|
},
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "currentBalance"
|
||||||
|
expression: __getTotalBalance(model.balances, model.decimals, model.symbol, root.selectedSenderAccount)
|
||||||
|
expectedRoles: ["balances", "decimals", "symbol"]
|
||||||
|
},
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "currentCurrencyBalance"
|
||||||
|
expression: {
|
||||||
|
if (!!model.marketDetails) {
|
||||||
|
return model.currentBalance * model.marketDetails.currencyPrice.amount
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
expectedRoles: ["marketDetails", "currentBalance"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
filters: [
|
||||||
|
FastExpressionFilter {
|
||||||
|
function search(symbol, name, addressPerChain, searchString) {
|
||||||
|
return (
|
||||||
|
symbol.startsWith(searchString.toUpperCase()) ||
|
||||||
|
name.toUpperCase().startsWith(searchString.toUpperCase()) || __searchAddressInList(addressPerChain, searchString)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
expression: search(symbol, name, addressPerChain, root.assetSearchString)
|
||||||
|
expectedRoles: ["symbol", "name", "addressPerChain"]
|
||||||
|
},
|
||||||
|
ValueFilter {
|
||||||
|
roleName: "isCommunityAsset"
|
||||||
|
value: false
|
||||||
|
enabled: !showCommunityAssetsInSend
|
||||||
|
},
|
||||||
|
FastExpressionFilter {
|
||||||
|
expression: {
|
||||||
|
if (model.isCommunityAsset)
|
||||||
|
return true
|
||||||
|
return model.currentCurrencyBalance > balanceThresholdAmount
|
||||||
|
}
|
||||||
|
expectedRoles: ["isCommunityAsset", "currentCurrencyBalance"]
|
||||||
|
enabled: balanceThresholdEnabled
|
||||||
|
}
|
||||||
|
]
|
||||||
|
sorters: RoleSorter {
|
||||||
|
roleName: "isCommunityAsset"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Internal function to search token address */
|
||||||
|
function __searchAddressInList(addressPerChain, searchString) {
|
||||||
|
let addressFound = false
|
||||||
|
let tokenAddresses = SQUtils.ModelUtils.modelToFlatArray(addressPerChain, "address")
|
||||||
|
for (let i =0; i< tokenAddresses.length; i++){
|
||||||
|
if(tokenAddresses[i].toUpperCase().startsWith(searchString.toUpperCase())) {
|
||||||
|
addressFound = true
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addressFound
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal function to calculate total balance */
|
||||||
|
function __getTotalBalance(balances, decimals, symbol) {
|
||||||
|
let totalBalance = 0
|
||||||
|
for(let i=0; i<balances.count; i++) {
|
||||||
|
let balancePerAddressPerChain = SQUtils.ModelUtils.get(balances, i)
|
||||||
|
totalBalance+=SQUtils.AmountsArithmetic.toNumber(balancePerAddressPerChain.balance, decimals)
|
||||||
|
}
|
||||||
|
return totalBalance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ Item {
|
||||||
property alias count: comboBox.count
|
property alias count: comboBox.count
|
||||||
property alias delegate: comboBox.delegate
|
property alias delegate: comboBox.delegate
|
||||||
property alias contentItem: comboBox.contentItem
|
property alias contentItem: comboBox.contentItem
|
||||||
|
property alias comboBoxListViewSection: listView.section
|
||||||
|
|
||||||
property alias currentIndex: comboBox.currentIndex
|
property alias currentIndex: comboBox.currentIndex
|
||||||
property alias currentValue: comboBox.currentValue
|
property alias currentValue: comboBox.currentValue
|
||||||
|
|
|
@ -98,4 +98,9 @@ QtObject {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Property and methods below are used to apply advanced token management settings to the SendModal
|
||||||
|
readonly property bool showCommunityAssetsInSend: root._allTokensModule.showCommunityAssetWhenSendingTokens
|
||||||
|
readonly property bool balanceThresholdEnabled: root._allTokensModule.displayAssetsBelowBalance
|
||||||
|
readonly property real balanceThresholdAmount: root._allTokensModule.displayAssetsBelowBalanceThreshold
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,8 @@ Item {
|
||||||
primaryText: token && token.name ? token.name : Constants.dummyText
|
primaryText: token && token.name ? token.name : Constants.dummyText
|
||||||
secondaryText: token ? LocaleUtils.currencyAmountToLocaleString(root.currencyStore.getCurrencyAmount(token.currentBalance, token.symbol)) : Constants.dummyText
|
secondaryText: token ? LocaleUtils.currencyAmountToLocaleString(root.currencyStore.getCurrencyAmount(token.currentBalance, token.symbol)) : Constants.dummyText
|
||||||
tertiaryText: {
|
tertiaryText: {
|
||||||
let totalCurrencyBalance = token && token.currentCurrencyBalance ? token.currentCurrencyBalance : 0
|
let totalCurrencyBalance = token && token.currentCurrencyBalance && token.symbol ? token.currentCurrencyBalance : 0
|
||||||
return LocaleUtils.currencyAmountToLocaleString(root.currencyStore.getCurrentCurrencyAmount(totalCurrencyBalance))
|
return currencyStore.formatCurrencyAmount(totalCurrencyBalance, token.symbol)
|
||||||
}
|
}
|
||||||
decimals: token && token.decimals ? token.decimals : 4
|
decimals: token && token.decimals ? token.decimals : 4
|
||||||
balances: token && token.balances ? token.balances: null
|
balances: token && token.balances ? token.balances: null
|
||||||
|
|
|
@ -73,8 +73,9 @@ Item {
|
||||||
readonly property WalletStore.TokensStore tokensStore: WalletStore.RootStore.tokensStore
|
readonly property WalletStore.TokensStore tokensStore: WalletStore.RootStore.tokensStore
|
||||||
readonly property WalletStore.WalletAssetsStore walletAssetsStore: WalletStore.RootStore.walletAssetsStore
|
readonly property WalletStore.WalletAssetsStore walletAssetsStore: WalletStore.RootStore.walletAssetsStore
|
||||||
readonly property CurrenciesStore currencyStore: CurrenciesStore{}
|
readonly property CurrenciesStore currencyStore: CurrenciesStore{}
|
||||||
readonly property TransactionStore transactionStore: TransactionStore{
|
readonly property TransactionStore transactionStore: TransactionStore {
|
||||||
walletAssetStore: appMain.walletAssetsStore
|
walletAssetStore: appMain.walletAssetsStore
|
||||||
|
tokensStore: appMain.tokensStore
|
||||||
}
|
}
|
||||||
|
|
||||||
// set from main.qml
|
// set from main.qml
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Layouts 1.13
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Popups.Dialog 0.1
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
signal openInfoPopup()
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
StatusDialogDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.current.padding
|
||||||
|
Layout.bottomMargin: Style.current.halfPadding
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: Style.current.padding
|
||||||
|
Layout.rightMargin: Style.current.smallPadding
|
||||||
|
Layout.bottomMargin: 4
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTr("Community assets")
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
StatusFlatButton {
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
icon.name: "info"
|
||||||
|
textColor: Theme.palette.baseColor1
|
||||||
|
horizontalPadding: 0
|
||||||
|
verticalPadding: 0
|
||||||
|
onClicked: openInfoPopup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,3 +45,4 @@ TransactionDelegate 1.0 TransactionDelegate.qml
|
||||||
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
||||||
MockedKeycardReaderStateSelector 1.0 MockedKeycardReaderStateSelector.qml
|
MockedKeycardReaderStateSelector 1.0 MockedKeycardReaderStateSelector.qml
|
||||||
MockedKeycardStateSelector 1.0 MockedKeycardStateSelector.qml
|
MockedKeycardStateSelector 1.0 MockedKeycardStateSelector.qml
|
||||||
|
AssetsSectionDelegate 1.0 AssetsSectionDelegate.qml
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Popups.Dialog 0.1
|
||||||
|
|
||||||
|
StatusDialog {
|
||||||
|
destroyOnClose: true
|
||||||
|
title: qsTr("What are community assets?")
|
||||||
|
standardButtons: Dialog.Ok
|
||||||
|
width: 520
|
||||||
|
contentItem: StatusBaseText {
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text: qsTr("Community assets are assets that have been minted by a community. As these assets cannot be verified, always double check their origin and validity before interacting with them. If in doubt, ask a trusted member or admin of the relevant community.")
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,3 +26,4 @@ DeleteMessageConfirmationPopup 1.0 DeleteMessageConfirmationPopup.qml
|
||||||
UserAgreementPopup 1.0 UserAgreementPopup.qml
|
UserAgreementPopup 1.0 UserAgreementPopup.qml
|
||||||
AlertPopup 1.0 AlertPopup.qml
|
AlertPopup 1.0 AlertPopup.qml
|
||||||
ConfirmExternalLinkPopup 1.0 ConfirmExternalLinkPopup.qml
|
ConfirmExternalLinkPopup 1.0 ConfirmExternalLinkPopup.qml
|
||||||
|
CommunityAssetsInfoPopup 1.0 CommunityAssetsInfoPopup.qml
|
||||||
|
|
|
@ -77,9 +77,8 @@ StatusDialog {
|
||||||
(popup.bestRoutes && popup.bestRoutes.count === 0 &&
|
(popup.bestRoutes && popup.bestRoutes.count === 0 &&
|
||||||
!!amountToSendInput.input.text && recipientLoader.ready && !popup.isLoading) ?
|
!!amountToSendInput.input.text && recipientLoader.ready && !popup.isLoading) ?
|
||||||
Constants.NoRoute : Constants.NoError
|
Constants.NoRoute : Constants.NoError
|
||||||
readonly property double totalSelectedHoldingBalance: isSelectedHoldingValidAsset ? !d.selectedHolding.communityId ? selectedHoldingAggregator.value/(10 ** d.selectedHolding.decimals): selectedHoldingAggregator.value: 0
|
readonly property double maxFiatBalance: isSelectedHoldingValidAsset ? selectedHolding.currentCurrencyBalance : 0
|
||||||
readonly property double maxFiatBalance: isSelectedHoldingValidAsset && selectedHolding.marketDetails ? totalSelectedHoldingBalance * selectedHolding.marketDetails.currencyPrice.amount : 0
|
readonly property double maxCryptoBalance: isSelectedHoldingValidAsset ? selectedHolding.currentBalance : 0
|
||||||
readonly property double maxCryptoBalance: isSelectedHoldingValidAsset ? totalSelectedHoldingBalance : 0
|
|
||||||
readonly property double maxInputBalance: amountToSendInput.inputIsFiat ? maxFiatBalance : maxCryptoBalance
|
readonly property double maxInputBalance: amountToSendInput.inputIsFiat ? maxFiatBalance : maxCryptoBalance
|
||||||
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? currencyStore.currentCurrency : store.selectedAssetSymbol
|
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? currencyStore.currentCurrency : store.selectedAssetSymbol
|
||||||
readonly property bool errorMode: popup.isLoading || !recipientLoader.ready ? false : errorType !== Constants.NoError || networkSelector.errorMode || !amountToSendInput.inputNumberValid
|
readonly property bool errorMode: popup.isLoading || !recipientLoader.ready ? false : errorType !== Constants.NoError || networkSelector.errorMode || !amountToSendInput.inputNumberValid
|
||||||
|
@ -149,21 +148,6 @@ StatusDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SumAggregator {
|
|
||||||
id: selectedHoldingAggregator
|
|
||||||
model: SortFilterProxyModel {
|
|
||||||
sourceModel: d.isSelectedHoldingValidAsset ? d.selectedHolding.balances: d.isHoveredHoldingValidAsset && !!d.hoveredHolding.symbol ? d.hoveredHolding.balances: null
|
|
||||||
filters: FastExpressionFilter {
|
|
||||||
expression: {
|
|
||||||
store.selectedSenderAccount
|
|
||||||
return store.selectedSenderAccount.address === model.account
|
|
||||||
}
|
|
||||||
expectedRoles: ["account"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roleName: "balance"
|
|
||||||
}
|
|
||||||
|
|
||||||
width: 556
|
width: 556
|
||||||
|
|
||||||
padding: 0
|
padding: 0
|
||||||
|
@ -282,7 +266,7 @@ StatusDialog {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
selectedSenderAccount: store.selectedSenderAccount.address
|
selectedSenderAccount: store.selectedSenderAccount.address
|
||||||
assetsModel: popup.store.walletAssetStore.groupedAccountAssetsModel
|
assetsModel: popup.store.processedAssetsModel
|
||||||
collectiblesModel: popup.preSelectedAccount ? popup.nestedCollectiblesModel : null
|
collectiblesModel: popup.preSelectedAccount ? popup.nestedCollectiblesModel : null
|
||||||
networksModel: popup.store.allNetworksModel
|
networksModel: popup.store.allNetworksModel
|
||||||
currentCurrencySymbol: d.currencyStore.currentCurrencySymbol
|
currentCurrencySymbol: d.currencyStore.currentCurrencySymbol
|
||||||
|
@ -291,11 +275,12 @@ StatusDialog {
|
||||||
onItemSelected: {
|
onItemSelected: {
|
||||||
d.setSelectedHoldingId(holdingId, holdingType)
|
d.setSelectedHoldingId(holdingId, holdingType)
|
||||||
}
|
}
|
||||||
getCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
onSearchTextChanged: popup.store.assetSearchString = searchText
|
||||||
return store.getCurrencyAmountFromBigInt(balance, symbol, decimals)
|
formatCurrentCurrencyAmount: function(balance){
|
||||||
|
return popup.store.currencyStore.formatCurrencyAmount(balance, popup.store.currencyStore.currentCurrency)
|
||||||
}
|
}
|
||||||
getCurrentCurrencyAmount: function(balance){
|
formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
||||||
return store.getCurrentCurrencyAmount(balance)
|
return popup.store.formatCurrencyAmountFromBigInt(balance, symbol, decimals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,8 +291,7 @@ StatusDialog {
|
||||||
visible: d.isSelectedHoldingValidAsset || d.isHoveredHoldingValidAsset && !d.isERC721Transfer
|
visible: d.isSelectedHoldingValidAsset || d.isHoveredHoldingValidAsset && !d.isERC721Transfer
|
||||||
title: {
|
title: {
|
||||||
if(d.isHoveredHoldingValidAsset && !!d.hoveredHolding.symbol) {
|
if(d.isHoveredHoldingValidAsset && !!d.hoveredHolding.symbol) {
|
||||||
let totalAmount = !d.hoveredHolding.communityId ? selectedHoldingAggregator.value/(10 ** d.hoveredHolding.decimals): selectedHoldingAggregator.value
|
const input = amountToSendInput.inputIsFiat ? d.hoveredHolding.currentCurrencyBalance : d.hoveredHolding.currentBalance
|
||||||
const input = amountToSendInput.inputIsFiat ? totalAmount * d.hoveredHolding.marketDetails.currencyPrice.amount : totalAmount
|
|
||||||
const max = d.prepareForMaxSend(input, d.hoveredHolding.symbol)
|
const max = d.prepareForMaxSend(input, d.hoveredHolding.symbol)
|
||||||
if (max <= 0)
|
if (max <= 0)
|
||||||
return qsTr("No balances active")
|
return qsTr("No balances active")
|
||||||
|
@ -424,7 +408,7 @@ StatusDialog {
|
||||||
|
|
||||||
visible: !d.selectedHolding
|
visible: !d.selectedHolding
|
||||||
selectedSenderAccount: store.selectedSenderAccount.address
|
selectedSenderAccount: store.selectedSenderAccount.address
|
||||||
assets: popup.store.walletAssetStore.groupedAccountAssetsModel
|
assets: popup.store.processedAssetsModel
|
||||||
collectibles: popup.preSelectedAccount ? popup.nestedCollectiblesModel : null
|
collectibles: popup.preSelectedAccount ? popup.nestedCollectiblesModel : null
|
||||||
networksModel: popup.store.allNetworksModel
|
networksModel: popup.store.allNetworksModel
|
||||||
onlyAssets: holdingSelector.onlyAssets
|
onlyAssets: holdingSelector.onlyAssets
|
||||||
|
@ -438,11 +422,12 @@ StatusDialog {
|
||||||
d.setHoveredHoldingId("", Constants.TokenType.Unknown)
|
d.setHoveredHoldingId("", Constants.TokenType.Unknown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
onAssetSearchStringChanged: store.assetSearchString = assetSearchString
|
||||||
return store.getCurrencyAmountFromBigInt(balance, symbol, decimals)
|
formatCurrentCurrencyAmount: function(balance){
|
||||||
|
return popup.store.currencyStore.formatCurrencyAmount(balance, popup.store.currencyStore.currentCurrency)
|
||||||
}
|
}
|
||||||
getCurrentCurrencyAmount: function(balance){
|
formatCurrencyAmountFromBigInt: function(balance, symbol, decimals) {
|
||||||
return store.getCurrentCurrencyAmount(balance)
|
return popup.store.formatCurrencyAmountFromBigInt(balance, symbol, decimals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ StatusListItem {
|
||||||
|
|
||||||
signal tokenSelected(var selectedToken)
|
signal tokenSelected(var selectedToken)
|
||||||
signal tokenHovered(var selectedToken, bool hovered)
|
signal tokenHovered(var selectedToken, bool hovered)
|
||||||
property var getCurrencyAmountFromBigInt: function(balance, symbol, decimals){}
|
property var formatCurrentCurrencyAmount: function(balance){}
|
||||||
property var getCurrentCurrencyAmount: function(balance){}
|
property var formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){}
|
||||||
property var balancesModel
|
property var balancesModel
|
||||||
property string selectedSenderAccount
|
property string selectedSenderAccount
|
||||||
|
|
||||||
|
@ -29,25 +29,6 @@ StatusListItem {
|
||||||
function selectToken() {
|
function selectToken() {
|
||||||
root.tokenSelected({name, symbol, balances, decimals})
|
root.tokenSelected({name, symbol, balances, decimals})
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property string balanceRoleName: "balance"
|
|
||||||
property string roleName: balanceRoleName
|
|
||||||
}
|
|
||||||
|
|
||||||
property var filteredBalances : SortFilterProxyModel {
|
|
||||||
sourceModel: root.balancesModel
|
|
||||||
filters: FastExpressionFilter {
|
|
||||||
expression: {
|
|
||||||
root.selectedSenderAccount
|
|
||||||
return root.selectedSenderAccount === model.account
|
|
||||||
}
|
|
||||||
expectedRoles: ["account"]
|
|
||||||
}
|
|
||||||
onCountChanged: {
|
|
||||||
// Added because the SumAggregator is not evaluated after the filters are applied
|
|
||||||
d.roleName = ""
|
|
||||||
d.roleName = d.balanceRoleName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -64,11 +45,8 @@ StatusListItem {
|
||||||
statusListItemTitleAside.width: statusListItemTitleArea.width - statusListItemTitle.width
|
statusListItemTitleAside.width: statusListItemTitleArea.width - statusListItemTitle.width
|
||||||
statusListItemTitleAside.elide: Text.ElideRight
|
statusListItemTitleAside.elide: Text.ElideRight
|
||||||
label: {
|
label: {
|
||||||
if (!!model && !!model.marketDetails && !!model.marketDetails.currencyPrice) {
|
let balance = !!model && !!model.currentCurrencyBalance ? model.currentCurrencyBalance : 0
|
||||||
let totalCurrencyBalance = aggregator.value/(10 ** decimals) * model.marketDetails.currencyPrice.amount
|
return root.formatCurrentCurrencyAmount(balance)
|
||||||
return LocaleUtils.currencyAmountToLocaleString(root.getCurrentCurrencyAmount(totalCurrencyBalance))
|
|
||||||
}
|
|
||||||
return LocaleUtils.currencyAmountToLocaleString(root.getCurrentCurrencyAmount(0))
|
|
||||||
}
|
}
|
||||||
asset.name: symbol ? Style.png("tokens/" + symbol) : ""
|
asset.name: symbol ? Style.png("tokens/" + symbol) : ""
|
||||||
asset.isImage: true
|
asset.isImage: true
|
||||||
|
@ -77,13 +55,13 @@ StatusListItem {
|
||||||
statusListItemLabel.anchors.verticalCenterOffset: -12
|
statusListItemLabel.anchors.verticalCenterOffset: -12
|
||||||
statusListItemLabel.color: Theme.palette.directColor1
|
statusListItemLabel.color: Theme.palette.directColor1
|
||||||
statusListItemInlineTagsSlot.spacing: 0
|
statusListItemInlineTagsSlot.spacing: 0
|
||||||
tagsModel: filteredBalances
|
tagsModel: root.balancesModel
|
||||||
tagsDelegate: expandedItem
|
tagsDelegate: expandedItem
|
||||||
statusListItemInlineTagsSlot.children: Row {
|
statusListItemInlineTagsSlot.children: Row {
|
||||||
id: compactRow
|
id: compactRow
|
||||||
spacing: -6
|
spacing: -6
|
||||||
Repeater {
|
Repeater {
|
||||||
model: filteredBalances
|
model: root.balancesModel
|
||||||
delegate: compactItem
|
delegate: compactItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,12 +71,6 @@ StatusListItem {
|
||||||
|
|
||||||
onClicked: d.selectToken()
|
onClicked: d.selectToken()
|
||||||
|
|
||||||
SumAggregator {
|
|
||||||
id: aggregator
|
|
||||||
model: filteredBalances
|
|
||||||
roleName: d.roleName
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: compactItem
|
id: compactItem
|
||||||
StatusRoundedImage {
|
StatusRoundedImage {
|
||||||
|
@ -114,7 +86,7 @@ StatusListItem {
|
||||||
StatusListItemTag {
|
StatusListItemTag {
|
||||||
height: 16
|
height: 16
|
||||||
leftPadding: 0
|
leftPadding: 0
|
||||||
title: LocaleUtils.currencyAmountToLocaleString(root.getCurrencyAmountFromBigInt(balance, symbol, decimals))
|
title: root.formatCurrencyAmountFromBigInt(balance, symbol, decimals)
|
||||||
titleText.font.pixelSize: 12
|
titleText.font.pixelSize: 12
|
||||||
closeButtonVisible: false
|
closeButtonVisible: false
|
||||||
bgColor: "transparent"
|
bgColor: "transparent"
|
||||||
|
|
|
@ -34,6 +34,7 @@ Item {
|
||||||
|
|
||||||
property alias comboBoxControl: comboBox.control
|
property alias comboBoxControl: comboBox.control
|
||||||
property alias comboBoxDelegate: comboBox.delegate
|
property alias comboBoxDelegate: comboBox.delegate
|
||||||
|
property alias comboBoxListViewSection: comboBox.comboBoxListViewSection
|
||||||
property var comboBoxPopupHeader
|
property var comboBoxPopupHeader
|
||||||
|
|
||||||
property int contentIconSize: 21
|
property int contentIconSize: 21
|
||||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick 2.13
|
||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.13
|
||||||
|
|
||||||
import shared.controls 1.0
|
import shared.controls 1.0
|
||||||
|
import shared.popups 1.0
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
import SortFilterProxyModel 0.2
|
import SortFilterProxyModel 0.2
|
||||||
|
@ -12,7 +13,6 @@ import StatusQ 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
|
||||||
|
|
||||||
import "../controls"
|
import "../controls"
|
||||||
|
|
||||||
|
@ -25,12 +25,13 @@ Item {
|
||||||
property var networksModel
|
property var networksModel
|
||||||
property string currentCurrencySymbol
|
property string currentCurrencySymbol
|
||||||
property bool onlyAssets: true
|
property bool onlyAssets: true
|
||||||
|
property string searchText
|
||||||
|
|
||||||
implicitWidth: holdingItemSelector.implicitWidth
|
implicitWidth: holdingItemSelector.implicitWidth
|
||||||
implicitHeight: holdingItemSelector.implicitHeight
|
implicitHeight: holdingItemSelector.implicitHeight
|
||||||
|
|
||||||
property var getCurrencyAmountFromBigInt: function(balance, symbol, decimals){}
|
property var formatCurrentCurrencyAmount: function(balance){}
|
||||||
property var getCurrentCurrencyAmount: function(balance){}
|
property var formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){}
|
||||||
|
|
||||||
signal itemHovered(string holdingId, var holdingType)
|
signal itemHovered(string holdingId, var holdingType)
|
||||||
signal itemSelected(string holdingId, var holdingType)
|
signal itemSelected(string holdingId, var holdingType)
|
||||||
|
@ -78,7 +79,6 @@ Item {
|
||||||
|
|
||||||
property var currentHoldingType: Constants.TokenType.Unknown
|
property var currentHoldingType: Constants.TokenType.Unknown
|
||||||
|
|
||||||
property string searchText
|
|
||||||
readonly property string uppercaseSearchText: searchText.toUpperCase()
|
readonly property string uppercaseSearchText: searchText.toUpperCase()
|
||||||
|
|
||||||
property var assetTextFn: function (asset) {
|
property var assetTextFn: function (asset) {
|
||||||
|
@ -89,25 +89,6 @@ Item {
|
||||||
return !!asset && asset.symbol ? Style.png("tokens/%1".arg(asset.symbol)) : ""
|
return !!asset && asset.symbol ? Style.png("tokens/%1".arg(asset.symbol)) : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
property var assetComboBoxModel: SortFilterProxyModel {
|
|
||||||
sourceModel: root.assetsModel
|
|
||||||
filters: [
|
|
||||||
FastExpressionFilter {
|
|
||||||
function search(symbol, name, addressPerChain, searchString) {
|
|
||||||
return (
|
|
||||||
searchString === "" ||
|
|
||||||
symbol.startsWith(searchString) ||
|
|
||||||
name.toUpperCase().startsWith(searchString) ||
|
|
||||||
d.searchAddressInList(addressPerChain, searchString)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
expression: search(symbol, name, addressPerChain, d.uppercaseSearchText)
|
|
||||||
expectedRoles: ["symbol", "name", "addressPerChain"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
property var collectibleTextFn: function (item) {
|
property var collectibleTextFn: function (item) {
|
||||||
if (!!item) {
|
if (!!item) {
|
||||||
return !!item.collectionName ? item.collectionName + ": " + item.name : item.name
|
return !!item.collectionName ? item.collectionName + ": " + item.name : item.name
|
||||||
|
@ -168,18 +149,6 @@ Item {
|
||||||
readonly property int collectibleContentIconSize: 28
|
readonly property int collectibleContentIconSize: 28
|
||||||
readonly property int assetContentTextSize: 28
|
readonly property int assetContentTextSize: 28
|
||||||
readonly property int collectibleContentTextSize: 15
|
readonly property int collectibleContentTextSize: 15
|
||||||
|
|
||||||
function searchAddressInList(addressPerChain, searchString) {
|
|
||||||
let addressFound = false
|
|
||||||
let tokenAddresses = SQUtils.ModelUtils.modelToFlatArray(addressPerChain, "address")
|
|
||||||
for (let i =0; i< tokenAddresses.length; i++){
|
|
||||||
if(tokenAddresses[i].toUpperCase().startsWith(searchString.toUpperCase())) {
|
|
||||||
addressFound = true
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addressFound
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HoldingItemSelector {
|
HoldingItemSelector {
|
||||||
|
@ -222,15 +191,39 @@ Item {
|
||||||
comboBoxPopupHeader: headerComponent
|
comboBoxPopupHeader: headerComponent
|
||||||
itemTextFn: d.isCurrentBrowsingTypeAsset ? d.assetTextFn : d.collectibleTextFn
|
itemTextFn: d.isCurrentBrowsingTypeAsset ? d.assetTextFn : d.collectibleTextFn
|
||||||
itemIconSourceFn: d.isCurrentBrowsingTypeAsset ? d.assetIconSourceFn : d.collectibleIconSourceFn
|
itemIconSourceFn: d.isCurrentBrowsingTypeAsset ? d.assetIconSourceFn : d.collectibleIconSourceFn
|
||||||
comboBoxModel: d.isCurrentBrowsingTypeAsset ? d.assetComboBoxModel : d.collectibleComboBoxModel
|
comboBoxModel: d.isCurrentBrowsingTypeAsset ? root.assetsModel : d.collectibleComboBoxModel
|
||||||
|
|
||||||
contentIconSize: d.isAsset(d.currentHoldingType) ? d.assetContentIconSize : d.collectibleContentIconSize
|
contentIconSize: d.isAsset(d.currentHoldingType) ? d.assetContentIconSize : d.collectibleContentIconSize
|
||||||
contentTextSize: d.isAsset(d.currentHoldingType) ? d.assetContentTextSize : d.collectibleContentTextSize
|
contentTextSize: d.isAsset(d.currentHoldingType) ? d.assetContentTextSize : d.collectibleContentTextSize
|
||||||
|
comboBoxListViewSection.property: "isCommunityAsset"
|
||||||
|
comboBoxListViewSection.delegate: Loader {
|
||||||
|
width: ListView.view.width
|
||||||
|
required property string section
|
||||||
|
sourceComponent: d.isCurrentBrowsingTypeAsset && section === "true" ? sectionDelegate : null
|
||||||
|
}
|
||||||
|
comboBoxControl.popup.onClosed: comboBoxControl.popup.contentItem.headerItem.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: sectionDelegate
|
||||||
|
AssetsSectionDelegate {
|
||||||
|
width: parent.width
|
||||||
|
onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: communityInfoPopupCmp
|
||||||
|
CommunityAssetsInfoPopup {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: headerComponent
|
id: headerComponent
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
function clear() {
|
||||||
|
searchInput.input.edit.clear()
|
||||||
|
}
|
||||||
|
|
||||||
width: holdingItemSelector.comboBoxControl.popup.width
|
width: holdingItemSelector.comboBoxControl.popup.width
|
||||||
Layout.topMargin: d.headerTopMargin
|
Layout.topMargin: d.headerTopMargin
|
||||||
spacing: -1 // Used to overlap rectangles from row components
|
spacing: -1 // Used to overlap rectangles from row components
|
||||||
|
@ -318,11 +311,11 @@ Item {
|
||||||
root.itemSelected(selectedToken.symbol, Constants.TokenType.ERC20)
|
root.itemSelected(selectedToken.symbol, Constants.TokenType.ERC20)
|
||||||
holdingItemSelector.comboBoxControl.popup.close()
|
holdingItemSelector.comboBoxControl.popup.close()
|
||||||
}
|
}
|
||||||
getCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
formatCurrentCurrencyAmount: function(balance){
|
||||||
return root.getCurrencyAmountFromBigInt(balance, symbol, decimals)
|
return root.formatCurrentCurrencyAmount(balance)
|
||||||
}
|
}
|
||||||
getCurrentCurrencyAmount: function(balance){
|
formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
||||||
return root.getCurrentCurrencyAmount(balance)
|
return root.formatCurrencyAmountFromBigInt(balance, symbol, decimals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,11 @@ import StatusQ.Controls 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Components 0.1
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
|
import shared.controls 1.0
|
||||||
|
import shared.popups 1.0
|
||||||
import "../controls"
|
import "../controls"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -21,25 +22,28 @@ Item {
|
||||||
property var assets: null
|
property var assets: null
|
||||||
property var collectibles: null
|
property var collectibles: null
|
||||||
property var networksModel
|
property var networksModel
|
||||||
|
property string assetSearchString
|
||||||
|
|
||||||
signal tokenSelected(string symbol, var holdingType)
|
signal tokenSelected(string symbol, var holdingType)
|
||||||
signal tokenHovered(string symbol, var holdingType, bool hovered)
|
signal tokenHovered(string symbol, var holdingType, bool hovered)
|
||||||
|
|
||||||
property bool onlyAssets: false
|
property bool onlyAssets: false
|
||||||
property int browsingHoldingType: Constants.TokenType.ERC20
|
property int browsingHoldingType: Constants.TokenType.ERC20
|
||||||
property var getCurrencyAmountFromBigInt: function(balance, symbol, decimals){}
|
property var formatCurrentCurrencyAmount: function(balance){}
|
||||||
property var getCurrentCurrencyAmount: function(balance){}
|
property var formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){}
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if(!visible && root.collectibles)
|
if(!visible) {
|
||||||
root.collectibles.currentCollectionUid = ""
|
if (root.collectibles)
|
||||||
|
root.collectibles.currentCollectionUid = ""
|
||||||
|
tokenList.headerItem.input.edit.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
property string assetSearchString
|
|
||||||
readonly property var updateAssetSearchText: Backpressure.debounce(root, 1000, function(inputText) {
|
readonly property var updateAssetSearchText: Backpressure.debounce(root, 1000, function(inputText) {
|
||||||
d.assetSearchString = inputText
|
assetSearchString = inputText
|
||||||
})
|
})
|
||||||
|
|
||||||
property string collectibleSearchString
|
property string collectibleSearchString
|
||||||
|
@ -71,18 +75,6 @@ Item {
|
||||||
rightModel: d.renamedAllNetworksModel
|
rightModel: d.renamedAllNetworksModel
|
||||||
joinRole: "chainId"
|
joinRole: "chainId"
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchAddressInList(addressPerChain, searchString) {
|
|
||||||
let addressFound = false
|
|
||||||
let tokenAddresses = SQUtils.ModelUtils.modelToFlatArray(addressPerChain, "address")
|
|
||||||
for (let i =0; i< tokenAddresses.length; i++){
|
|
||||||
if(tokenAddresses[i].toUpperCase().startsWith(searchString.toUpperCase())) {
|
|
||||||
addressFound = true
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addressFound
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitWidth: contentLayout.implicitWidth
|
implicitWidth: contentLayout.implicitWidth
|
||||||
|
@ -144,30 +136,34 @@ Item {
|
||||||
height: tokenList.contentHeight
|
height: tokenList.contentHeight
|
||||||
|
|
||||||
header: root.browsingHoldingType === Constants.TokenType.ERC20 ? tokenHeader : collectibleHeader
|
header: root.browsingHoldingType === Constants.TokenType.ERC20 ? tokenHeader : collectibleHeader
|
||||||
model: root.browsingHoldingType === Constants.TokenType.ERC20 ? tokensModel : collectiblesModel
|
model: root.browsingHoldingType === Constants.TokenType.ERC20 ? root.assets : collectiblesModel
|
||||||
delegate: root.browsingHoldingType === Constants.TokenType.ERC20 ? tokenDelegate : collectiblesDelegate
|
delegate: root.browsingHoldingType === Constants.TokenType.ERC20 ? tokenDelegate : collectiblesDelegate
|
||||||
|
section {
|
||||||
|
property: "isCommunityAsset"
|
||||||
|
delegate: Loader {
|
||||||
|
width: ListView.view.width
|
||||||
|
required property string section
|
||||||
|
sourceComponent: root.browsingHoldingType === Constants.TokenType.ERC20 && section === "true" ? sectionDelegate : null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: sectionDelegate
|
||||||
|
AssetsSectionDelegate {
|
||||||
|
width: parent.width
|
||||||
|
onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: communityInfoPopupCmp
|
||||||
|
CommunityAssetsInfoPopup {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property var tokensModel: SortFilterProxyModel {
|
|
||||||
sourceModel: root.assets
|
|
||||||
filters: [
|
|
||||||
FastExpressionFilter {
|
|
||||||
function search(symbol, name, addressPerChain, searchString) {
|
|
||||||
tokenList.positionViewAtBeginning()
|
|
||||||
return (
|
|
||||||
symbol.startsWith(searchString.toUpperCase()) ||
|
|
||||||
name.toUpperCase().startsWith(searchString.toUpperCase()) || d.searchAddressInList(addressPerChain, searchString)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
expression: search(symbol, name, addressPerChain, d.assetSearchString)
|
|
||||||
expectedRoles: ["symbol", "name", "addressPerChain"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
property var collectiblesModel: SortFilterProxyModel {
|
property var collectiblesModel: SortFilterProxyModel {
|
||||||
sourceModel: d.collectiblesNetworksJointModel
|
sourceModel: d.collectiblesNetworksJointModel
|
||||||
filters: [
|
filters: [
|
||||||
|
@ -195,11 +191,11 @@ Item {
|
||||||
}
|
}
|
||||||
onTokenSelected: root.tokenSelected(symbol, Constants.TokenType.ERC20)
|
onTokenSelected: root.tokenSelected(symbol, Constants.TokenType.ERC20)
|
||||||
onTokenHovered: root.tokenHovered(symbol, Constants.TokenType.ERC20, hovered)
|
onTokenHovered: root.tokenHovered(symbol, Constants.TokenType.ERC20, hovered)
|
||||||
getCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
formatCurrentCurrencyAmount: function(balance){
|
||||||
return root.getCurrencyAmountFromBigInt(balance, symbol, decimals)
|
return root.formatCurrentCurrencyAmount(balance)
|
||||||
}
|
}
|
||||||
getCurrentCurrencyAmount: function(balance){
|
formatCurrencyAmountFromBigInt: function(balance, symbol, decimals){
|
||||||
return root.getCurrentCurrencyAmount(balance)
|
return root.formatCurrencyAmountFromBigInt(balance, symbol, decimals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import shared.stores 1.0
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
import StatusQ.Core.Utils 0.1
|
import StatusQ.Core.Utils 0.1
|
||||||
|
|
||||||
import AppLayouts.Wallet.stores 1.0
|
import AppLayouts.Wallet.stores 1.0
|
||||||
|
@ -15,6 +16,7 @@ QtObject {
|
||||||
|
|
||||||
property CurrenciesStore currencyStore: CurrenciesStore {}
|
property CurrenciesStore currencyStore: CurrenciesStore {}
|
||||||
property WalletAssetsStore walletAssetStore
|
property WalletAssetsStore walletAssetStore
|
||||||
|
property TokensStore tokensStore
|
||||||
|
|
||||||
property var mainModuleInst: mainModule
|
property var mainModuleInst: mainModule
|
||||||
property var walletSectionSendInst: walletSectionSend
|
property var walletSectionSendInst: walletSectionSend
|
||||||
|
@ -105,15 +107,9 @@ QtObject {
|
||||||
|
|
||||||
function getAsset(assetsList, symbol) {
|
function getAsset(assetsList, symbol) {
|
||||||
for(var i=0; i< assetsList.rowCount();i++) {
|
for(var i=0; i< assetsList.rowCount();i++) {
|
||||||
let asset = ModelUtils.get(assetsList, i)
|
let asset = assetsList.get(i)
|
||||||
if(symbol === asset.symbol) {
|
if(symbol === asset.symbol) {
|
||||||
return {
|
return asset
|
||||||
name: asset.name,
|
|
||||||
symbol: asset.symbol,
|
|
||||||
totalBalance: asset.totalBalance,
|
|
||||||
balances: asset.balances,
|
|
||||||
decimals: asset.decimals
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
|
@ -137,7 +133,7 @@ QtObject {
|
||||||
|
|
||||||
function getHolding(holdingId, holdingType) {
|
function getHolding(holdingId, holdingType) {
|
||||||
if (holdingType === Constants.TokenType.ERC20) {
|
if (holdingType === Constants.TokenType.ERC20) {
|
||||||
return getAsset(walletAssetStore.groupedAccountAssetsModel, holdingId)
|
return getAsset(processedAssetsModel, holdingId)
|
||||||
} else if (holdingType === Constants.TokenType.ERC721) {
|
} else if (holdingType === Constants.TokenType.ERC721) {
|
||||||
return getCollectible(holdingId)
|
return getCollectible(holdingId)
|
||||||
} else {
|
} else {
|
||||||
|
@ -147,7 +143,7 @@ QtObject {
|
||||||
|
|
||||||
function getSelectorHolding(holdingId, holdingType) {
|
function getSelectorHolding(holdingId, holdingType) {
|
||||||
if (holdingType === Constants.TokenType.ERC20) {
|
if (holdingType === Constants.TokenType.ERC20) {
|
||||||
return getAsset(walletAssetStore.groupedAccountAssetsModel, holdingId)
|
return getAsset(processedAssetsModel, holdingId)
|
||||||
} else if (holdingType === Constants.TokenType.ERC721) {
|
} else if (holdingType === Constants.TokenType.ERC721) {
|
||||||
return getSelectorCollectible(holdingId)
|
return getSelectorCollectible(holdingId)
|
||||||
} else {
|
} else {
|
||||||
|
@ -238,6 +234,7 @@ QtObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetStoredProperties() {
|
function resetStoredProperties() {
|
||||||
|
assetSearchString = ""
|
||||||
walletSectionSendInst.resetStoredProperties()
|
walletSectionSendInst.resetStoredProperties()
|
||||||
nestedCollectiblesModel.currentCollectionUid = ""
|
nestedCollectiblesModel.currentCollectionUid = ""
|
||||||
}
|
}
|
||||||
|
@ -253,13 +250,104 @@ QtObject {
|
||||||
return walletSectionSendInst.getShortChainIds(chainShortNames)
|
return walletSectionSendInst.getShortChainIds(chainShortNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrencyAmountFromBigInt(balance, symbol, decimals) {
|
function formatCurrencyAmountFromBigInt(balance, symbol, decimals) {
|
||||||
let bigIntBalance = AmountsArithmetic.fromString(balance)
|
let bigIntBalance = AmountsArithmetic.fromString(balance)
|
||||||
let decimalBalance = AmountsArithmetic.toNumber(bigIntBalance, decimals)
|
let decimalBalance = AmountsArithmetic.toNumber(bigIntBalance, decimals)
|
||||||
return currencyStore.getCurrencyAmount(decimalBalance, symbol)
|
return currencyStore.formatCurrencyAmount(decimalBalance, symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentCurrencyAmount(balance) {
|
// Property set from TokenLIstView and HoldingSelector to search token by name, symbol or contract address
|
||||||
return currencyStore.getCurrencyAmount(balance, currencyStore.currentCurrency)
|
property string assetSearchString
|
||||||
|
|
||||||
|
// Internal model filtering balances by the account selected on the SendModalPage
|
||||||
|
property SubmodelProxyModel __assetsWithFilteredBalances: SubmodelProxyModel {
|
||||||
|
sourceModel: walletAssetStore.groupedAccountAssetsModel
|
||||||
|
submodelRoleName: "balances"
|
||||||
|
delegateModel: SortFilterProxyModel {
|
||||||
|
sourceModel: submodel
|
||||||
|
filters: FastExpressionFilter {
|
||||||
|
expression: root.selectedSenderAccount.address === model.account
|
||||||
|
expectedRoles: ["account"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Model prepared to provide filtered and sorted assets as per the advanced Settings in token management
|
||||||
|
property var processedAssetsModel: SortFilterProxyModel {
|
||||||
|
sourceModel: __assetsWithFilteredBalances
|
||||||
|
proxyRoles: [
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "isCommunityAsset"
|
||||||
|
expression: !!model.communityId
|
||||||
|
expectedRoles: ["communityId"]
|
||||||
|
},
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "currentBalance"
|
||||||
|
expression: __getTotalBalance(model.balances, model.decimals, root.selectedSenderAccount)
|
||||||
|
expectedRoles: ["balances", "decimals"]
|
||||||
|
},
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "currentCurrencyBalance"
|
||||||
|
expression: {
|
||||||
|
if (!!model.marketDetails) {
|
||||||
|
return model.currentBalance * model.marketDetails.currencyPrice.amount
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
expectedRoles: ["marketDetails", "currentBalance", "symbol"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
filters: [
|
||||||
|
FastExpressionFilter {
|
||||||
|
function search(symbol, name, addressPerChain, searchString) {
|
||||||
|
return (
|
||||||
|
symbol.toUpperCase().startsWith(searchString.toUpperCase()) ||
|
||||||
|
name.toUpperCase().startsWith(searchString.toUpperCase()) || __searchAddressInList(addressPerChain, searchString)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
expression: search(symbol, name, addressPerChain, assetSearchString)
|
||||||
|
expectedRoles: ["symbol", "name", "addressPerChain"]
|
||||||
|
},
|
||||||
|
ValueFilter {
|
||||||
|
roleName: "isCommunityAsset"
|
||||||
|
value: false
|
||||||
|
enabled: !tokensStore.showCommunityAssetsInSend
|
||||||
|
},
|
||||||
|
FastExpressionFilter {
|
||||||
|
expression: {
|
||||||
|
if (model.isCommunityAsset)
|
||||||
|
return true
|
||||||
|
return model.currentCurrencyBalance > tokensStore.balanceThresholdAmount
|
||||||
|
}
|
||||||
|
expectedRoles: ["isCommunityAsset", "currentCurrencyBalance"]
|
||||||
|
enabled: tokensStore.balanceThresholdEnabled
|
||||||
|
}
|
||||||
|
]
|
||||||
|
sorters: RoleSorter {
|
||||||
|
roleName: "isCommunityAsset"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal function to search token address */
|
||||||
|
function __searchAddressInList(addressPerChain, searchString) {
|
||||||
|
let addressFound = false
|
||||||
|
let tokenAddresses = ModelUtils.modelToFlatArray(addressPerChain, "address")
|
||||||
|
for (let i =0; i< tokenAddresses.length; i++){
|
||||||
|
if(tokenAddresses[i].toUpperCase().startsWith(searchString.toUpperCase())) {
|
||||||
|
addressFound = true
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addressFound
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal function to calculate total balance */
|
||||||
|
function __getTotalBalance(balances, decimals) {
|
||||||
|
let totalBalance = 0
|
||||||
|
for(let i=0; i<balances.count; i++) {
|
||||||
|
let balancePerAddressPerChain = ModelUtils.get(balances, i)
|
||||||
|
totalBalance+=AmountsArithmetic.toNumber(balancePerAddressPerChain.balance, decimals)
|
||||||
|
}
|
||||||
|
return totalBalance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,6 @@ ColumnLayout {
|
||||||
sourceModel: root.assets
|
sourceModel: root.assets
|
||||||
proxyRoles: [
|
proxyRoles: [
|
||||||
FastExpressionRole {
|
FastExpressionRole {
|
||||||
id: filter
|
|
||||||
name: "currentBalance"
|
name: "currentBalance"
|
||||||
expression: d.getTotalBalance(model.balances, model.decimals, root.addressFilters, root.networkFilters)
|
expression: d.getTotalBalance(model.balances, model.decimals, root.addressFilters, root.networkFilters)
|
||||||
expectedRoles: ["balances", "decimals"]
|
expectedRoles: ["balances", "decimals"]
|
||||||
|
@ -240,35 +239,9 @@ ColumnLayout {
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: sectionDelegate
|
id: sectionDelegate
|
||||||
ColumnLayout {
|
AssetsSectionDelegate {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: 0
|
onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp)
|
||||||
|
|
||||||
StatusDialogDivider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: Style.current.padding
|
|
||||||
Layout.bottomMargin: Style.current.halfPadding
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: Style.current.padding
|
|
||||||
Layout.rightMargin: Style.current.smallPadding
|
|
||||||
Layout.bottomMargin: 4
|
|
||||||
StatusBaseText {
|
|
||||||
text: qsTr("Community assets")
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
StatusFlatButton {
|
|
||||||
Layout.preferredWidth: 32
|
|
||||||
Layout.preferredHeight: 32
|
|
||||||
icon.name: "info"
|
|
||||||
textColor: Theme.palette.baseColor1
|
|
||||||
horizontalPadding: 0
|
|
||||||
verticalPadding: 0
|
|
||||||
onClicked: Global.openPopup(communityInfoPopupCmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +280,7 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
currencyBalance.text: {
|
currencyBalance.text: {
|
||||||
let totalCurrencyBalance = modelData && modelData.currentCurrencyBalance ? modelData.currentCurrencyBalance : 0
|
let totalCurrencyBalance = modelData && modelData.currentCurrencyBalance ? modelData.currentCurrencyBalance : 0
|
||||||
return LocaleUtils.currencyAmountToLocaleString(root.currencyStore.getCurrentCurrencyAmount(totalCurrencyBalance))
|
return currencyStore.formatCurrencyAmount(totalCurrencyBalance, currencyStore.currentCurrency)
|
||||||
}
|
}
|
||||||
errorMode: !!networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCache && !networkConnectionStore.noMarketConnectionAndNoCache : false
|
errorMode: !!networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCache && !networkConnectionStore.noMarketConnectionAndNoCache : false
|
||||||
errorIcon.tooltip.text: !!networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCacheText : ""
|
errorIcon.tooltip.text: !!networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCacheText : ""
|
||||||
|
@ -380,16 +353,7 @@ ColumnLayout {
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: communityInfoPopupCmp
|
id: communityInfoPopupCmp
|
||||||
StatusDialog {
|
CommunityAssetsInfoPopup {}
|
||||||
destroyOnClose: true
|
|
||||||
title: qsTr("What are community assets?")
|
|
||||||
standardButtons: Dialog.Ok
|
|
||||||
width: 520
|
|
||||||
contentItem: StatusBaseText {
|
|
||||||
wrapMode: Text.Wrap
|
|
||||||
text: qsTr("Community assets are assets that have been minted by a community. As these assets cannot be verified, always double check their origin and validity before interacting with them. If in doubt, ask a trusted member or admin of the relevant community.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|
Loading…
Reference in New Issue