feat(@desktop/wallet): display balance in collectibles view
Closes #12940
This commit is contained in:
parent
96c7795153
commit
af84d788ff
|
@ -1,4 +1,5 @@
|
||||||
import NimQml, Tables, strutils, strformat
|
import NimQml, Tables, strutils, strformat
|
||||||
|
import stint
|
||||||
|
|
||||||
import backend/collectibles_types as backend
|
import backend/collectibles_types as backend
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ QtObject:
|
||||||
of ModelRole.AccountAddress:
|
of ModelRole.AccountAddress:
|
||||||
result = newQVariant(item.address)
|
result = newQVariant(item.address)
|
||||||
of ModelRole.Balance:
|
of ModelRole.Balance:
|
||||||
result = newQVariant($item.balance)
|
result = newQVariant(item.balance.toString(10))
|
||||||
of ModelRole.TxTimestamp:
|
of ModelRole.TxTimestamp:
|
||||||
result = newQVariant(item.txTimestamp)
|
result = newQVariant(item.txTimestamp)
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,12 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 1
|
txTimestamp: 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 2
|
txTimestamp: 2
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -56,7 +56,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "8",
|
||||||
txTimestamp: 3
|
txTimestamp: 3
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -76,7 +76,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 3
|
txTimestamp: 3
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -96,7 +96,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 6
|
txTimestamp: 6
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -116,12 +116,12 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 50
|
txTimestamp: 50
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 10
|
txTimestamp: 10
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -141,7 +141,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 16
|
txTimestamp: 16
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -161,7 +161,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 19
|
txTimestamp: 19
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -184,7 +184,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "15",
|
||||||
txTimestamp: 20
|
txTimestamp: 20
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -204,7 +204,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "4",
|
||||||
txTimestamp: 21
|
txTimestamp: 21
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -224,7 +224,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 22
|
txTimestamp: 22
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -244,7 +244,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 23
|
txTimestamp: 23
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -264,7 +264,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1000",
|
||||||
txTimestamp: 25
|
txTimestamp: 25
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -284,7 +284,7 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "1",
|
||||||
txTimestamp: 26
|
txTimestamp: 26
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -304,9 +304,14 @@ ListModel {
|
||||||
ownership: [
|
ownership: [
|
||||||
{
|
{
|
||||||
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
|
||||||
balance: 1,
|
balance: "60",
|
||||||
txTimestamp: 27
|
txTimestamp: 27
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accountAddress: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
|
||||||
|
balance: "70",
|
||||||
|
txTimestamp: 60
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,6 +123,16 @@ QtObject {
|
||||||
return divident.div(divisor)
|
return divident.div(divisor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmlmethod AmountsArithmetic::sum(amount1, amount2)
|
||||||
|
\brief Returns a Big number whose value is the sum of amount1 and amount2.
|
||||||
|
*/
|
||||||
|
function sum(amount1, amount2) {
|
||||||
|
console.assert(amount1 instanceof Big.Big)
|
||||||
|
console.assert(amount2 instanceof Big.Big)
|
||||||
|
return amount1.plus(amount2)
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmlmethod AmountsArithmetic::cmp(amount1, amount2)
|
\qmlmethod AmountsArithmetic::cmp(amount1, amount2)
|
||||||
\brief Compares two amounts.
|
\brief Compares two amounts.
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
|
||||||
|
Control {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int balance: 1
|
||||||
|
|
||||||
|
implicitHeight: 24
|
||||||
|
horizontalPadding: 8
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: Theme.palette.indirectColor4
|
||||||
|
radius: height / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: StatusBaseText {
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
font.pixelSize: 10
|
||||||
|
font.family: Theme.palette.baseFont.name
|
||||||
|
text: {
|
||||||
|
if (root.balance > 99) {
|
||||||
|
return "99+"
|
||||||
|
} else {
|
||||||
|
return root.balance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,3 +12,4 @@ ManageTokensDelegate 1.0 ManageTokensDelegate.qml
|
||||||
ManageTokensGroupDelegate 1.0 ManageTokensGroupDelegate.qml
|
ManageTokensGroupDelegate 1.0 ManageTokensGroupDelegate.qml
|
||||||
InformationTileAssetDetails 1.0 InformationTileAssetDetails.qml
|
InformationTileAssetDetails 1.0 InformationTileAssetDetails.qml
|
||||||
StatusNetworkListItemTag 1.0 StatusNetworkListItemTag.qml
|
StatusNetworkListItemTag 1.0 StatusNetworkListItemTag.qml
|
||||||
|
CollectibleBalanceTag 1.0 CollectibleBalanceTag.qml
|
||||||
|
|
|
@ -10,7 +10,6 @@ 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
|
import StatusQ.Core.Utils 0.1
|
||||||
import StatusQ.Internal 0.1
|
|
||||||
import StatusQ.Models 0.1
|
import StatusQ.Models 0.1
|
||||||
import StatusQ.Popups 0.1
|
import StatusQ.Popups 0.1
|
||||||
import StatusQ.Popups.Dialog 0.1
|
import StatusQ.Popups.Dialog 0.1
|
||||||
|
@ -124,27 +123,44 @@ ColumnLayout {
|
||||||
readonly property var nwFilters: root.networkFilters.split(":")
|
readonly property var nwFilters: root.networkFilters.split(":")
|
||||||
readonly property var addrFilters: root.addressFilters.split(":").map((addr) => addr.toLowerCase())
|
readonly property var addrFilters: root.addressFilters.split(":").map((addr) => addr.toLowerCase())
|
||||||
|
|
||||||
function containsAnyAddress(ownership, filterList) {
|
|
||||||
for (let i = 0; i < ownership.count; i++) {
|
|
||||||
let accountAddress = ModelUtils.get(ownership, i, "accountAddress").toLowerCase()
|
|
||||||
if (filterList.includes(accountAddress)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLatestTimestmap(ownership, filterList) {
|
function getLatestTimestmap(ownership, filterList) {
|
||||||
let latest = 0
|
let latest = 0
|
||||||
for (let i = 0; i < ownership.count; i++) {
|
|
||||||
let accountAddress = ModelUtils.get(ownership, i, "accountAddress").toLowerCase()
|
if (!!ownership) {
|
||||||
if (filterList.includes(accountAddress)) {
|
for (let i = 0; i < ownership.count; i++) {
|
||||||
let txTimestamp = ModelUtils.get(ownership, i, "txTimestamp")
|
let accountAddress = ModelUtils.get(ownership, i, "accountAddress").toLowerCase()
|
||||||
latest = Math.max(latest, txTimestamp)
|
if (filterList.includes(accountAddress)) {
|
||||||
|
let txTimestamp = ModelUtils.get(ownership, i, "txTimestamp")
|
||||||
|
latest = Math.max(latest, txTimestamp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return latest
|
return latest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBalance(ownership, filterList) {
|
||||||
|
// Balance is a Uint256, so we need to use AmountsArithmetic to handle it
|
||||||
|
let balance = AmountsArithmetic.fromNumber(0)
|
||||||
|
|
||||||
|
if (!!ownership) {
|
||||||
|
for (let i = 0; i < ownership.count; i++) {
|
||||||
|
let accountAddress = ModelUtils.get(ownership, i, "accountAddress").toLowerCase()
|
||||||
|
if (filterList.includes(accountAddress)) {
|
||||||
|
let tokenBalanceStr = ModelUtils.get(ownership, i, "balance")+""
|
||||||
|
if (tokenBalanceStr !== "") {
|
||||||
|
let tokenBalance = AmountsArithmetic.fromString(tokenBalanceStr)
|
||||||
|
balance = AmountsArithmetic.sum(balance, tokenBalance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For simplicity, we limit the result to the maximum int manageable by QML
|
||||||
|
const maxInt = 2147483647
|
||||||
|
if (AmountsArithmetic.cmp(balance, AmountsArithmetic.fromNumber(maxInt)) === 1) {
|
||||||
|
return maxInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AmountsArithmetic.toNumber(balance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component CustomSFPM: SortFilterProxyModel {
|
component CustomSFPM: SortFilterProxyModel {
|
||||||
|
@ -157,6 +173,11 @@ ColumnLayout {
|
||||||
name: "groupName"
|
name: "groupName"
|
||||||
roleNames: ["collectionName", "communityName"]
|
roleNames: ["collectionName", "communityName"]
|
||||||
},
|
},
|
||||||
|
FastExpressionRole {
|
||||||
|
name: "balance"
|
||||||
|
expression: d.addrFilters, d.getBalance(model.ownership, d.addrFilters)
|
||||||
|
expectedRoles: ["ownership"]
|
||||||
|
},
|
||||||
FastExpressionRole {
|
FastExpressionRole {
|
||||||
name: "lastTxTimestamp"
|
name: "lastTxTimestamp"
|
||||||
expression: d.addrFilters, d.getLatestTimestmap(model.ownership, d.addrFilters)
|
expression: d.addrFilters, d.getLatestTimestmap(model.ownership, d.addrFilters)
|
||||||
|
@ -166,10 +187,14 @@ ColumnLayout {
|
||||||
filters: [
|
filters: [
|
||||||
FastExpressionFilter {
|
FastExpressionFilter {
|
||||||
expression: {
|
expression: {
|
||||||
d.addrFilters
|
return d.nwFilters.includes(model.chainId+"")
|
||||||
return d.nwFilters.includes(model.chainId+"") && d.containsAnyAddress(model.ownership, d.addrFilters)
|
|
||||||
}
|
}
|
||||||
expectedRoles: ["chainId", "ownership"]
|
expectedRoles: ["chainId"]
|
||||||
|
},
|
||||||
|
ValueFilter {
|
||||||
|
roleName: "balance"
|
||||||
|
value: 0
|
||||||
|
inverted: true
|
||||||
},
|
},
|
||||||
FastExpressionFilter {
|
FastExpressionFilter {
|
||||||
expression: {
|
expression: {
|
||||||
|
@ -461,6 +486,7 @@ ColumnLayout {
|
||||||
communityId: model.communityId ?? ""
|
communityId: model.communityId ?? ""
|
||||||
communityName: model.communityName ?? ""
|
communityName: model.communityName ?? ""
|
||||||
communityImage: model.communityImage ?? ""
|
communityImage: model.communityImage ?? ""
|
||||||
|
balance: model.balance ?? 1
|
||||||
|
|
||||||
onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.symbol, model.tokenType)
|
onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.symbol, model.tokenType)
|
||||||
onRightClicked: {
|
onRightClicked: {
|
||||||
|
|
|
@ -27,6 +27,7 @@ Control {
|
||||||
property string communityId: ""
|
property string communityId: ""
|
||||||
property string communityName
|
property string communityName
|
||||||
property string communityImage
|
property string communityImage
|
||||||
|
property int balance: 1
|
||||||
|
|
||||||
// Special Owner and TMaster token properties
|
// Special Owner and TMaster token properties
|
||||||
readonly property bool isCommunityCollectible: communityId !== ""
|
readonly property bool isCommunityCollectible: communityId !== ""
|
||||||
|
@ -65,6 +66,13 @@ Control {
|
||||||
cursorShape: !root.isLoading ? Qt.PointingHandCursor : undefined
|
cursorShape: !root.isLoading ? Qt.PointingHandCursor : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property Component balanceTag: Component {
|
||||||
|
CollectibleBalanceTag {
|
||||||
|
visible: !root.isLoading && (root.balance > 1)
|
||||||
|
balance: root.balance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
@ -89,6 +97,13 @@ Control {
|
||||||
active: root.isLoading
|
active: root.isLoading
|
||||||
sourceComponent: LoadingComponent {radius: image.radius}
|
sourceComponent: LoadingComponent {radius: image.radius}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: Style.current.halfPadding
|
||||||
|
sourceComponent: root.balanceTag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivilegedTokenArtworkPanel {
|
PrivilegedTokenArtworkPanel {
|
||||||
|
@ -110,6 +125,13 @@ Control {
|
||||||
active: root.isLoading
|
active: root.isLoading
|
||||||
sourceComponent: LoadingComponent {radius: image.radius}
|
sourceComponent: LoadingComponent {radius: image.radius}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: Style.current.halfPadding
|
||||||
|
sourceComponent: root.balanceTag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|
Loading…
Reference in New Issue