feat(@desktop/wallet): implement collectible details activity tab

Fixes #12311
This commit is contained in:
Dario Gabriel Lipicar 2024-02-25 23:32:59 -03:00 committed by dlipicar
parent 82e197da88
commit 10c44b8038
13 changed files with 627 additions and 35 deletions

View File

@ -197,6 +197,9 @@ QtObject:
self.status.setLoadingCollectibles(false)
error "error fetching collectibles: ", res.error
return
proc resetFilter*(self: Controller) {.slot.} =
self.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
proc setFilterTime*(self: Controller, startTimestamp: int, endTimestamp: int) {.slot.} =
self.currentActivityFilter.period = backend_activity.newPeriod(startTimestamp, endTimestamp)
@ -424,7 +427,7 @@ QtObject:
var addresses = newSeq[string]()
for i in 0 ..< addressesJson.len:
if addressesJson[i].kind != JString:
error "not string entry in the json adday for index ", i
error "not string entry in the addresses json array for index ", i
return
addresses.add(addressesJson[i].getStr())
@ -441,6 +444,21 @@ QtObject:
self.status.emitFilterChainsChanged()
self.updateAssetsIdentities()
proc setFilterChainsJson*(self: Controller, jsonArray: string, allChainsSelected: bool) {.slot.} =
let chainsJson = parseJson(jsonArray)
if chainsJson.kind != JArray:
error "invalid array of json ints"
return
var chains = newSeq[int]()
for i in 0 ..< chainsJson.len:
if chainsJson[i].kind != JInt:
error "not int entry in the chains json array for index ", i
return
chains.add(chainsJson[i].getInt())
self.setFilterChains(chains, allChainsSelected)
proc updateRecipientsModel*(self: Controller) {.slot.} =
self.status.setLoadingRecipients(true)
let res = backend_activity.getRecipientsAsync(self.requestId, self.chainIds, self.addresses, 0, FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)

View File

@ -51,7 +51,8 @@ export io_interface
type
ActivityID = enum
History
Temporary
Temporary0
Temporary1
Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface
@ -84,8 +85,11 @@ type
activityController: activityc.Controller
collectibleDetailsController: collectible_detailsc.Controller
# instance to be used in temporary, short-lived, workflows (e.g. send popup)
tmpActivityController: activityc.Controller
# Instances to be used in temporary, short-lived, workflows (e.g. send popup). There's probably tidier ways of
# doing this (one for each required module, create them dynamically) but for now this will do.
# We need one for each app "layer" that simultaneously needs to show a different list of activity
# entries (e.g. send popup is one "layer" above the collectible details activity tab)
tmpActivityControllers: ActivityControllerArray
wcController: wcc.Controller
@ -139,14 +143,18 @@ proc newModule*(
result.transactionService = transactionService
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService,
savedAddressService, events)
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService,
result.tmpActivityControllers = [
activityc.newController(int32(ActivityID.Temporary0), currencyService, tokenService,
savedAddressService, events),
activityc.newController(int32(ActivityID.Temporary1), currencyService, tokenService,
savedAddressService, events)
]
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
result.filter = initFilter(result.controller)
result.wcController = wcc.newController(events, walletAccountService)
result.view = newView(result, result.activityController, result.tmpActivityController, result.collectibleDetailsController, result.wcController)
result.view = newView(result, result.activityController, result.tmpActivityControllers, result.collectibleDetailsController, result.wcController)
method delete*(self: Module) =
self.accountsModule.delete
@ -159,7 +167,8 @@ method delete*(self: Module) =
self.controller.delete
self.view.delete
self.activityController.delete
self.tmpActivityController.delete
for i in 0..self.tmpActivityControllers.len-1:
self.tmpActivityControllers[i].delete
self.collectibleDetailsController.delete
self.wcController.delete

View File

@ -6,6 +6,9 @@ import ./io_interface
import ../../shared_models/currency_amount
import ./wallet_connect/controller as wcc
type
ActivityControllerArray* = array[2, activityc.Controller]
QtObject:
type
View* = ref object of QObject
@ -16,7 +19,7 @@ QtObject:
tmpAmount: float # shouldn't be used anywhere except in prepare*/getPrepared* procs
tmpSymbol: string # shouldn't be used anywhere except in prepare*/getPrepared* procs
activityController: activityc.Controller
tmpActivityController: activityc.Controller
tmpActivityControllers: ActivityControllerArray
collectibleDetailsController: collectible_detailsc.Controller
isNonArchivalNode: bool
keypairOperabilityForObservedAccount: string
@ -31,11 +34,11 @@ QtObject:
proc delete*(self: View) =
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface, activityController: activityc.Controller, tmpActivityController: activityc.Controller, collectibleDetailsController: collectible_detailsc.Controller, wcController: wcc.Controller): View =
proc newView*(delegate: io_interface.AccessInterface, activityController: activityc.Controller, tmpActivityControllers: ActivityControllerArray, collectibleDetailsController: collectible_detailsc.Controller, wcController: wcc.Controller): View =
new(result, delete)
result.delegate = delegate
result.activityController = activityController
result.tmpActivityController = tmpActivityController
result.tmpActivityControllers = tmpActivityControllers
result.collectibleDetailsController = collectibleDetailsController
result.wcController = wcController
@ -151,10 +154,15 @@ QtObject:
QtProperty[QVariant] collectibleDetailsController:
read = getCollectibleDetailsController
proc getTmpActivityController(self: View): QVariant {.slot.} =
return newQVariant(self.tmpActivityController)
QtProperty[QVariant] tmpActivityController:
read = getTmpActivityController
proc getTmpActivityController0(self: View): QVariant {.slot.} =
return newQVariant(self.tmpActivityControllers[0])
QtProperty[QVariant] tmpActivityController0:
read = getTmpActivityController0
proc getTmpActivityController1(self: View): QVariant {.slot.} =
return newQVariant(self.tmpActivityControllers[1])
QtProperty[QVariant] tmpActivityController1:
read = getTmpActivityController1
proc getLatestBlockNumber*(self: View, chainId: int): string {.slot.} =
return self.delegate.getLatestBlockNumber(chainId)

View File

@ -0,0 +1,134 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Storybook 1.0
import AppLayouts.Wallet 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStores
import AppLayouts.Wallet.views.collectibles 1.0
import StatusQ.Core.Utils 0.1
import shared.controls 1.0
import shared.stores 1.0
import Models 1.0
import utils 1.0
SplitView {
id: root
QtObject {
id: d
readonly property QtObject collectiblesModel: WalletCollectiblesModel {
Component.onCompleted: {
d.refreshCurrentCollectible()
}
}
property var currentCollectible
function refreshCurrentCollectible() {
currentCollectible = ModelUtils.get(collectiblesModel, collectibleComboBox.currentIndex)
}
readonly property QtObject transactionsModel: WalletTransactionsModel{}
}
SplitView {
orientation: Qt.Vertical
SplitView.fillWidth: true
Item {
SplitView.fillWidth: true
SplitView.fillHeight: true
Rectangle {
anchors.fill: viewLoader
anchors.margins: -1
color: "transparent"
border.width: 1
border.color: "#808080"
}
Loader {
id: viewLoader
anchors.fill: parent
anchors.margins: 50
active: false
sourceComponent: CollectibleDetailView {
collectible: d.currentCollectible
isCollectibleLoading: isLoadingCheckbox.checked
activityModel: d.transactionsModel
rootStore: QtObject {
readonly property string currentCurrency: "EUR"
function getFiatValue(cryptoValue, symbol) {
return cryptoValue * 0.1;
}
function formatCurrencyAmount(cryptoValue, symbol) {
return "%L1 %2".arg(cryptoValue).arg(symbol)
}
function getNetworkFullName(chainId) {
return chainId
}
function getNetworkColor(chainId) {
return "pink"
}
}
walletRootStore: QtObject {
function getNameForAddress(address) {
return "NAMEFOR: %1".arg(address)
}
readonly property bool showAllAccounts: true
}
communitiesStore: QtObject {
function getCommunityDetailsAsJson(communityId) {
return ""
}
}
}
Component.onCompleted: viewLoader.active = true
}
}
LogsAndControlsPanel {
SplitView.minimumHeight: 100
SplitView.preferredHeight: 150
SplitView.fillWidth: true
}
}
Pane {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 300
ColumnLayout {
Label {
text: "Collectible:"
}
ComboBox {
id: collectibleComboBox
Layout.fillWidth: true
textRole: "name"
model: d.collectiblesModel
currentIndex: 0
onCurrentIndexChanged: d.refreshCurrentCollectible()
}
CheckBox {
id: isLoadingCheckbox
text: "isLoading"
checked: false
}
}
}
}
// category: Wallet

View File

@ -1,5 +1,8 @@
import QtQuick 2.15
import StatusQ.Core 0.1
import utils 1.0
ListModel {
readonly property var rootData: [
{
@ -9,8 +12,29 @@ ListModel {
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",
@ -19,8 +43,29 @@ ListModel {
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",
@ -29,8 +74,29 @@ ListModel {
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",
@ -39,8 +105,29 @@ ListModel {
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",
@ -49,8 +136,29 @@ ListModel {
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"
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",
@ -59,8 +167,21 @@ ListModel {
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",
@ -69,8 +190,21 @@ ListModel {
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",
@ -79,8 +213,34 @@ ListModel {
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
}
]

View File

@ -0,0 +1,187 @@
import QtQuick 2.15
import StatusQ 0.1
import StatusQ.Core 0.1
import utils 1.0
ListModel {
readonly property var rootData: [
{
activityEntry: {
timestamp: Date.now() / 1000,
status: 0,
amount: 123.45,
inAmount: 123.45,
outAmount: 123.45,
symbol: "SNT",
inSymbol: "SNT",
outSymbol: "SNT",
isMultiTransaction: false,
txType: 0,
sender: "0xfB8131c260749c7835a08ccBdb64728De432858E",
recipient: "0x3fb81384583b3910BB14Cc72582E8e8a56E83ae9",
isNFT: false,
isCommunityAssetViaAirdrop: false,
communityName: "Doodles",
communityImageUrl: Style.png("collectibles/HappyMeow"),
tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337",
tokenAddress: "0xdeadbeef",
tokenInAddress: "0xdeadbeef-00",
tokenOutAddress: "0xdeadbeef-00",
nftName: "Happy Meow NFT",
nftImageUrl: Style.png("collectibles/HappyMeow"),
chainId: "NETWORKID",
chainIdIn: "NETWORKID-IN",
chainIdOut: "NETWORKID-OUT"
}
},
{
activityEntry: {
timestamp: Date.now() / 1000,
status: 0,
amount: 123.45,
inAmount: 123.45,
outAmount: 123.45,
symbol: "SNT",
inSymbol: "SNT",
outSymbol: "SNT",
isMultiTransaction: false,
txType: 0,
sender: "0xfB8131c260749c7835a08ccBdb64728De432858E",
recipient: "0x3fb81384583b3910BB14Cc72582E8e8a56E83ae9",
isNFT: false,
isCommunityAssetViaAirdrop: false,
communityName: "Doodles",
communityImageUrl: Style.png("collectibles/HappyMeow"),
tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337",
tokenAddress: "0xdeadbeef",
tokenInAddress: "0xdeadbeef-00",
tokenOutAddress: "0xdeadbeef-00",
nftName: "Happy Meow NFT",
nftImageUrl: Style.png("collectibles/HappyMeow"),
chainId: "NETWORKID",
chainIdIn: "NETWORKID-IN",
chainIdOut: "NETWORKID-OUT"
}
},
{
activityEntry: {
timestamp: Date.now() / 1000,
status: 0,
amount: 123.45,
inAmount: 123.45,
outAmount: 123.45,
symbol: "SNT",
inSymbol: "SNT",
outSymbol: "SNT",
isMultiTransaction: false,
txType: 0,
sender: "0xfB8131c260749c7835a08ccBdb64728De432858E",
recipient: "0x3fb81384583b3910BB14Cc72582E8e8a56E83ae9",
isNFT: false,
isCommunityAssetViaAirdrop: false,
communityName: "Doodles",
communityImageUrl: Style.png("collectibles/HappyMeow"),
tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337",
tokenAddress: "0xdeadbeef",
tokenInAddress: "0xdeadbeef-00",
tokenOutAddress: "0xdeadbeef-00",
nftName: "Happy Meow NFT",
nftImageUrl: Style.png("collectibles/HappyMeow"),
chainId: "NETWORKID",
chainIdIn: "NETWORKID-IN",
chainIdOut: "NETWORKID-OUT"
}
},
{
activityEntry: {
timestamp: Date.now() / 1000,
status: 0,
amount: 123.45,
inAmount: 123.45,
outAmount: 123.45,
symbol: "SNT",
inSymbol: "SNT",
outSymbol: "SNT",
isMultiTransaction: false,
txType: 0,
sender: "0xfB8131c260749c7835a08ccBdb64728De432858E",
recipient: "0x3fb81384583b3910BB14Cc72582E8e8a56E83ae9",
isNFT: false,
isCommunityAssetViaAirdrop: false,
communityName: "Doodles",
communityImageUrl: Style.png("collectibles/HappyMeow"),
tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337",
tokenAddress: "0xdeadbeef",
tokenInAddress: "0xdeadbeef-00",
tokenOutAddress: "0xdeadbeef-00",
nftName: "Happy Meow NFT",
nftImageUrl: Style.png("collectibles/HappyMeow"),
chainId: "NETWORKID",
chainIdIn: "NETWORKID-IN",
chainIdOut: "NETWORKID-OUT"
}
},
{
activityEntry: {
timestamp: Date.now() / 1000,
status: 0,
amount: 123.45,
inAmount: 123.45,
outAmount: 123.45,
symbol: "SNT",
inSymbol: "SNT",
outSymbol: "SNT",
isMultiTransaction: false,
txType: 0,
sender: "0xfB8131c260749c7835a08ccBdb64728De432858E",
recipient: "0x3fb81384583b3910BB14Cc72582E8e8a56E83ae9",
isNFT: false,
isCommunityAssetViaAirdrop: false,
communityName: "Doodles",
communityImageUrl: Style.png("collectibles/HappyMeow"),
tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337",
tokenAddress: "0xdeadbeef",
tokenInAddress: "0xdeadbeef-00",
tokenOutAddress: "0xdeadbeef-00",
nftName: "Happy Meow NFT",
nftImageUrl: Style.png("collectibles/HappyMeow"),
chainId: "NETWORKID",
chainIdIn: "NETWORKID-IN",
chainIdOut: "NETWORKID-OUT"
}
},
{
activityEntry: {
timestamp: Date.now() / 1000,
status: 0,
amount: 123.45,
inAmount: 123.45,
outAmount: 123.45,
symbol: "SNT",
inSymbol: "SNT",
outSymbol: "SNT",
isMultiTransaction: false,
txType: 0,
sender: "0xfB8131c260749c7835a08ccBdb64728De432858E",
recipient: "0x3fb81384583b3910BB14Cc72582E8e8a56E83ae9",
isNFT: false,
isCommunityAssetViaAirdrop: false,
communityName: "Doodles",
communityImageUrl: Style.png("collectibles/HappyMeow"),
tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337",
tokenAddress: "0xdeadbeef",
tokenInAddress: "0xdeadbeef-00",
tokenOutAddress: "0xdeadbeef-00",
nftName: "Happy Meow NFT",
nftImageUrl: Style.png("collectibles/HappyMeow"),
chainId: "NETWORKID",
chainIdIn: "NETWORKID-IN",
chainIdOut: "NETWORKID-OUT"
}
},
]
Component.onCompleted: append(rootData)
}

View File

@ -19,6 +19,7 @@ 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
GroupedAccountsAssetsModel 1.0 GroupedAccountsAssetsModel.qml
TokensBySymbolModel 1.0 TokensBySymbolModel.qml
CommunitiesModel 1.0 CommunitiesModel.qml

View File

@ -50,7 +50,8 @@ QtObject {
property var walletSectionSavedAddressesInst: walletSectionSavedAddresses
property var totalCurrencyBalance: walletSectionInst.totalCurrencyBalance
property var activityController: walletSectionInst.activityController
property var tmpActivityController: walletSectionInst.tmpActivityController
property var tmpActivityController0: walletSectionInst.tmpActivityController0
property var tmpActivityController1: walletSectionInst.tmpActivityController1
property string signingPhrase: walletSectionInst.signingPhrase
property string mnemonicBackedUp: walletSectionInst.isMnemonicBackedUp
property var walletConnectController: walletSectionInst.walletConnectController

View File

@ -8,7 +8,7 @@ import StatusQ.Core.Theme 0.1
import utils 1.0
import shared.controls 1.0
import shared.views 1.0
import shared.stores 1.0
import shared.stores 1.0 as SharedStores
import shared.panels 1.0
import "./"
@ -69,6 +69,8 @@ RightTabBaseView {
return ""
}
}
readonly property var detailedCollectibleActivityController: RootStore.tmpActivityController0
}
ColumnLayout {
@ -174,6 +176,12 @@ RightTabBaseView {
onCollectibleClicked: {
RootStore.collectiblesStore.getDetailedCollectible(chainId, contractAddress, tokenId)
RootStore.setCurrentViewedHolding(uid, Constants.TokenType.ERC721)
d.detailedCollectibleActivityController.resetFilter()
d.detailedCollectibleActivityController.setFilterAddressesJson(JSON.stringify(RootStore.addressFilters.split(":")), RootStore.showAllAccounts)
d.detailedCollectibleActivityController.setFilterChainsJson(JSON.stringify([chainId]), false)
d.detailedCollectibleActivityController.setFilterCollectibles(JSON.stringify([uid]))
d.detailedCollectibleActivityController.updateFilter()
stack.currentIndex = 1
}
onSendRequested: (symbol) => {
@ -212,10 +220,15 @@ RightTabBaseView {
CollectibleDetailView {
collectible: RootStore.collectiblesStore.detailedCollectible
isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading
activityModel: d.detailedCollectibleActivityController.model
rootStore: SharedStores.RootStore
walletRootStore: RootStore
communitiesStore: root.communitiesStore
onVisibleChanged: {
if (!visible)
if (!visible) {
RootStore.resetCurrentViewedHolding(Constants.TokenType.ERC721)
}
}
}
AssetsDetailView {

View File

@ -11,6 +11,7 @@ import AppLayouts.Communities.panels 1.0
import utils 1.0
import shared.controls 1.0
import shared.views 1.0
import "../../stores"
import "../../controls"
@ -18,7 +19,12 @@ import "../../controls"
Item {
id: root
property var collectible
required property var rootStore
required property var walletRootStore
required property var communitiesStore
required property var collectible
property var activityModel
property bool isCollectibleLoading
readonly property int isNarrowMode : width < 700
@ -70,7 +76,7 @@ Item {
visible: root.isCommunityCollectible && (root.isOwnerTokenType || root.isTMasterTokenType)
size: root.isNarrowMode ? PrivilegedTokenArtworkPanel.Size.Medium : PrivilegedTokenArtworkPanel.Size.Large
artwork: collectible.imageUrl
color: !!collectible ? collectible.communityColor : "transparent"
color: !!collectible && root.isCommunityCollectible? collectible.communityColor : "transparent"
isOwner: root.isOwnerTokenType
}
@ -86,8 +92,8 @@ Item {
color: collectible.backgroundColor
border.color: Theme.palette.directColor8
border.width: 1
mediaUrl: collectible.mediaUrl
mediaType: collectible.mediaType
mediaUrl: collectible.mediaUrl ?? ""
mediaType: collectible.mediaType ?? ""
fallbackImageUrl: collectible.imageUrl
}
@ -147,6 +153,11 @@ Item {
width: implicitWidth
text: qsTr("Properties")
}
StatusTabButton {
rightPadding: 0
width: implicitWidth
text: qsTr("Activity")
}
}
StatusScrollView {
@ -154,15 +165,56 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
contentWidth: availableWidth
Flow {
width: scrollView.availableWidth
spacing: 10
Repeater {
model: collectible.traits
InformationTile {
maxWidth: parent.width
primaryText: model.traitType
secondaryText: model.value
Loader {
id: tabLoader
Layout.fillWidth: true
Layout.fillHeight: true
sourceComponent: {
switch (collectiblesDetailsTab.currentIndex) {
case 0: return traitsView
case 1: return activityView
}
}
Component {
id: traitsView
Flow {
width: scrollView.availableWidth
spacing: 10
Repeater {
model: collectible.traits
InformationTile {
maxWidth: parent.width
primaryText: model.traitType
secondaryText: model.value
}
}
}
}
Component {
id: activityView
StatusListView {
width: scrollView.availableWidth
height: scrollView.availableHeight
model: root.activityModel
delegate: TransactionDelegate {
required property var model
required property int index
width: parent.width
modelData: model.activityEntry
timeStampText: isModelDataValid ? LocaleUtils.formatRelativeTimestamp(modelData.timestamp * 1000, true) : ""
rootStore: root.rootStore
walletRootStore: root.walletRootStore
showAllAccounts: root.walletRootStore.showAllAccounts
displayValues: true
community: isModelDataValid && !!communityId && !!root.communitiesStore ? root.communitiesStore.getCommunityDetailsAsJson(communityId) : null
loading: false
onClicked: {
// TODO: Implement switch to transaction details screen
}
}
}
}
}

View File

@ -1 +1,2 @@
CollectibleDetailView 1.0 CollectibleDetailView.qml
CollectibleView 1.0 CollectibleView.qml

View File

@ -37,6 +37,13 @@ Item {
None
}
QtObject {
id: d
// Use Layer1 controller since this could go on top of other activity lists
readonly property var activityController: root.store.tmpActivityController1
}
StatusTabBar {
id: accountSelectionTabBar
anchors.top: parent.top
@ -174,7 +181,7 @@ Item {
onClicked: recipientSelected(entry, TabAddressSelectorView.Type.RecentsAddress)
}
model: root.store.tmpActivityController.model
model: d.activityController.model
onVisibleChanged: {
if (visible) {
@ -193,9 +200,9 @@ Item {
function updateRecentsActivity() {
if(root.selectedAccount) {
root.store.tmpActivityController.setFilterAddressesJson(JSON.stringify([root.selectedAccount.address], false))
d.activityController.setFilterAddressesJson(JSON.stringify([root.selectedAccount.address]), false)
}
root.store.tmpActivityController.updateFilter()
d.activityController.updateFilter()
}
}
}

View File

@ -30,7 +30,8 @@ QtObject {
property var collectiblesModel: walletSectionSendInst.collectiblesModel
property var nestedCollectiblesModel: walletSectionSendInst.nestedCollectiblesModel
property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled
property var tmpActivityController: walletSection.tmpActivityController
property var tmpActivityController0: walletSection.tmpActivityController0
property var tmpActivityController1: walletSection.tmpActivityController1
property var savedAddressesModel: SortFilterProxyModel {
sourceModel: walletSectionSavedAddresses.model
filters: [