feat(@desktop/wallet): Collectible Details balance tag

fixes #13809
This commit is contained in:
Khushboo Mehta 2024-03-27 22:49:46 +01:00 committed by Khushboo-dev-cpp
parent 21b884e5ed
commit 2d20a2e1b7
9 changed files with 484 additions and 379 deletions

View File

@ -19,10 +19,23 @@ import utils 1.0
SplitView {
id: root
QtObject {
function isValidURL(url) {
return true
}
Component.onCompleted: {
Utils.globalUtilsInst = this
}
Component.onDestruction: {
Utils.globalUtilsInst = {}
}
}
QtObject {
id: d
readonly property QtObject collectiblesModel: WalletCollectiblesModel {
readonly property QtObject collectiblesModel: ManageCollectiblesModel {
Component.onCompleted: {
d.refreshCurrentCollectible()
}
@ -34,6 +47,15 @@ SplitView {
}
readonly property QtObject transactionsModel: WalletTransactionsModel{}
readonly property string addressesSelected: {
let supportedAddresses = ""
for (let i =0; i< accountsRepeater.count; i++) {
if (accountsRepeater.itemAt(i).checked && accountsRepeater.itemAt(i).visible)
supportedAddresses += accountsRepeater.itemAt(i).address + ":"
}
return supportedAddresses
}
}
SplitView {
@ -62,6 +84,7 @@ SplitView {
collectible: d.currentCollectible
isCollectibleLoading: isLoadingCheckbox.checked
activityModel: d.transactionsModel
addressFilters: d.addressesSelected
rootStore: QtObject {
readonly property string currentCurrency: "EUR"
@ -83,6 +106,26 @@ SplitView {
}
readonly property bool showAllAccounts: true
function getExplorerUrl(networkShortName, contractAddress, tokenId) {
let link = Constants.networkExplorerLinks.etherscan
if (networkShortName === Constants.networkShortChainNames.mainnet) {
return "%1/nft/%2/%3".arg(link).arg(contractAddress).arg(tokenId)
}
else {
return "%1/token/%2?a=%3".arg(link).arg(contractAddress).arg(tokenId)
}
}
function getOpenSeaCollectionUrl(networkShortName, contractAddress) {
let baseLink = root.areTestNetworksEnabled ? Constants.openseaExplorerLinks.testnetLink : Constants.openseaExplorerLinks.mainnetLink
return "%1/assets/%2/%3".arg(baseLink).arg(networkShortName).arg(contractAddress)
}
function getOpenSeaCollectibleUrl(networkShortName, contractAddress, tokenId) {
let baseLink = root.areTestNetworksEnabled ? Constants.openseaExplorerLinks.testnetLink : Constants.openseaExplorerLinks.mainnetLink
return "%1/assets/%2/%3/%4".arg(baseLink).arg(networkShortName).arg(contractAddress).arg(tokenId)
}
}
communitiesStore: QtObject {
function getCommunityDetailsAsJson(communityId) {
@ -130,6 +173,23 @@ SplitView {
text: "isLoading"
checked: false
}
ColumnLayout {
Layout.fillWidth: true
Text {
text: "select account(s)"
}
Repeater {
id: accountsRepeater
model: WalletAccountsModel {}
delegate: CheckBox {
property string address: model.address
checked: true
visible: index<2
width: parent.width
text: name
}
}
}
}
}
}

View File

@ -117,7 +117,7 @@ Item {
const lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvOther)
tryCompare(lvOther, "count", 7)
tryCompare(lvOther, "count", 9)
const delegate0 = findChild(lvOther, "manageTokensDelegate-0")
verify(!!delegate0)
const title = delegate0.title
@ -127,7 +127,7 @@ Item {
tryCompare(notificationSpy, "count", 1)
// verify we now have -1 regular tokens after the "hide" operation
tryCompare(lvOther, "count", 6)
tryCompare(lvOther, "count", 8)
}
function test_showHideCommunityGroup() {
@ -149,7 +149,7 @@ Item {
verify(!!lvCommunity)
// verify we have 2 community collectible groups
tryCompare(lvCommunity, "count", 4)
tryCompare(lvCommunity, "count", 6)
tryCompare(notificationSpy, "count", 0)
triggerDelegateMenuAction(lvCommunity, 0, "miHideTokenGroup", true)
// verify the signal to show the notification toast got fired
@ -157,7 +157,7 @@ Item {
// verify we have one less group
waitForItemPolished(lvCommunity)
tryCompare(lvCommunity, "count", 3)
tryCompare(lvCommunity, "count", 5)
}
function test_dnd() {
@ -200,7 +200,7 @@ Item {
const lvCommunity = findChild(controlUnderTest, "communityTokensListView")
verify(!!lvCommunity)
waitForItemPolished(lvCommunity)
tryCompare(lvCommunity, "count", 4)
tryCompare(lvCommunity, "count", 6)
const group0 = findChild(lvCommunity, "manageTokensGroupDelegate-0")
const title0 = group0.title
@ -235,7 +235,7 @@ Item {
const lvCommunity = findChild(controlUnderTest, "communityTokensListView")
verify(!!lvCommunity)
waitForItemPolished(lvCommunity)
tryCompare(lvCommunity, "count", 4)
tryCompare(lvCommunity, "count", 6)
// get the "Bearz" group at index 1
var bearzGroupTokenDelegate = findChild(lvCommunity, "manageTokensGroupDelegate-1")

View File

@ -22,7 +22,7 @@ ListModel {
userHas: 9,
name: "Punx not dead!",
collectionUid: "",
collectionName: "",
collectionName: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
communityId: "",
communityName: "",
communityImage: ModelsData.icons.status,
@ -40,7 +40,26 @@ ListModel {
balance: "1",
txTimestamp: 2
},
]
],
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum,
description: "Punx not dead is a very rare CryptoKitty. It's a Gen 0 and has a lot of special traits.",
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Blue"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
tokenId: "403"
},
{
uid: "pp23",
@ -61,7 +80,26 @@ ListModel {
balance: "8",
txTimestamp: 3
},
]
],
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum,
description: "pepepunk not dead is a very rare CryptoKitty. It's a Gen 0 and has a lot of special traits.",
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Green"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
tokenId: "123"
},
{
uid: "34545656768",
@ -82,7 +120,26 @@ ListModel {
balance: "1",
txTimestamp: 3
},
]
],
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum,
description: "Furbeard is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Green"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
tokenId: "7123"
},
{
uid: "123456",
@ -103,7 +160,29 @@ ListModel {
balance: "1",
txTimestamp: 6
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Furbeard is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Green"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
tokenId: "403123"
},
{
uid: "12345645459537432",
@ -129,7 +208,26 @@ ListModel {
balance: "1",
txTimestamp: 10
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Big Kitty is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Blue"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
tokenId: "1"
},
{
uid: "pp21",
@ -150,7 +248,18 @@ ListModel {
balance: "1",
txTimestamp: 16
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "pepepunk not dead is a very rare nft. It's a Gen 0 and has a lot of special traits.",
traits: [
{
traitType: "Type",
value: "Special"
}
],
tokenId: "12568"
},
{
uid: "lp#666a",
@ -171,7 +280,18 @@ ListModel {
balance: "1",
txTimestamp: 19
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Lonely Panda #666 is a very rare NFT. It's a Gen 0 and has a lot of special traits.likie sjasja sajhash jhasjas",
traits: [
{
traitType: "Type",
value: "Rare"
}
],
tokenId: "1445"
},
]
@ -194,7 +314,13 @@ ListModel {
balance: "15",
txTimestamp: 20
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [],
tokenId: "4"
},
{
uid: "691",
@ -214,7 +340,13 @@ ListModel {
balance: "4",
txTimestamp: 21
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy :)",
traits: [],
tokenId: "3"
},
{
uid: "8876",
@ -234,7 +366,13 @@ ListModel {
balance: "1",
txTimestamp: 22
},
]
],
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum,
description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy :)",
traits: [],
tokenId: "341"
},
{
uid: "fp#3195",
@ -254,7 +392,13 @@ ListModel {
balance: "1",
txTimestamp: 23
},
]
],
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [],
tokenId: "765"
},
{
uid: "fp#4297",
@ -274,7 +418,13 @@ ListModel {
balance: "1000",
txTimestamp: 25
},
]
],
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [],
tokenId: "166"
},
{
uid: "fp#909",
@ -294,7 +444,13 @@ ListModel {
balance: "1",
txTimestamp: 26
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [],
tokenId: "1111"
},
{
uid: "lb#666",
@ -319,7 +475,13 @@ ListModel {
balance: "70",
txTimestamp: 60
}
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy",
traits: [],
tokenId: "6"
},
{
uid: "lb#777",
@ -339,8 +501,114 @@ ListModel {
balance: "1",
txTimestamp: 27
},
]
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "Lonely Turtle is a community for all of us to talk and communicate! Welcome onboard and enjoy",
traits: [],
tokenId: "7"
},
{
uid: "ID-Custom",
chainId: 1,
contractAddress: "0x04",
tokenId: "403",
name: "Custom Collectible",
imageUrl: ModelsData.collectibles.custom,
backgroundColor: "transparent",
description: "This is a custom collectible. It's a unique piece of art.",
collectionUid: "custom",
collectionName: "Custom",
collectionImageUrl: "",
traits: [],
ownership: [
{
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
balance: "1",
txTimestamp: 27
},
],
communityId: "",
networkShortName: "ARB",
networkColor: "blue",
networkIconUrl: ModelsData.networks.arbitrum
},
{
uid: "ID-MissingMetadata",
chainId: 1,
contractAddress: "0x05",
tokenId: "405",
name: "",
imageUrl: "",
backgroundColor: "transparent",
description: "",
collectionUid: "missing",
collectionName: "",
collectionImageUrl: "",
traits: [],
ownership: [
{
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
balance: "1",
txTimestamp: 27
},
],
communityId: "",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
},
{
uid: "ID-Community1",
chainId: 1,
contractAddress: "0x06",
tokenId: "406",
name: "Community Admin Token",
imageUrl: ModelsData.collectibles.mana,
backgroundColor: "transparent",
description: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
collectionUid: "community-uid-1",
collectionName: "",
collectionImageUrl: "",
traits: [],
ownership: [
{
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
balance: "1",
txTimestamp: 27
},
],
communityId: "community-id-1",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
},
{
uid: "ID-Community-Unknown",
chainId: 1,
contractAddress: "0x07",
tokenId: "407",
name: "Removed community token",
imageUrl: ModelsData.collectibles.mana,
backgroundColor: "transparent",
description: "This is unkown community community token",
collectionUid: "community-uid-unknown",
collectionName: "",
collectionImageUrl: "",
traits: [],
ownership: [
{
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
balance: "1",
txTimestamp: 27
},
],
communityId: "community-id-unknown",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
}
]
Component.onCompleted: {

View File

@ -1,284 +0,0 @@
import QtQuick 2.15
import StatusQ.Core 0.1
import utils 1.0
ListModel {
readonly property var rootData: [
{
uid: "ID-Kitty1",
chainId: 1,
contractAddress: "0x1",
tokenId: "1",
name: "Furbeard",
imageUrl: ModelsData.collectibles.kitty1Big,
backgroundColor: "#f5f5f5",
description: "Furbeard is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
collectionUid: "cryptokitties",
collectionName: "CryptoKitties",
collectionImageUrl: ModelsData.collectibles.cryptoKitties,
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Green"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
communityId: "",
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum
},
{
uid: "ID-Kitty2",
chainId: 1,
contractAddress: "0x1",
tokenId: "2",
name: "Magicat",
imageUrl: ModelsData.collectibles.kitty2Big,
backgroundColor: "transparent",
description: "Magicat is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
collectionUid: "cryptokitties",
collectionName: "CryptoKitties",
collectionImageUrl: ModelsData.collectibles.cryptoKitties,
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Blue"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
communityId: "",
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum
},
{
uid: "ID-Kitty3",
chainId: 1,
contractAddress: "0x1",
tokenId: "3",
name: "Happy Meow",
imageUrl: ModelsData.collectibles.kitty3Big,
backgroundColor: "blue",
description: "Happy Meow is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
collectionUid: "cryptokitties",
collectionName: "CryptoKitties",
collectionImageUrl: ModelsData.collectibles.cryptoKitties,
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Green"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
communityId: "",
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum
},
{
uid: "ID-Kitty4",
chainId: 1,
contractAddress: "0x1",
tokenId: "4",
name: "Furbeard-2",
imageUrl: ModelsData.collectibles.kitty4Big,
backgroundColor: "red",
description: "Furbeard-2 is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
collectionUid: "cryptokitties",
collectionName: "CryptoKitties",
collectionImageUrl: ModelsData.collectibles.cryptoKitties,
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Green"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
communityId: "",
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum
},
{
uid: "ID-Kitty5",
chainId: 1,
contractAddress: "0x1",
tokenId: "4",
name: "Magicat-3",
imageUrl: ModelsData.collectibles.kitty5Big,
backgroundColor: "yellow",
description: "Magicat-3 is a very rare CryptoKitty. It's a Gen 0 cat and has a lot of special traits.",
collectionUid: "cryptokitties",
collectionName: "CryptoKitties",
collectionImageUrl: ModelsData.collectibles.cryptoKitties,
traits: [
{
traitType: "Fur",
value: "White"
},
{
traitType: "Eyes",
value: "Blue"
},
{
traitType: "Pattern",
value: "Tigerpunk"
}
],
communityId: "",
networkShortName: "ETH",
networkColor: "blue",
networkIconUrl: ModelsData.networks.ethereum
},
{
uid: "ID-Anniversary",
chainId: 1,
contractAddress: "0x2",
tokenId: "1",
name: "Anniversary",
imageUrl: ModelsData.collectibles.anniversary,
backgroundColor: "black",
description: "This is a special collectible to celebrate the anniversary of the platform.",
collectionUid: "anniversary",
collectionName: "Anniversary",
collectionImageUrl: ModelsData.collectibles.anniversary,
traits: [
{
traitType: "Type",
value: "Special"
}
],
communityId: "",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
},
{
uid: "ID-SuperRare",
chainId: 1,
contractAddress: "0x3",
tokenId: "101",
name: "SuperRare",
imageUrl: ModelsData.collectibles.superRare,
backgroundColor: "transparent",
description: "This is a very rare collectible. It's a unique piece of art.",
collectionUid: "super-rare",
collectionName: "SuperRare",
collectionImageUrl: ModelsData.collectibles.doodles,
traits: [
{
traitType: "Type",
value: "Rare"
}
],
communityId: "",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
},
{
uid: "ID-Custom",
chainId: 1,
contractAddress: "0x04",
tokenId: "403",
name: "Custom Collectible",
imageUrl: ModelsData.collectibles.custom,
backgroundColor: "transparent",
description: "This is a custom collectible. It's a unique piece of art.",
collectionUid: "custom",
collectionName: "Custom",
collectionImageUrl: "",
traits: [],
communityId: "",
networkShortName: "ARB",
networkColor: "blue",
networkIconUrl: ModelsData.networks.arbitrum
},
{
uid: "ID-MissingMetadata",
chainId: 1,
contractAddress: "0x05",
tokenId: "405",
name: "",
imageUrl: "",
backgroundColor: "transparent",
description: "",
collectionUid: "missing",
collectionName: "",
collectionImageUrl: "",
traits: [],
communityId: "",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
},
{
uid: "ID-Community1",
chainId: 1,
contractAddress: "0x06",
tokenId: "406",
name: "Community Admin Token",
imageUrl: ModelsData.collectibles.mana,
backgroundColor: "transparent",
description: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
collectionUid: "community-uid-1",
collectionName: "",
collectionImageUrl: "",
traits: [],
communityId: "community-id-1",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
},
{
uid: "ID-Community-Unknown",
chainId: 1,
contractAddress: "0x07",
tokenId: "407",
name: "Removed community token",
imageUrl: ModelsData.collectibles.mana,
backgroundColor: "transparent",
description: "This is unkown community community token",
collectionUid: "community-uid-unknown",
collectionName: "",
collectionImageUrl: "",
traits: [],
communityId: "community-id-unknown",
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism
}
]
Component.onCompleted: append(rootData)
}

View File

@ -16,7 +16,6 @@ TokenHoldersModel 1.0 TokenHoldersModel.qml
UsersModel 1.0 UsersModel.qml
WalletSendAccountsModel 1.0 WalletSendAccountsModel.qml
WalletAccountsModel 1.0 WalletAccountsModel.qml
WalletCollectiblesModel 1.0 WalletCollectiblesModel.qml
WalletKeyPairModel 1.0 WalletKeyPairModel.qml
WalletNestedCollectiblesModel 1.0 WalletNestedCollectiblesModel.qml
WalletTransactionsModel 1.0 WalletTransactionsModel.qml

View File

@ -28,7 +28,7 @@ QtObject {
property var fromNetworksModel: NetworksModel.sendFromNetworks
property var toNetworksModel: NetworksModel.sendToNetworks
property var selectedSenderAccount: senderAccounts.get(0)
readonly property QtObject collectiblesModel: WalletCollectiblesModel {}
readonly property QtObject collectiblesModel: ManageCollectiblesModel {}
readonly property QtObject nestedCollectiblesModel: WalletNestedCollectiblesModel {}
readonly property QtObject walletSectionSendInst: QtObject {

View File

@ -15,7 +15,7 @@ Control {
horizontalPadding: 8
background: Rectangle {
color: Theme.palette.indirectColor4
color: Theme.palette.indirectColor2
radius: height / 2
}

View File

@ -232,6 +232,7 @@ RightTabBaseView {
collectible: RootStore.collectiblesStore.detailedCollectible
isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading
activityModel: d.detailedCollectibleActivityController.model
addressFilters: RootStore.addressFilters
rootStore: SharedStores.RootStore
walletRootStore: RootStore
communitiesStore: root.communitiesStore

View File

@ -1,6 +1,8 @@
import QtQuick 2.14
import QtQuick.Layouts 1.13
import SortFilterProxyModel 0.2
import StatusQ 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core 0.1
@ -28,6 +30,7 @@ Item {
required property var collectible
property var activityModel
property bool isCollectibleLoading
required property string addressFilters
// Community related token props:
readonly property bool isCommunityCollectible: !!collectible ? collectible.communityId !== "" : false
@ -38,9 +41,34 @@ Item {
QtObject {
id: d
readonly property string collectibleLink: root.walletRootStore.getOpenSeaCollectibleUrl(collectible.networkShortName, collectible.contractAddress, collectible.tokenId)
readonly property string collectionLink: root.walletRootStore.getOpenSeaCollectionUrl(collectible.networkShortName, collectible.contractAddress)
readonly property string blockExplorerLink: root.walletRootStore.getExplorerUrl(collectible.networkShortName, collectible.contractAddress, collectible.tokenId)
readonly property string collectibleLink: !!collectible ? root.walletRootStore.getOpenSeaCollectibleUrl(collectible.networkShortName, collectible.contractAddress, collectible.tokenId): ""
readonly property string collectionLink: !!collectible ? root.walletRootStore.getOpenSeaCollectionUrl(collectible.networkShortName, collectible.contractAddress): ""
readonly property string blockExplorerLink: !!collectible ? root.walletRootStore.getExplorerUrl(collectible.networkShortName, collectible.contractAddress, collectible.tokenId): ""
readonly property var addrFilters: root.addressFilters.split(":").map((addr) => addr.toLowerCase())
readonly property int imageStackSpacing: 4
property Component balanceTag: Component {
CollectibleBalanceTag {
balance: d.balanceAggregator.value
}
}
property SortFilterProxyModel filteredBalances: SortFilterProxyModel {
sourceModel: !!collectible ? collectible.ownership : null
filters: [
FastExpressionFilter {
expression: {
d.addrFilters
return d.addrFilters.includes(model.accountAddress.toLowerCase())
}
expectedRoles: ["accountAddress"]
}
]
}
property SumAggregator balanceAggregator: SumAggregator {
model: d.filteredBalances
roleName: "balance"
}
}
CollectibleDetailsHeader {
@ -48,16 +76,16 @@ Item {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
collectibleName: !!collectible.name ? collectible.name : qsTr("Unknown")
collectibleId: "#" + collectible.tokenId
collectibleName: !!collectible && !!collectible.name ? collectible.name : qsTr("Unknown")
collectibleId: !!collectible ? "#" + collectible.tokenId : ""
communityName: !!communityDetails ? communityDetails.name : ""
communityId: collectible.communityId
collectionName: collectible.collectionName
communityImage: !!communityDetails ? communityDetails.image: ""
networkShortName: collectible.networkShortName
networkColor: collectible.networkColor
networkIconURL: collectible.networkIconUrl
networkExplorerName: root.walletRootStore.getExplorerNameForNetwork(collectible.networkShortName)
communityId: !!collectible ? collectible.communityId : ""
collectionName: !!collectible ? collectible.collectionName : ""
communityImage: !!communityDetails ? communityDetails.image : ""
networkShortName: !!collectible ? collectible.networkShortName : ""
networkColor: !!collectible ?collectible.networkColor : ""
networkIconURL: !!collectible ? collectible.networkIconUrl : ""
networkExplorerName: !!collectible ? root.walletRootStore.getExplorerNameForNetwork(collectible.networkShortName): ""
collectibleLinkEnabled: Utils.getUrlStatus(d.collectibleLink)
collectionLinkEnabled: (!!communityDetails && communityDetails.name) || Utils.getUrlStatus(d.collectionLink)
explorerLinkEnabled: Utils.getUrlStatus(d.blockExplorerLink)
@ -78,7 +106,6 @@ Item {
anchors.top: collectibleHeader.bottom
anchors.topMargin: 25
anchors.left: parent.left
anchors.leftMargin: 52
anchors.right: parent.right
anchors.bottom: parent.bottom
@ -87,62 +114,41 @@ Item {
Row {
id: collectibleImageDetails
readonly property real visibleImageHeight: (collectibleimage.visible ? collectibleimage.height : privilegedCollectibleImage.height)
readonly property real visibleImageWidth: (collectibleimage.visible ? collectibleimage.width : privilegedCollectibleImage.width)
readonly property real visibleImageHeight: artwork.height
readonly property real visibleImageWidth: artwork.width
height: collectibleImageDetails.visibleImageHeight
width: parent.width
spacing: 24
// Special artwork representation for community `Owner and Master Token` token types:
PrivilegedTokenArtworkPanel {
id: privilegedCollectibleImage
visible: root.isCommunityCollectible && (root.isOwnerTokenType || root.isTMasterTokenType)
size: PrivilegedTokenArtworkPanel.Size.Large
artwork: root.collectible.imageUrl
color: !!root.collectible && !!root.communityDetails ? root.communityDetails.color : "transparent"
isOwner: root.isOwnerTokenType
}
StatusRoundedMedia {
id: collectibleimage
readonly property bool isEmpty: !mediaUrl.toString() && !fallbackImageUrl.toString()
visible: !privilegedCollectibleImage.visible
width: 248
height: width
radius: Style.current.radius
color: isError || isEmpty ? Theme.palette.baseColor5 : collectible.backgroundColor
border.color: Theme.palette.directColor8
border.width: 1
mediaUrl: collectible.mediaUrl ?? ""
mediaType: collectible.mediaType ?? ""
fallbackImageUrl: collectible.imageUrl
Column {
anchors.centerIn: parent
visible: collectibleimage.isError || collectibleimage.isEmpty
spacing: 10
StatusIcon {
anchors.horizontalCenter: parent.horizontalCenter
icon: "frowny"
opacity: 0.1
color: Theme.palette.directColor1
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Qt.AlignHCenter
color: Theme.palette.directColor6
text: {
if (collectibleimage.isError && collectibleimage.componentMediaType === StatusRoundedMedia.MediaType.Unkown) {
return qsTr("Unsupported\nfile format")
}
if (!collectible.description && !collectible.name) {
return qsTr("Info can't\nbe fetched")
}
return qsTr("Failed\nto load")
ColumnLayout {
id: artwork
spacing: 0
Repeater {
id: repeater
model: Math.min(3, d.balanceAggregator.value)
Item {
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: childrenRect.height
Layout.leftMargin: index * d.imageStackSpacing
Layout.topMargin: index === 0 ? 0 : -Layout.preferredHeight + d.imageStackSpacing
opacity: index === 0 ? 1: 0.4/index
// so that the first item remains on top in the stack
z: -index
Loader {
property int modelIndex: index
anchors.top: parent.top
anchors.left: parent.left
sourceComponent: root.isCommunityCollectible && (root.isOwnerTokenType || root.isTMasterTokenType) ? privilegedCollectibleImage: collectibleimage
active: root.visible
}
Loader {
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: Style.current.padding
sourceComponent: d.balanceTag
// only show balance tag on top of the first image in stack
active: index === 0 && d.balanceAggregator.value > 1 && root.visible
}
}
}
@ -159,7 +165,8 @@ Item {
width: parent.width
height: 24
text: root.isCommunityCollectible && !!communityDetails ? qsTr("Minted by %1").arg(root.communityDetails.name): root.collectible.collectionName
text: root.isCommunityCollectible && !!communityDetails ? qsTr("Minted by %1").arg(root.communityDetails.name):
!!collectible ? collectible.collectionName: ""
color: Theme.palette.directColor1
font.pixelSize: 17
lineHeight: 24
@ -174,7 +181,7 @@ Item {
height: collectibleImageDetails.height - collectibleName.height - parent.spacing
clip: true
text: collectible.description
text: !!collectible ? collectible.description : ""
textFormat: Text.MarkdownText
color: Theme.palette.directColor4
font.pixelSize: 15
@ -190,7 +197,7 @@ Item {
id: collectiblesDetailsTab
width: parent.width
topPadding: Style.current.xlPadding
visible: collectible.traits.count > 0
visible: !!collectible && collectible.traits.count > 0
StatusTabButton {
leftPadding: 0
@ -228,7 +235,7 @@ Item {
width: scrollView.availableWidth
spacing: 10
Repeater {
model: collectible.traits
model: !!collectible ? collectible.traits: null
InformationTile {
maxWidth: parent.width
primaryText: model.traitType
@ -240,7 +247,7 @@ Item {
Component {
id: activityView
StatusListView {
StatusListView {
width: scrollView.availableWidth
height: scrollView.availableHeight
model: root.activityModel
@ -269,4 +276,58 @@ Item {
}
}
}
Component {
id: privilegedCollectibleImage
// Special artwork representation for community `Owner and Master Token` token types:
PrivilegedTokenArtworkPanel {
size: PrivilegedTokenArtworkPanel.Size.Large
artwork: collectible.imageUrl ?? ""
color: !!root.collectible && !!root.communityDetails ? root.communityDetails.color : "transparent"
isOwner: root.isOwnerTokenType
}
}
Component {
id: collectibleimage
StatusRoundedMedia {
id: collectibleImage
readonly property bool isEmpty: !mediaUrl.toString() && !fallbackImageUrl.toString()
width: 248
height: width
radius: Style.current.radius
color: isError || isEmpty ? Theme.palette.baseColor5 : collectible.backgroundColor
border.color: Theme.palette.directColor8
border.width: 1
mediaUrl: collectible.mediaUrl ?? ""
mediaType: modelIndex === 0 && !!collectible ? collectible.mediaType : ""
fallbackImageUrl: collectible.imageUrl
Column {
anchors.centerIn: parent
visible: collectibleImage.isError || collectibleImage.isEmpty
spacing: 10
StatusIcon {
anchors.horizontalCenter: parent.horizontalCenter
icon: "frowny"
opacity: 0.1
color: Theme.palette.directColor1
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Qt.AlignHCenter
color: Theme.palette.directColor6
text: {
if (collectibleImage.isError && collectibleImage.componentMediaType === StatusRoundedMedia.MediaType.Unkown) {
return qsTr("Unsupported\nfile format")
}
if (!collectible.description && !collectible.name) {
return qsTr("Info can't\nbe fetched")
}
return qsTr("Failed\nto load")
}
}
}
}
}
}