parent
6ec562c6b2
commit
30294f97fe
|
@ -30,23 +30,14 @@ proc newController*(
|
||||||
proc delete*(self: Controller) =
|
proc delete*(self: Controller) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc refreshCollections*(self: Controller, chainId: int, address: string) =
|
proc refreshCollectibles*(self: Controller, chainId: int, address: string) =
|
||||||
let collections = self.collectibleService.getOwnedCollections(chainId, address)
|
let collectibles = self.collectibleService.getOwnedCollectibles(chainId, address)
|
||||||
self.delegate.setCollections(collections)
|
self.delegate.refreshCollectibles(chainId, address, collectibles)
|
||||||
|
|
||||||
proc refreshCollectibles*(self: Controller, chainId: int, address: string, collectionSlug: string) =
|
proc init*(self: Controller) =
|
||||||
let collection = self.collectibleService.getOwnedCollection(chainId, address, collectionSlug)
|
self.events.on(SIGNAL_OWNED_COLLECTIBLES_UPDATE_FINISHED) do(e:Args):
|
||||||
self.delegate.updateCollection(collection)
|
|
||||||
|
|
||||||
proc init*(self: Controller) =
|
|
||||||
self.events.on(SIGNAL_OWNED_COLLECTIONS_UPDATED) do(e:Args):
|
|
||||||
let args = OwnedCollectionsUpdateArgs(e)
|
|
||||||
self.refreshCollections(args.chainId, args.address)
|
|
||||||
self.collectibleService.fetchAllOwnedCollectibles(args.chainId, args.address)
|
|
||||||
|
|
||||||
self.events.on(SIGNAL_OWNED_COLLECTIBLES_UPDATED) do(e:Args):
|
|
||||||
let args = OwnedCollectiblesUpdateArgs(e)
|
let args = OwnedCollectiblesUpdateArgs(e)
|
||||||
self.refreshCollectibles(args.chainId, args.address, args.collectionSlug)
|
self.refreshCollectibles(args.chainId, args.address)
|
||||||
|
|
||||||
proc getWalletAccount*(self: Controller, accountIndex: int): wallet_account_service.WalletAccountDto =
|
proc getWalletAccount*(self: Controller, accountIndex: int): wallet_account_service.WalletAccountDto =
|
||||||
return self.walletAccountService.getWalletAccount(accountIndex)
|
return self.walletAccountService.getWalletAccount(accountIndex)
|
||||||
|
@ -54,8 +45,14 @@ proc getWalletAccount*(self: Controller, accountIndex: int): wallet_account_serv
|
||||||
proc getNetwork*(self: Controller): network_service.NetworkDto =
|
proc getNetwork*(self: Controller): network_service.NetworkDto =
|
||||||
return self.networkService.getNetworkForCollectibles()
|
return self.networkService.getNetworkForCollectibles()
|
||||||
|
|
||||||
proc fetchOwnedCollections*(self: Controller, chainId: int, address: string) =
|
proc resetOwnedCollectibles*(self: Controller, chainId: int, address: string) =
|
||||||
self.collectibleService.fetchOwnedCollections(chainId, address)
|
self.collectibleService.resetOwnedCollectibles(chainId, address)
|
||||||
|
|
||||||
proc fetchOwnedCollectibles*(self: Controller, chainId: int, address: string, collectionSlug: string) =
|
proc fetchOwnedCollectibles*(self: Controller, chainId: int, address: string, limit: int) =
|
||||||
self.collectibleService.fetchOwnedCollectibles(chainId, address, collectionSlug)
|
self.collectibleService.fetchOwnedCollectibles(chainId, address, limit)
|
||||||
|
|
||||||
|
proc getCollectible*(self: Controller, chainId: int, id: UniqueID) : CollectibleDto =
|
||||||
|
self.collectibleService.getCollectible(chainId, id)
|
||||||
|
|
||||||
|
proc getCollection*(self: Controller, chainId: int, slug: string) : CollectionDto =
|
||||||
|
self.collectibleService.getCollection(chainId, slug)
|
||||||
|
|
|
@ -29,6 +29,7 @@ method setCurrentAddress*(self: Controller, network: network_dto.NetworkDto, add
|
||||||
self.network = network
|
self.network = network
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
proc update*(self: Controller, collectionSlug: string, id: int) =
|
proc update*(self: Controller, id: collectible_service.UniqueID) =
|
||||||
let collection = self.collectibleService.getOwnedCollection(self.network.chainId, self.address, collectionSlug)
|
let collectible = self.collectibleService.getCollectible(self.network.chainId, id)
|
||||||
self.delegate.setData(collection.collection, collection.collectibles[id], self.network)
|
let collection = self.collectibleService.getCollection(self.network.chainId, collectible.collectionSlug)
|
||||||
|
self.delegate.setData(collection, collectible, self.network)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import stint
|
||||||
import ../../../../../../app_service/service/network/dto as network_dto
|
import ../../../../../../app_service/service/network/dto as network_dto
|
||||||
import ../../../../../../app_service/service/collectible/dto as collectible_dto
|
import ../../../../../../app_service/service/collectible/dto as collectible_dto
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||||
method setCurrentAddress*(self: AccessInterface, network: network_dto.NetworkDto, address: string) {.base.} =
|
method setCurrentAddress*(self: AccessInterface, network: network_dto.NetworkDto, address: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method update*(self: AccessInterface, collectionSlug: string, id: int) {.base.} =
|
method update*(self: AccessInterface, address: string, tokenId: Uint256) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method setData*(self: AccessInterface, collection: collectible_dto.CollectionDto, collectible: collectible_dto.CollectibleDto, network: network_dto.NetworkDto) {.base.} =
|
method setData*(self: AccessInterface, collection: collectible_dto.CollectionDto, collectible: collectible_dto.CollectibleDto, network: network_dto.NetworkDto) {.base.} =
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import NimQml, sequtils, sugar
|
import NimQml, sequtils, sugar, stint
|
||||||
|
|
||||||
import ../../../../../global/global_singleton
|
import ../../../../../global/global_singleton
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@ import ../../../../../../app_service/service/collectible/service as collectible_
|
||||||
import ../../../../../../app_service/service/collectible/dto as collectible_dto
|
import ../../../../../../app_service/service/collectible/dto as collectible_dto
|
||||||
import ../../../../../../app_service/service/network/dto as network_dto
|
import ../../../../../../app_service/service/network/dto as network_dto
|
||||||
|
|
||||||
|
import ../models/collectibles_item as collectibles_item
|
||||||
|
import ../models/collectibles_utils
|
||||||
|
|
||||||
export io_interface
|
export io_interface
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -45,8 +48,13 @@ method viewDidLoad*(self: Module) =
|
||||||
method setCurrentAddress*(self: Module, network: network_dto.NetworkDto, address: string) =
|
method setCurrentAddress*(self: Module, network: network_dto.NetworkDto, address: string) =
|
||||||
self.controller.setCurrentAddress(network, address)
|
self.controller.setCurrentAddress(network, address)
|
||||||
|
|
||||||
method update*(self: Module, collectionSlug: string, id: int) =
|
method update*(self: Module, address: string, tokenId: Uint256) =
|
||||||
self.controller.update(collectionSlug, id)
|
let id = collectible_dto.UniqueID(
|
||||||
|
contractAddress: address,
|
||||||
|
tokenId: tokenId
|
||||||
|
)
|
||||||
|
self.controller.update(id)
|
||||||
|
|
||||||
method setData*(self: Module, collection: collectible_dto.CollectionDto, collectible: collectible_dto.CollectibleDto, network: network_dto.NetworkDto) =
|
method setData*(self: Module, collection: collectible_dto.CollectionDto, collectible: collectible_dto.CollectibleDto, network: network_dto.NetworkDto) =
|
||||||
self.view.setData(collection, collectible, network)
|
let item = collectibleToItem(collectible, collection)
|
||||||
|
self.view.setData(item, network)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import NimQml, sequtils, sugar, stint
|
||||||
|
|
||||||
import ./io_interface
|
import ./io_interface
|
||||||
import ../../../../../../app_service/service/network/dto as network_dto
|
import ../../../../../../app_service/service/network/dto as network_dto
|
||||||
import ../../../../../../app_service/service/collectible/dto as collectible_dto
|
import ../models/collectibles_item
|
||||||
import ../models/collectible_trait_item
|
import ../models/collectible_trait_item
|
||||||
import ../models/collectible_trait_model
|
import ../models/collectible_trait_model
|
||||||
|
|
||||||
|
@ -15,16 +15,7 @@ QtObject:
|
||||||
networkColor: string
|
networkColor: string
|
||||||
networkIconUrl: string
|
networkIconUrl: string
|
||||||
|
|
||||||
collectionName: string
|
collectible: Item
|
||||||
collectionImageUrl: string
|
|
||||||
|
|
||||||
name: string
|
|
||||||
id: string
|
|
||||||
tokenId: string
|
|
||||||
description: string
|
|
||||||
backgroundColor: string
|
|
||||||
imageUrl: string
|
|
||||||
permalink: string
|
|
||||||
propertiesModel: TraitModel
|
propertiesModel: TraitModel
|
||||||
rankingsModel: TraitModel
|
rankingsModel: TraitModel
|
||||||
statsModel: TraitModel
|
statsModel: TraitModel
|
||||||
|
@ -39,8 +30,7 @@ QtObject:
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result.setup()
|
result.setup()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.description = "Collectibles"
|
result.collectible = initItem()
|
||||||
result.backgroundColor = "transparent"
|
|
||||||
result.propertiesModel = newTraitModel()
|
result.propertiesModel = newTraitModel()
|
||||||
result.rankingsModel = newTraitModel()
|
result.rankingsModel = newTraitModel()
|
||||||
result.statsModel = newTraitModel()
|
result.statsModel = newTraitModel()
|
||||||
|
@ -76,7 +66,7 @@ QtObject:
|
||||||
notify = networkIconUrlChanged
|
notify = networkIconUrlChanged
|
||||||
|
|
||||||
proc getName(self: View): QVariant {.slot.} =
|
proc getName(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.name)
|
return newQVariant(self.collectible.getName())
|
||||||
|
|
||||||
proc nameChanged(self: View) {.signal.}
|
proc nameChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -85,7 +75,7 @@ QtObject:
|
||||||
notify = nameChanged
|
notify = nameChanged
|
||||||
|
|
||||||
proc getID(self: View): QVariant {.slot.} =
|
proc getID(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.id)
|
return newQVariant(self.collectible.getId())
|
||||||
|
|
||||||
proc idChanged(self: View) {.signal.}
|
proc idChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -94,7 +84,7 @@ QtObject:
|
||||||
notify = idChanged
|
notify = idChanged
|
||||||
|
|
||||||
proc getTokenID(self: View): QVariant {.slot.} =
|
proc getTokenID(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.tokenId)
|
return newQVariant(self.collectible.getTokenId().toString())
|
||||||
|
|
||||||
proc tokenIdChanged(self: View) {.signal.}
|
proc tokenIdChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -103,7 +93,7 @@ QtObject:
|
||||||
notify = tokenIdChanged
|
notify = tokenIdChanged
|
||||||
|
|
||||||
proc getDescription(self: View): QVariant {.slot.} =
|
proc getDescription(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.description)
|
return newQVariant(self.collectible.getDescription())
|
||||||
|
|
||||||
proc descriptionChanged(self: View) {.signal.}
|
proc descriptionChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -112,7 +102,7 @@ QtObject:
|
||||||
notify = descriptionChanged
|
notify = descriptionChanged
|
||||||
|
|
||||||
proc getBackgroundColor(self: View): QVariant {.slot.} =
|
proc getBackgroundColor(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.backgroundColor)
|
return newQVariant(self.collectible.getBackgroundColor())
|
||||||
|
|
||||||
proc backgroundColorChanged(self: View) {.signal.}
|
proc backgroundColorChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -121,7 +111,7 @@ QtObject:
|
||||||
notify = backgroundColorChanged
|
notify = backgroundColorChanged
|
||||||
|
|
||||||
proc getImageUrl(self: View): QVariant {.slot.} =
|
proc getImageUrl(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.imageUrl)
|
return newQVariant(self.collectible.getImageUrl())
|
||||||
|
|
||||||
proc imageUrlChanged(self: View) {.signal.}
|
proc imageUrlChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -130,7 +120,7 @@ QtObject:
|
||||||
notify = imageUrlChanged
|
notify = imageUrlChanged
|
||||||
|
|
||||||
proc getCollectionName(self: View): QVariant {.slot.} =
|
proc getCollectionName(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.collectionName)
|
return newQVariant(self.collectible.getCollectionName())
|
||||||
|
|
||||||
proc collectionNameChanged(self: View) {.signal.}
|
proc collectionNameChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -139,7 +129,7 @@ QtObject:
|
||||||
notify = collectionNameChanged
|
notify = collectionNameChanged
|
||||||
|
|
||||||
proc getCollectionImageUrl(self: View): QVariant {.slot.} =
|
proc getCollectionImageUrl(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.collectionImageUrl)
|
return newQVariant(self.collectible.getCollectionImageUrl())
|
||||||
|
|
||||||
proc collectionImageUrlChanged(self: View) {.signal.}
|
proc collectionImageUrlChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -148,7 +138,7 @@ QtObject:
|
||||||
notify = collectionImageUrlChanged
|
notify = collectionImageUrlChanged
|
||||||
|
|
||||||
proc getPermalink(self: View): QVariant {.slot.} =
|
proc getPermalink(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.permalink)
|
return newQVariant(self.collectible.getPermalink())
|
||||||
|
|
||||||
proc permalinkChanged(self: View) {.signal.}
|
proc permalinkChanged(self: View) {.signal.}
|
||||||
|
|
||||||
|
@ -179,14 +169,14 @@ QtObject:
|
||||||
proc getStats*(self: View): QVariant {.slot.} =
|
proc getStats*(self: View): QVariant {.slot.} =
|
||||||
return newQVariant(self.statsModel)
|
return newQVariant(self.statsModel)
|
||||||
|
|
||||||
QtProperty[QVariant] rankings:
|
QtProperty[QVariant] stats:
|
||||||
read = getStats
|
read = getStats
|
||||||
notify = statsChanged
|
notify = statsChanged
|
||||||
|
|
||||||
proc update*(self: View, collectionSlug: string, id: int) {.slot.} =
|
proc update*(self: View, address: string, tokenId: string) {.slot.} =
|
||||||
self.delegate.update(collectionSlug, id)
|
self.delegate.update(address, parse(tokenId, Uint256))
|
||||||
|
|
||||||
proc setData*(self: View, collection: collectible_dto.CollectionDto, collectible: collectible_dto.CollectibleDto, network: network_dto.NetworkDto) =
|
proc setData*(self: View, collectible: Item, network: network_dto.NetworkDto) =
|
||||||
if (self.networkShortName != network.shortName):
|
if (self.networkShortName != network.shortName):
|
||||||
self.networkShortName = network.shortName
|
self.networkShortName = network.shortName
|
||||||
self.networkShortNameChanged()
|
self.networkShortNameChanged()
|
||||||
|
@ -199,46 +189,21 @@ QtObject:
|
||||||
self.networkIconUrl = network.iconURL
|
self.networkIconUrl = network.iconURL
|
||||||
self.networkIconUrlChanged()
|
self.networkIconUrlChanged()
|
||||||
|
|
||||||
if (self.collectionName != collection.name):
|
self.collectible = collectible
|
||||||
self.collectionName = collection.name
|
self.collectionNameChanged()
|
||||||
self.collectionNameChanged()
|
self.collectionImageUrlChanged()
|
||||||
|
self.nameChanged()
|
||||||
|
self.idChanged()
|
||||||
|
self.tokenIdChanged()
|
||||||
|
self.descriptionChanged()
|
||||||
|
self.backgroundColorChanged()
|
||||||
|
self.imageUrlChanged()
|
||||||
|
|
||||||
if (self.collectionImageUrl != collection.imageUrl):
|
self.propertiesModel.setItems(collectible.getProperties())
|
||||||
self.collectionImageUrl = collection.imageUrl
|
|
||||||
self.collectionImageUrlChanged()
|
|
||||||
|
|
||||||
if (self.name != collectible.name):
|
|
||||||
self.name = collectible.name
|
|
||||||
self.nameChanged()
|
|
||||||
|
|
||||||
let idString = $collectible.id
|
|
||||||
if (self.id != idString):
|
|
||||||
self.id = idString
|
|
||||||
self.idChanged()
|
|
||||||
|
|
||||||
let tokenIdString = collectible.tokenId.toString()
|
|
||||||
if (self.tokenId != tokenIdString):
|
|
||||||
self.tokenId = tokenIdString
|
|
||||||
self.tokenIdChanged()
|
|
||||||
|
|
||||||
if (self.description != collectible.description):
|
|
||||||
self.description = collectible.description
|
|
||||||
self.descriptionChanged()
|
|
||||||
|
|
||||||
let backgroundColor = if (collectible.backgroundColor == ""): "transparent" else: ("#" & collectible.backgroundColor)
|
|
||||||
if (self.backgroundColor != backgroundColor):
|
|
||||||
self.backgroundColor = backgroundColor
|
|
||||||
self.backgroundColorChanged()
|
|
||||||
|
|
||||||
if (self.imageUrl != collectible.imageUrl):
|
|
||||||
self.imageUrl = collectible.imageUrl
|
|
||||||
self.imageUrlChanged()
|
|
||||||
|
|
||||||
self.propertiesModel.setItems(collectible.properties.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)))
|
|
||||||
self.propertiesChanged()
|
self.propertiesChanged()
|
||||||
|
|
||||||
self.rankingsModel.setItems(collectible.rankings.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)))
|
self.rankingsModel.setItems(collectible.getRankings())
|
||||||
self.rankingsChanged()
|
self.rankingsChanged()
|
||||||
|
|
||||||
self.statsModel.setItems(collectible.statistics.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)))
|
self.statsModel.setItems(collectible.getStats())
|
||||||
self.statsChanged()
|
self.statsChanged()
|
||||||
|
|
|
@ -16,16 +16,10 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||||
method switchAccount*(self: AccessInterface, accountIndex: int) {.base.} =
|
method switchAccount*(self: AccessInterface, accountIndex: int) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method fetchOwnedCollections*(self: AccessInterface) {.base.} =
|
method fetchOwnedCollectibles*(self: AccessInterface, limit: int) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method setCollections*(self: AccessInterface, collections: CollectionsData) {.base.} =
|
method refreshCollectibles*(self: AccessInterface, chainId: int, address: string, collectibles: CollectiblesData) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
|
||||||
|
|
||||||
method fetchOwnedCollectibles*(self: AccessInterface, collectionSlug: string) {.base.} =
|
|
||||||
raise newException(ValueError, "No implementation available")
|
|
||||||
|
|
||||||
method updateCollection*(self: AccessInterface, collection: CollectionData) {.base.} =
|
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||||
|
@ -35,8 +29,5 @@ method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||||
method collectiblesModuleDidLoad*(self: AccessInterface) {.base.} =
|
method collectiblesModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method collectionsModuleDidLoad*(self: AccessInterface) {.base.} =
|
|
||||||
raise newException(ValueError, "No implementation available")
|
|
||||||
|
|
||||||
method currentCollectibleModuleDidLoad*(self: AccessInterface) {.base.} =
|
method currentCollectibleModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
|
@ -1,221 +0,0 @@
|
||||||
import NimQml, Tables, strutils
|
|
||||||
|
|
||||||
import ./collections_model as collections_model
|
|
||||||
import ./collectibles_model as collectibles_model
|
|
||||||
|
|
||||||
type
|
|
||||||
ModelRole* {.pure.} = enum
|
|
||||||
CollectionName = UserRole + 1,
|
|
||||||
CollectionSlug
|
|
||||||
CollectionImageUrl
|
|
||||||
CollectionOwnedAssetCount
|
|
||||||
CollectionCollectiblesCount
|
|
||||||
CollectionCollectiblesLoaded
|
|
||||||
Id
|
|
||||||
Name
|
|
||||||
ImageUrl
|
|
||||||
BackgroundColor
|
|
||||||
Description
|
|
||||||
Permalink
|
|
||||||
Properties
|
|
||||||
Rankings
|
|
||||||
Stats
|
|
||||||
|
|
||||||
const COLLECTION_ROLE_TO_PROXY_ROLE = {
|
|
||||||
CollectionRole.Name: ModelRole.CollectionName,
|
|
||||||
CollectionRole.Slug: ModelRole.CollectionSlug,
|
|
||||||
CollectionRole.ImageUrl: ModelRole.CollectionImageUrl,
|
|
||||||
CollectionRole.OwnedAssetCount: ModelRole.CollectionOwnedAssetCount,
|
|
||||||
CollectionRole.CollectiblesLoaded: ModelRole.CollectionCollectiblesLoaded,
|
|
||||||
}.toTable()
|
|
||||||
|
|
||||||
const COLLECTIBLE_ROLE_TO_PROXY_ROLE = {
|
|
||||||
CollectibleRole.Id: ModelRole.Id,
|
|
||||||
CollectibleRole.Name: ModelRole.Name,
|
|
||||||
CollectibleRole.ImageUrl: ModelRole.ImageUrl,
|
|
||||||
CollectibleRole.BackgroundColor: ModelRole.BackgroundColor,
|
|
||||||
CollectibleRole.Description: ModelRole.Description,
|
|
||||||
CollectibleRole.Permalink: ModelRole.Permalink,
|
|
||||||
CollectibleRole.Properties: ModelRole.Properties,
|
|
||||||
CollectibleRole.Rankings: ModelRole.Rankings,
|
|
||||||
CollectibleRole.Stats: ModelRole.Stats,
|
|
||||||
}.toTable()
|
|
||||||
|
|
||||||
type
|
|
||||||
Index = tuple
|
|
||||||
collectionIdx: int
|
|
||||||
collectibleIdx: int
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type
|
|
||||||
Model* = ref object of QAbstractListModel
|
|
||||||
collectionsModel: collections_model.Model
|
|
||||||
sourceIndexToRow: Table[Index, int]
|
|
||||||
collectionToRows: Table[int, (int, int)]
|
|
||||||
rowToSourceIndex: Table[int, Index]
|
|
||||||
|
|
||||||
proc delete(self: Model) =
|
|
||||||
self.collectionsModel = nil
|
|
||||||
self.QAbstractListModel.delete
|
|
||||||
|
|
||||||
proc setup(self: Model) =
|
|
||||||
self.QAbstractListModel.setup
|
|
||||||
|
|
||||||
proc countChanged(self: Model) {.signal.}
|
|
||||||
proc getCount(self: Model): int {.slot.} =
|
|
||||||
self.sourceIndexToRow.len
|
|
||||||
QtProperty[int] count:
|
|
||||||
read = getCount
|
|
||||||
notify = countChanged
|
|
||||||
|
|
||||||
proc collectionsLoadedChanged(self: Model) {.signal.}
|
|
||||||
proc getCollectionsLoaded*(self: Model): bool {.slot.} =
|
|
||||||
self.collectionsModel.getCollectionsLoaded()
|
|
||||||
QtProperty[bool] collectionsLoaded:
|
|
||||||
read = getCollectionsLoaded
|
|
||||||
notify = collectionsLoadedChanged
|
|
||||||
|
|
||||||
proc collectionCountChanged(self: Model) {.signal.}
|
|
||||||
proc getCollectionCount*(self: Model): int {.slot.} =
|
|
||||||
self.collectionsModel.getCount()
|
|
||||||
QtProperty[int] collectionCount:
|
|
||||||
read = getCollectionCount
|
|
||||||
notify = collectionCountChanged
|
|
||||||
|
|
||||||
proc rebuildMap(self: Model) =
|
|
||||||
self.beginResetModel()
|
|
||||||
self.sourceIndexToRow.clear()
|
|
||||||
self.collectionToRows.clear()
|
|
||||||
self.rowToSourceIndex.clear()
|
|
||||||
var proxy_row = 0
|
|
||||||
for i in 0 ..< self.collectionsModel.getCount():
|
|
||||||
let collectiblesModel = self.collectionsModel.getCollectiblesModel(i)
|
|
||||||
let collectionIndexStart = proxy_row
|
|
||||||
for j in 0 ..< collectiblesModel.getCount():
|
|
||||||
let idx = (collectionIdx: i, collectibleIdx: j)
|
|
||||||
self.sourceIndexToRow[idx] = proxy_row
|
|
||||||
self.rowToSourceIndex[proxy_row] = idx
|
|
||||||
proxy_row += 1
|
|
||||||
self.collectionToRows[i] = (collectionIndexStart, proxy_row - 1)
|
|
||||||
self.endResetModel()
|
|
||||||
self.countChanged()
|
|
||||||
|
|
||||||
proc newModel*(collectionsModel: collections_model.Model): Model =
|
|
||||||
new(result, delete)
|
|
||||||
|
|
||||||
result.collectionsModel = collectionsModel
|
|
||||||
result.setup
|
|
||||||
|
|
||||||
result.rebuildMap()
|
|
||||||
|
|
||||||
signalConnect(result.collectionsModel, "collectionsLoadedChanged()", result, "onCollectionsLoadedChanged()")
|
|
||||||
signalConnect(result.collectionsModel, "countChanged()", result, "onCollectionCountChanged()")
|
|
||||||
signalConnect(result.collectionsModel, "signalDataChanged(int, int, int)", result, "onDataChanged(int, int, int)")
|
|
||||||
|
|
||||||
proc onCollectionsLoadedChanged(self: Model) {.slot.} =
|
|
||||||
self.collectionsLoadedChanged()
|
|
||||||
|
|
||||||
proc onCollectionCountChanged(self: Model) {.slot.} =
|
|
||||||
self.collectionCountChanged()
|
|
||||||
self.rebuildMap()
|
|
||||||
|
|
||||||
proc onDataChanged(self: Model,
|
|
||||||
top: int,
|
|
||||||
bottom: int,
|
|
||||||
role: int) {.slot.} =
|
|
||||||
var topRow = self.collectionToRows[top][0]
|
|
||||||
var bottomRow = self.collectionToRows[bottom][1]
|
|
||||||
|
|
||||||
let topIndex = self.createIndex(topRow, 0, nil)
|
|
||||||
let bottomIndex = self.createIndex(bottomRow, 0, nil)
|
|
||||||
|
|
||||||
if (COLLECTION_ROLE_TO_PROXY_ROLE.hasKey(role.CollectionRole)):
|
|
||||||
self.dataChanged(topIndex, bottomIndex, @[COLLECTION_ROLE_TO_PROXY_ROLE[role.CollectionRole].int])
|
|
||||||
elif role == CollectionRole.CollectiblesModel.int:
|
|
||||||
self.rebuildMap()
|
|
||||||
|
|
||||||
method rowCount*(self: Model, index: QModelIndex = nil): int =
|
|
||||||
return self.getCount()
|
|
||||||
|
|
||||||
method roleNames(self: Model): Table[int, string] =
|
|
||||||
{
|
|
||||||
ModelRole.CollectionName.int:"collectionName",
|
|
||||||
ModelRole.CollectionSlug.int:"collectionSlug",
|
|
||||||
ModelRole.CollectionImageUrl.int:"collectionImageUrl",
|
|
||||||
ModelRole.CollectionOwnedAssetCount.int:"collectionOwnedAssetCount",
|
|
||||||
ModelRole.CollectionCollectiblesCount.int:"collectionCollectiblesCount",
|
|
||||||
ModelRole.CollectionCollectiblesLoaded.int:"collectionCollectiblesLoaded",
|
|
||||||
ModelRole.Id.int:"id",
|
|
||||||
ModelRole.Name.int:"name",
|
|
||||||
ModelRole.ImageUrl.int:"imageUrl",
|
|
||||||
ModelRole.BackgroundColor.int:"backgroundColor",
|
|
||||||
ModelRole.Description.int:"description",
|
|
||||||
ModelRole.Permalink.int:"permalink",
|
|
||||||
ModelRole.Properties.int:"properties",
|
|
||||||
ModelRole.Rankings.int:"rankings",
|
|
||||||
ModelRole.Stats.int:"stats",
|
|
||||||
}.toTable
|
|
||||||
|
|
||||||
proc mapFromSource(self: Model, index: Index): QModelIndex =
|
|
||||||
if not self.sourceIndexToRow.hasKey(index):
|
|
||||||
return QModelIndex()
|
|
||||||
let proxyIndex = self.sourceIndexToRow[index]
|
|
||||||
return self.createIndex(proxyIndex, 0, nil)
|
|
||||||
|
|
||||||
proc mapToSource(self: Model, index: QModelIndex): Index =
|
|
||||||
if not self.rowToSourceIndex.hasKey(index.row):
|
|
||||||
return (collectionIdx: -1, collectibleIdx: -1)
|
|
||||||
return self.rowToSourceIndex[index.row]
|
|
||||||
|
|
||||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
|
||||||
if (not index.isValid):
|
|
||||||
return
|
|
||||||
|
|
||||||
if (index.row < 0 or index.row >= self.getCount()):
|
|
||||||
return
|
|
||||||
|
|
||||||
let sourceIndex = self.mapToSource(index)
|
|
||||||
|
|
||||||
let collectionIndex = self.collectionsModel.createIndex(sourceIndex.collectionIdx, 0, nil)
|
|
||||||
let enumRole = role.ModelRole
|
|
||||||
|
|
||||||
case enumRole:
|
|
||||||
of ModelRole.CollectionName:
|
|
||||||
result = self.collectionsModel.data(collectionIndex, CollectionRole.Name.int)
|
|
||||||
of ModelRole.CollectionSlug:
|
|
||||||
result = self.collectionsModel.data(collectionIndex, CollectionRole.Slug.int)
|
|
||||||
of ModelRole.CollectionImageUrl:
|
|
||||||
result = self.collectionsModel.data(collectionIndex, CollectionRole.ImageUrl.int)
|
|
||||||
of ModelRole.CollectionOwnedAssetCount:
|
|
||||||
result = self.collectionsModel.data(collectionIndex, CollectionRole.OwnedAssetCount.int)
|
|
||||||
of ModelRole.CollectionCollectiblesLoaded:
|
|
||||||
result = self.collectionsModel.data(collectionIndex, CollectionRole.CollectiblesLoaded.int)
|
|
||||||
else:
|
|
||||||
let collectiblesModel = self.collectionsModel.getCollectiblesModel(sourceIndex.collectionIdx)
|
|
||||||
let collectibleIndex = collectiblesModel.createIndex(sourceIndex.collectibleIdx, 0, nil)
|
|
||||||
case enumRole:
|
|
||||||
of ModelRole.CollectionCollectiblesCount:
|
|
||||||
result = newQVariant(collectiblesModel.getCount())
|
|
||||||
of ModelRole.Id:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Id.int)
|
|
||||||
of ModelRole.Name:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Name.int)
|
|
||||||
of ModelRole.ImageUrl:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.ImageUrl.int)
|
|
||||||
of ModelRole.BackgroundColor:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.BackgroundColor.int)
|
|
||||||
of ModelRole.Description:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Description.int)
|
|
||||||
of ModelRole.Permalink:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Permalink.int)
|
|
||||||
of ModelRole.Properties:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Properties.int)
|
|
||||||
of ModelRole.Rankings:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Rankings.int)
|
|
||||||
of ModelRole.Stats:
|
|
||||||
result = collectiblesModel.data(collectibleIndex, CollectibleRole.Stats.int)
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
proc data*(self: Model, row: int, role: ModelRole): QVariant =
|
|
||||||
return self.data(self.createIndex(row, 0, nil), role.int)
|
|
|
@ -4,6 +4,7 @@ import ./collectible_trait_item
|
||||||
type
|
type
|
||||||
Item* = object
|
Item* = object
|
||||||
id: int
|
id: int
|
||||||
|
address: string
|
||||||
tokenId: UInt256
|
tokenId: UInt256
|
||||||
name: string
|
name: string
|
||||||
imageUrl: string
|
imageUrl: string
|
||||||
|
@ -13,9 +14,14 @@ type
|
||||||
properties: seq[CollectibleTrait]
|
properties: seq[CollectibleTrait]
|
||||||
rankings: seq[CollectibleTrait]
|
rankings: seq[CollectibleTrait]
|
||||||
stats: seq[CollectibleTrait]
|
stats: seq[CollectibleTrait]
|
||||||
|
collectionName: string
|
||||||
|
collectionSlug: string
|
||||||
|
collectionImageUrl: string
|
||||||
|
isLoading: bool
|
||||||
|
|
||||||
proc initItem*(
|
proc initItem*(
|
||||||
id: int,
|
id: int,
|
||||||
|
address: string,
|
||||||
tokenId: UInt256,
|
tokenId: UInt256,
|
||||||
name: string,
|
name: string,
|
||||||
imageUrl: string,
|
imageUrl: string,
|
||||||
|
@ -24,11 +30,15 @@ proc initItem*(
|
||||||
permalink: string,
|
permalink: string,
|
||||||
properties: seq[CollectibleTrait],
|
properties: seq[CollectibleTrait],
|
||||||
rankings: seq[CollectibleTrait],
|
rankings: seq[CollectibleTrait],
|
||||||
stats: seq[CollectibleTrait]
|
stats: seq[CollectibleTrait],
|
||||||
|
collectionName: string,
|
||||||
|
collectionSlug: string,
|
||||||
|
collectionImageUrl: string
|
||||||
): Item =
|
): Item =
|
||||||
result.id = id
|
result.id = id
|
||||||
|
result.address = address
|
||||||
result.tokenId = tokenId
|
result.tokenId = tokenId
|
||||||
result.name = name
|
result.name = if (name != ""): name else: ("#" & tokenId.toString())
|
||||||
result.imageUrl = imageUrl
|
result.imageUrl = imageUrl
|
||||||
result.backgroundColor = if (backgroundColor == ""): "transparent" else: ("#" & backgroundColor)
|
result.backgroundColor = if (backgroundColor == ""): "transparent" else: ("#" & backgroundColor)
|
||||||
result.description = description
|
result.description = description
|
||||||
|
@ -36,24 +46,39 @@ proc initItem*(
|
||||||
result.properties = properties
|
result.properties = properties
|
||||||
result.rankings = rankings
|
result.rankings = rankings
|
||||||
result.stats = stats
|
result.stats = stats
|
||||||
|
result.collectionName = collectionName
|
||||||
|
result.collectionSlug = collectionSlug
|
||||||
|
result.collectionImageUrl = collectionImageUrl
|
||||||
|
result.isLoading = false
|
||||||
|
|
||||||
proc initItem*: Item =
|
proc initItem*: Item =
|
||||||
result = initItem(-1, u256(0), "", "", "transparent", "Collectibles", "", @[], @[], @[])
|
result = initItem(-1, "", u256(0), "", "", "transparent", "Collectibles", "", @[], @[], @[], "", "", "")
|
||||||
|
|
||||||
|
proc initLoadingItem*: Item =
|
||||||
|
result = initItem()
|
||||||
|
result.isLoading = true
|
||||||
|
|
||||||
proc `$`*(self: Item): string =
|
proc `$`*(self: Item): string =
|
||||||
result = fmt"""Collectibles(
|
result = fmt"""Collectibles(
|
||||||
id: {self.id},
|
id: {self.id},
|
||||||
|
address: {self.address},
|
||||||
tokenId: {self.tokenId},
|
tokenId: {self.tokenId},
|
||||||
name: {self.name},
|
name: {self.name},
|
||||||
imageUrl: {self.imageUrl},
|
imageUrl: {self.imageUrl},
|
||||||
backgroundColor: {self.backgroundColor},
|
backgroundColor: {self.backgroundColor},
|
||||||
description: {self.description},
|
description: {self.description},
|
||||||
permalink: {self.permalink},
|
permalink: {self.permalink},
|
||||||
|
collectionName: {self.collectionName},
|
||||||
|
collectionSlug: {self.collectionSlug},
|
||||||
|
collectionImageUrl: {self.collectionImageUrl},
|
||||||
]"""
|
]"""
|
||||||
|
|
||||||
proc getId*(self: Item): int =
|
proc getId*(self: Item): int =
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
|
proc getAddress*(self: Item): string =
|
||||||
|
return self.address
|
||||||
|
|
||||||
proc getTokenId*(self: Item): UInt256 =
|
proc getTokenId*(self: Item): UInt256 =
|
||||||
return self.tokenId
|
return self.tokenId
|
||||||
|
|
||||||
|
@ -80,3 +105,15 @@ proc getRankings*(self: Item): seq[CollectibleTrait] =
|
||||||
|
|
||||||
proc getStats*(self: Item): seq[CollectibleTrait] =
|
proc getStats*(self: Item): seq[CollectibleTrait] =
|
||||||
return self.stats
|
return self.stats
|
||||||
|
|
||||||
|
proc getCollectionName*(self: Item): string =
|
||||||
|
return self.collectionName
|
||||||
|
|
||||||
|
proc getCollectionSlug*(self: Item): string =
|
||||||
|
return self.collectionSlug
|
||||||
|
|
||||||
|
proc getCollectionImageUrl*(self: Item): string =
|
||||||
|
return self.collectionImageUrl
|
||||||
|
|
||||||
|
proc getIsLoading*(self: Item): bool =
|
||||||
|
return self.isLoading
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ./collectibles_item, ./collectible_trait_model
|
||||||
type
|
type
|
||||||
CollectibleRole* {.pure.} = enum
|
CollectibleRole* {.pure.} = enum
|
||||||
Id = UserRole + 1,
|
Id = UserRole + 1,
|
||||||
|
Address
|
||||||
TokenId
|
TokenId
|
||||||
Name
|
Name
|
||||||
ImageUrl
|
ImageUrl
|
||||||
|
@ -14,11 +15,23 @@ type
|
||||||
Properties
|
Properties
|
||||||
Rankings
|
Rankings
|
||||||
Stats
|
Stats
|
||||||
|
CollectionName
|
||||||
|
CollectionSlug
|
||||||
|
CollectionImageUrl
|
||||||
|
IsLoading
|
||||||
|
|
||||||
|
# Maximum number of owned collectibles to be fetched at a time
|
||||||
|
const ownedCollectiblesFetchLimit = 200
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
Model* = ref object of QAbstractListModel
|
Model* = ref object of QAbstractListModel
|
||||||
items: seq[Item]
|
items: seq[Item]
|
||||||
|
allCollectiblesLoaded: bool
|
||||||
|
isFetching: bool
|
||||||
|
|
||||||
|
proc addLoadingItems(self: Model)
|
||||||
|
proc removeLoadingItems(self: Model)
|
||||||
|
|
||||||
proc delete(self: Model) =
|
proc delete(self: Model) =
|
||||||
self.items = @[]
|
self.items = @[]
|
||||||
|
@ -27,13 +40,12 @@ QtObject:
|
||||||
proc setup(self: Model) =
|
proc setup(self: Model) =
|
||||||
self.QAbstractListModel.setup
|
self.QAbstractListModel.setup
|
||||||
|
|
||||||
proc newModel*(items: seq[Item]): Model =
|
proc newModel*(): Model =
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result.setup
|
result.setup
|
||||||
result.items = items
|
result.items = @[]
|
||||||
|
result.allCollectiblesLoaded = false
|
||||||
proc newModel*(): Model =
|
result.isFetching = true
|
||||||
return newModel(@[])
|
|
||||||
|
|
||||||
proc `$`*(self: Model): string =
|
proc `$`*(self: Model): string =
|
||||||
for i in 0 ..< self.items.len:
|
for i in 0 ..< self.items.len:
|
||||||
|
@ -46,12 +58,50 @@ QtObject:
|
||||||
read = getCount
|
read = getCount
|
||||||
notify = countChanged
|
notify = countChanged
|
||||||
|
|
||||||
|
proc isFetchingChanged(self: Model) {.signal.}
|
||||||
|
proc getIsFetching*(self: Model): bool {.slot.} =
|
||||||
|
self.isFetching
|
||||||
|
QtProperty[bool] isFetching:
|
||||||
|
read = getIsFetching
|
||||||
|
notify = isFetchingChanged
|
||||||
|
proc setIsFetching(self: Model, value: bool) =
|
||||||
|
if value == self.isFetching:
|
||||||
|
return
|
||||||
|
if value:
|
||||||
|
self.addLoadingItems()
|
||||||
|
else:
|
||||||
|
self.removeLoadingItems()
|
||||||
|
self.isFetching = value
|
||||||
|
self.isFetchingChanged()
|
||||||
|
|
||||||
|
proc allCollectiblesLoadedChanged(self: Model) {.signal.}
|
||||||
|
proc getAllCollectiblesLoaded*(self: Model): bool {.slot.} =
|
||||||
|
self.allCollectiblesLoaded
|
||||||
|
QtProperty[bool] allCollectiblesLoaded:
|
||||||
|
read = getAllCollectiblesLoaded
|
||||||
|
notify = allCollectiblesLoadedChanged
|
||||||
|
proc setAllCollectiblesLoaded*(self: Model, value: bool) =
|
||||||
|
if value == self.allCollectiblesLoaded:
|
||||||
|
return
|
||||||
|
self.allCollectiblesLoaded = value
|
||||||
|
self.allCollectiblesLoadedChanged()
|
||||||
|
|
||||||
|
method canFetchMore*(self: Model, parent: QModelIndex): bool =
|
||||||
|
return not self.allCollectiblesLoaded and not self.isFetching
|
||||||
|
|
||||||
|
proc requestFetch(self: Model, limit: int) {.signal.}
|
||||||
|
method fetchMore*(self: Model, parent: QModelIndex) =
|
||||||
|
if not self.isFetching:
|
||||||
|
self.setIsFetching(true)
|
||||||
|
self.requestFetch(ownedCollectiblesFetchLimit)
|
||||||
|
|
||||||
method rowCount*(self: Model, index: QModelIndex = nil): int =
|
method rowCount*(self: Model, index: QModelIndex = nil): int =
|
||||||
return self.items.len
|
return self.items.len
|
||||||
|
|
||||||
method roleNames(self: Model): Table[int, string] =
|
method roleNames(self: Model): Table[int, string] =
|
||||||
{
|
{
|
||||||
CollectibleRole.Id.int:"id",
|
CollectibleRole.Id.int:"id",
|
||||||
|
CollectibleRole.Address.int:"address",
|
||||||
CollectibleRole.TokenId.int:"tokenId",
|
CollectibleRole.TokenId.int:"tokenId",
|
||||||
CollectibleRole.Name.int:"name",
|
CollectibleRole.Name.int:"name",
|
||||||
CollectibleRole.ImageUrl.int:"imageUrl",
|
CollectibleRole.ImageUrl.int:"imageUrl",
|
||||||
|
@ -61,6 +111,10 @@ QtObject:
|
||||||
CollectibleRole.Properties.int:"properties",
|
CollectibleRole.Properties.int:"properties",
|
||||||
CollectibleRole.Rankings.int:"rankings",
|
CollectibleRole.Rankings.int:"rankings",
|
||||||
CollectibleRole.Stats.int:"stats",
|
CollectibleRole.Stats.int:"stats",
|
||||||
|
CollectibleRole.CollectionName.int:"collectionName",
|
||||||
|
CollectibleRole.CollectionSlug.int:"collectionSlug",
|
||||||
|
CollectibleRole.CollectionImageUrl.int:"collectionImageUrl",
|
||||||
|
CollectibleRole.IsLoading.int:"isLoading",
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||||
|
@ -76,6 +130,8 @@ QtObject:
|
||||||
case enumRole:
|
case enumRole:
|
||||||
of CollectibleRole.Id:
|
of CollectibleRole.Id:
|
||||||
result = newQVariant(item.getId())
|
result = newQVariant(item.getId())
|
||||||
|
of CollectibleRole.Address:
|
||||||
|
result = newQVariant(item.getAddress())
|
||||||
of CollectibleRole.TokenId:
|
of CollectibleRole.TokenId:
|
||||||
result = newQVariant(item.getTokenId().toString())
|
result = newQVariant(item.getTokenId().toString())
|
||||||
of CollectibleRole.Name:
|
of CollectibleRole.Name:
|
||||||
|
@ -100,15 +156,45 @@ QtObject:
|
||||||
let traits = newTraitModel()
|
let traits = newTraitModel()
|
||||||
traits.setItems(item.getStats())
|
traits.setItems(item.getStats())
|
||||||
result = newQVariant(traits)
|
result = newQVariant(traits)
|
||||||
|
of CollectibleRole.CollectionName:
|
||||||
|
result = newQVariant(item.getCollectionName())
|
||||||
|
of CollectibleRole.CollectionSlug:
|
||||||
|
result = newQVariant(item.getCollectionSlug())
|
||||||
|
of CollectibleRole.CollectionImageUrl:
|
||||||
|
result = newQVariant(item.getCollectionImageUrl())
|
||||||
|
of CollectibleRole.IsLoading:
|
||||||
|
result = newQVariant(item.getIsLoading())
|
||||||
|
|
||||||
proc getItem*(self: Model, index: int): Item =
|
proc addLoadingItems(self: Model) =
|
||||||
return self.items[index]
|
let parentModelIndex = newQModelIndex()
|
||||||
|
defer: parentModelIndex.delete
|
||||||
|
|
||||||
proc setItems*(self: Model, items: seq[Item]) =
|
let loadingItem = initLoadingItem()
|
||||||
self.beginResetModel()
|
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len + ownedCollectiblesFetchLimit - 1)
|
||||||
self.items = items
|
for i in 1..ownedCollectiblesFetchLimit:
|
||||||
self.endResetModel()
|
self.items.add(loadingItem)
|
||||||
|
self.endInsertRows()
|
||||||
self.countChanged()
|
self.countChanged()
|
||||||
|
|
||||||
proc appendItems*(self: Model, items: seq[Item]) =
|
proc removeLoadingItems(self: Model) =
|
||||||
self.setItems(concat(self.items, items))
|
for i in 0 ..< self.items.len:
|
||||||
|
if self.items[i].getIsLoading():
|
||||||
|
self.beginRemoveRows(newQModelIndex(), i, self.items.len-1)
|
||||||
|
self.items.delete(i, self.items.len-1)
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.countChanged()
|
||||||
|
return
|
||||||
|
|
||||||
|
proc setItems*(self: Model, items: seq[Item], append: bool) =
|
||||||
|
self.setIsFetching(false)
|
||||||
|
if append:
|
||||||
|
let parentModelIndex = newQModelIndex()
|
||||||
|
defer: parentModelIndex.delete
|
||||||
|
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len + items.len - 1)
|
||||||
|
self.items = concat(self.items, items)
|
||||||
|
self.endInsertRows()
|
||||||
|
else:
|
||||||
|
self.beginResetModel()
|
||||||
|
self.items = items
|
||||||
|
self.endResetModel()
|
||||||
|
self.countChanged()
|
||||||
|
|
|
@ -2,9 +2,10 @@ import sequtils, sugar
|
||||||
import ../../../../../../app_service/service/collectible/dto
|
import ../../../../../../app_service/service/collectible/dto
|
||||||
import collectibles_item, collectible_trait_item
|
import collectibles_item, collectible_trait_item
|
||||||
|
|
||||||
proc collectibleToItem*(c: CollectibleDto) : Item =
|
proc collectibleToItem*(c: CollectibleDto, co: CollectionDto) : Item =
|
||||||
return initItem(
|
return initItem(
|
||||||
c.id,
|
c.id,
|
||||||
|
c.address,
|
||||||
c.tokenId,
|
c.tokenId,
|
||||||
c.name,
|
c.name,
|
||||||
c.imageUrl,
|
c.imageUrl,
|
||||||
|
@ -13,5 +14,8 @@ proc collectibleToItem*(c: CollectibleDto) : Item =
|
||||||
c.permalink,
|
c.permalink,
|
||||||
c.properties.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)),
|
c.properties.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)),
|
||||||
c.rankings.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)),
|
c.rankings.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)),
|
||||||
c.statistics.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue))
|
c.statistics.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue)),
|
||||||
|
co.name,
|
||||||
|
co.slug,
|
||||||
|
co.imageUrl
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import strformat, stint
|
|
||||||
import ./collectibles_model as collectibles_model
|
|
||||||
import ./collectibles_item as collectibles_item
|
|
||||||
|
|
||||||
type
|
|
||||||
Item* = object
|
|
||||||
name: string
|
|
||||||
slug: string
|
|
||||||
imageUrl: string
|
|
||||||
ownedAssetCount: Uint256
|
|
||||||
collectiblesLoaded*: bool
|
|
||||||
collectiblesModel: collectibles_model.Model
|
|
||||||
|
|
||||||
proc initItem*(name, slug, imageUrl: string, ownedAssetCount: Uint256, collectiblesLoaded: bool, collectibles: seq[collectibles_item.Item]): Item =
|
|
||||||
result.name = name
|
|
||||||
result.slug = slug
|
|
||||||
result.imageUrl = imageUrl
|
|
||||||
result.ownedAssetCount = ownedAssetCount
|
|
||||||
result.collectiblesLoaded = collectiblesLoaded
|
|
||||||
result.collectiblesModel = collectibles_model.newModel(collectibles)
|
|
||||||
|
|
||||||
proc initItem*(): Item =
|
|
||||||
result = initItem("", "", "", u256(0), false, @[])
|
|
||||||
|
|
||||||
proc `$`*(self: Item): string =
|
|
||||||
result = fmt"""CollectibleCollection(
|
|
||||||
name: {self.name},
|
|
||||||
slug: {self.slug},
|
|
||||||
imageUrl: {self.imageUrl},
|
|
||||||
ownedAssetCount: {self.ownedAssetCount},
|
|
||||||
collectiblesLoaded: {self.collectiblesLoaded},
|
|
||||||
collectibles: {self.collectiblesModel}
|
|
||||||
]"""
|
|
||||||
|
|
||||||
proc getName*(self: Item): string =
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
proc getSlug*(self: Item): string =
|
|
||||||
return self.slug
|
|
||||||
|
|
||||||
proc getImageUrl*(self: Item): string =
|
|
||||||
return self.imageUrl
|
|
||||||
|
|
||||||
proc getOwnedAssetCount*(self: Item): Uint256 =
|
|
||||||
return self.ownedAssetCount
|
|
||||||
|
|
||||||
proc getCollectiblesLoaded*(self: Item): bool =
|
|
||||||
return self.collectiblesLoaded
|
|
||||||
|
|
||||||
proc getCollectiblesModel*(self: Item): collectibles_model.Model =
|
|
||||||
return self.collectiblesModel
|
|
|
@ -1,131 +0,0 @@
|
||||||
import NimQml, Tables, strutils, strformat, stint
|
|
||||||
|
|
||||||
import ./collections_item as collections_item
|
|
||||||
|
|
||||||
import ./collectibles_model as collectibles_model
|
|
||||||
import ./collectibles_item as collectibles_item
|
|
||||||
|
|
||||||
type
|
|
||||||
CollectionRole* {.pure.} = enum
|
|
||||||
Name = UserRole + 1,
|
|
||||||
Slug
|
|
||||||
ImageUrl
|
|
||||||
OwnedAssetCount
|
|
||||||
CollectiblesLoaded
|
|
||||||
CollectiblesModel
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type
|
|
||||||
Model* = ref object of QAbstractListModel
|
|
||||||
items: seq[collections_item.Item]
|
|
||||||
collectionsLoaded: bool
|
|
||||||
|
|
||||||
proc delete(self: Model) =
|
|
||||||
self.items = @[]
|
|
||||||
self.QAbstractListModel.delete
|
|
||||||
|
|
||||||
proc setup(self: Model) =
|
|
||||||
self.QAbstractListModel.setup
|
|
||||||
self.collectionsLoaded = false
|
|
||||||
|
|
||||||
proc newModel*(): Model =
|
|
||||||
new(result, delete)
|
|
||||||
result.setup
|
|
||||||
|
|
||||||
proc `$`*(self: Model): string =
|
|
||||||
for i in 0 ..< self.items.len:
|
|
||||||
result &= fmt"""[{i}]:({$self.items[i]})"""
|
|
||||||
|
|
||||||
proc countChanged(self: Model) {.signal.}
|
|
||||||
proc getCount*(self: Model): int {.slot.} =
|
|
||||||
self.items.len
|
|
||||||
QtProperty[int] count:
|
|
||||||
read = getCount
|
|
||||||
notify = countChanged
|
|
||||||
|
|
||||||
proc collectionsLoadedChanged(self: Model) {.signal.}
|
|
||||||
proc getCollectionsLoaded*(self: Model): bool {.slot.} =
|
|
||||||
self.collectionsLoaded
|
|
||||||
QtProperty[bool] collectionsLoaded:
|
|
||||||
read = getCollectionsLoaded
|
|
||||||
notify = collectionsLoadedChanged
|
|
||||||
|
|
||||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
|
||||||
return self.items.len
|
|
||||||
|
|
||||||
method roleNames(self: Model): Table[int, string] =
|
|
||||||
{
|
|
||||||
CollectionRole.Name.int:"name",
|
|
||||||
CollectionRole.Slug.int:"slug",
|
|
||||||
CollectionRole.ImageUrl.int:"imageUrl",
|
|
||||||
CollectionRole.OwnedAssetCount.int:"ownedAssetCount",
|
|
||||||
CollectionRole.CollectiblesLoaded.int:"collectiblesLoaded",
|
|
||||||
CollectionRole.CollectiblesModel.int:"collectiblesModel"
|
|
||||||
}.toTable
|
|
||||||
|
|
||||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
|
||||||
if (not index.isValid):
|
|
||||||
return
|
|
||||||
|
|
||||||
if (index.row < 0 or index.row >= self.items.len):
|
|
||||||
return
|
|
||||||
|
|
||||||
let item = self.items[index.row]
|
|
||||||
let enumRole = role.CollectionRole
|
|
||||||
|
|
||||||
case enumRole:
|
|
||||||
of CollectionRole.Name:
|
|
||||||
result = newQVariant(item.getName())
|
|
||||||
of CollectionRole.Slug:
|
|
||||||
result = newQVariant(item.getSlug())
|
|
||||||
of CollectionRole.ImageUrl:
|
|
||||||
result = newQVariant(item.getImageUrl())
|
|
||||||
of CollectionRole.OwnedAssetCount:
|
|
||||||
result = newQVariant(item.getOwnedAssetCount().toString())
|
|
||||||
of CollectionRole.CollectiblesLoaded:
|
|
||||||
result = newQVariant(item.getCollectiblesLoaded())
|
|
||||||
of CollectionRole.CollectiblesModel:
|
|
||||||
result = newQVariant(item.getCollectiblesModel())
|
|
||||||
|
|
||||||
proc setCollections*(self: Model, items: seq[collections_item.Item], collectionsLoaded: bool) =
|
|
||||||
self.beginResetModel()
|
|
||||||
self.items = items
|
|
||||||
self.endResetModel()
|
|
||||||
self.countChanged()
|
|
||||||
if self.collectionsLoaded != collectionsLoaded:
|
|
||||||
self.collectionsLoaded = collectionsLoaded
|
|
||||||
self.collectionsLoadedChanged()
|
|
||||||
|
|
||||||
proc getCollectionItem*(self: Model, index: int) : collections_item.Item =
|
|
||||||
return self.items[index]
|
|
||||||
|
|
||||||
proc getCollectiblesModel*(self: Model, index: int) : collectibles_model.Model =
|
|
||||||
if index < self.items.len:
|
|
||||||
return self.items[index].getCollectiblesModel()
|
|
||||||
echo "getCollectiblesModel: Invalid index ", index, " with len ", self.items.len
|
|
||||||
return collectibles_model.newModel()
|
|
||||||
|
|
||||||
proc findIndexBySlug(self: Model, slug: string): int =
|
|
||||||
for i in 0 ..< self.items.len:
|
|
||||||
if self.items[i].getSlug() == slug:
|
|
||||||
return i
|
|
||||||
return -1
|
|
||||||
|
|
||||||
proc signalDataChanged(self: Model, top: int, bottom: int, roles: int) {.signal.}
|
|
||||||
|
|
||||||
proc emitDataChanged(self: Model, top: int, bottom: int, role: int) =
|
|
||||||
let topIndex = self.createIndex(top, 0, nil)
|
|
||||||
let bottomIndex = self.createIndex(bottom, 0, nil)
|
|
||||||
self.dataChanged(topIndex, bottomIndex, @[role])
|
|
||||||
self.signalDataChanged(top, bottom, role)
|
|
||||||
|
|
||||||
proc updateCollectionCollectibles*(self: Model, slug: string, collectibles: seq[collectibles_item.Item], collectiblesLoaded: bool) =
|
|
||||||
let idx = self.findIndexBySlug(slug)
|
|
||||||
if idx > -1:
|
|
||||||
let collectiblesModel = self.items[idx].getCollectiblesModel()
|
|
||||||
collectiblesModel.setItems(collectibles)
|
|
||||||
self.emitDataChanged(idx, idx, CollectionRole.CollectiblesModel.int)
|
|
||||||
|
|
||||||
if self.items[idx].getCollectiblesLoaded() != collectiblesLoaded:
|
|
||||||
self.items[idx].collectiblesLoaded = collectiblesLoaded
|
|
||||||
self.emitDataChanged(idx, idx, CollectionRole.CollectiblesLoaded.int)
|
|
|
@ -1,13 +0,0 @@
|
||||||
import sequtils, sugar, Tables
|
|
||||||
import ../../../../../../app_service/service/collectible/service
|
|
||||||
import collections_item, collectibles_utils
|
|
||||||
|
|
||||||
proc collectionToItem*(collection: CollectionData) : Item =
|
|
||||||
return initItem(
|
|
||||||
collection.collection.name,
|
|
||||||
collection.collection.slug,
|
|
||||||
collection.collection.imageUrl,
|
|
||||||
collection.collection.ownedAssetCount,
|
|
||||||
collection.collectiblesLoaded,
|
|
||||||
toSeq(collection.collectibles.values).map(c => collectibleToItem(c))
|
|
||||||
)
|
|
|
@ -11,8 +11,6 @@ import ../../../../../app_service/service/network/service as network_service
|
||||||
|
|
||||||
import ./current_collectible/module as current_collectible_module
|
import ./current_collectible/module as current_collectible_module
|
||||||
|
|
||||||
import ./models/collections_item as collections_item
|
|
||||||
import ./models/collections_utils
|
|
||||||
import ./models/collectibles_item as collectibles_item
|
import ./models/collectibles_item as collectibles_item
|
||||||
import ./models/collectible_trait_item as collectible_trait_item
|
import ./models/collectible_trait_item as collectible_trait_item
|
||||||
import ./models/collectibles_utils
|
import ./models/collectibles_utils
|
||||||
|
@ -45,7 +43,6 @@ proc newModule*(
|
||||||
result.moduleLoaded = false
|
result.moduleLoaded = false
|
||||||
result.currentCollectibleModule = currentCollectibleModule.newModule(result, collectibleService)
|
result.currentCollectibleModule = currentCollectibleModule.newModule(result, collectibleService)
|
||||||
|
|
||||||
|
|
||||||
method delete*(self: Module) =
|
method delete*(self: Module) =
|
||||||
self.view.delete
|
self.view.delete
|
||||||
self.currentCollectibleModule.delete
|
self.currentCollectibleModule.delete
|
||||||
|
@ -76,6 +73,9 @@ method viewDidLoad*(self: Module) =
|
||||||
method currentCollectibleModuleDidLoad*(self: Module) =
|
method currentCollectibleModuleDidLoad*(self: Module) =
|
||||||
self.checkIfModuleDidLoad()
|
self.checkIfModuleDidLoad()
|
||||||
|
|
||||||
|
method fetchOwnedCollectibles*(self: Module, limit: int) =
|
||||||
|
self.controller.fetchOwnedCollectibles(self.chainId, self.address, limit)
|
||||||
|
|
||||||
method switchAccount*(self: Module, accountIndex: int) =
|
method switchAccount*(self: Module, accountIndex: int) =
|
||||||
let network = self.controller.getNetwork()
|
let network = self.controller.getNetwork()
|
||||||
let account = self.controller.getWalletAccount(accountIndex)
|
let account = self.controller.getWalletAccount(accountIndex)
|
||||||
|
@ -83,40 +83,30 @@ method switchAccount*(self: Module, accountIndex: int) =
|
||||||
self.chainId = network.chainId
|
self.chainId = network.chainId
|
||||||
self.address = account.address
|
self.address = account.address
|
||||||
|
|
||||||
self.controller.refreshCollections(self.chainId, self.address)
|
# TODO: Implement a way to reduce the number of full re-fetches. It could be only
|
||||||
self.controller.fetchOwnedCollections(self.chainId, self.address)
|
# when NFT activity was detected for the given account, or if a certain amount of
|
||||||
|
# time has passed. For now, we fetch every time we select the account.
|
||||||
|
self.controller.resetOwnedCollectibles(self.chainId, self.address)
|
||||||
|
|
||||||
|
self.controller.refreshCollectibles(self.chainId, self.address)
|
||||||
|
|
||||||
self.currentCollectibleModule.setCurrentAddress(network, self.address)
|
self.currentCollectibleModule.setCurrentAddress(network, self.address)
|
||||||
|
|
||||||
proc collectionToItem(self: Module, collection: CollectionData) : collections_item.Item =
|
method refreshCollectibles*(self: Module, chainId: int, address: string, collectibles: CollectiblesData) =
|
||||||
var item = collectionToItem(collection)
|
if self.chainId == chainId and self.address == address:
|
||||||
#[ Skeleton items are disabled until problem with OpenSea API is researched.
|
var idsToAdd = newSeq[UniqueID]()
|
||||||
OpenSea is telling us the address owns a certain amount of NFTs from a certain collection, but
|
let append = not collectibles.lastLoadWasFromStart
|
||||||
it doesn't give us the NFTs from that collection when trying to fetch them.
|
|
||||||
# Append skeleton collectibles if not yet fetched
|
|
||||||
let model = item.getCollectiblesModel()
|
|
||||||
let unfetchedCollectiblesCount = item.getOwnedAssetCount() - model.getCount()
|
|
||||||
if unfetchedCollectiblesCount > 0:
|
|
||||||
echo "unfetchedCollectiblesCount = ", unfetchedCollectiblesCount, " ", item.getSlug()
|
|
||||||
let skeletonItems = newSeqWith(unfetchedCollectiblesCount, collectibles_item.initItem())
|
|
||||||
model.appendItems(skeletonItems)
|
|
||||||
]#
|
|
||||||
return item
|
|
||||||
|
|
||||||
method setCollections*(self: Module, collections: CollectionsData) =
|
var startIdx = 0
|
||||||
self.view.setCollections(
|
if append:
|
||||||
toSeq(collections.collections.values).map(c => self.collectionToItem(c)),
|
for i in collectibles.ids.len - collectibles.lastLoadCount ..< collectibles.ids.len:
|
||||||
collections.collectionsLoaded
|
idsToAdd.add(collectibles.ids[i])
|
||||||
)
|
else:
|
||||||
|
idsToAdd = collectibles.ids
|
||||||
|
|
||||||
method updateCollection*(self: Module, collection: CollectionData) =
|
var newCollectibles = idsToAdd.map(id => (block:
|
||||||
self.view.setCollectibles(collection.collection.slug,
|
let c = self.controller.getCollectible(self.chainId, id)
|
||||||
toSeq(collection.collectibles.values).map(c => collectibleToItem(c)),
|
let co = self.controller.getCollection(self.chainId, c.collectionSlug)
|
||||||
collection.collectiblesLoaded
|
return collectibleToItem(c, co)
|
||||||
)
|
))
|
||||||
|
self.view.setCollectibles(newCollectibles, append, collectibles.allLoaded)
|
||||||
method fetchOwnedCollections*(self: Module) =
|
|
||||||
self.controller.fetchOwnedCollections(self.chainId, self.address)
|
|
||||||
|
|
||||||
method fetchOwnedCollectibles*(self: Module, collectionSlug: string) =
|
|
||||||
self.controller.fetchOwnedCollectibles(self.chainId, self.address, collectionSlug)
|
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
import NimQml
|
import NimQml
|
||||||
|
|
||||||
import ./models/collections_model as collections_model
|
import ./models/collectibles_model
|
||||||
import ./models/collectibles_flat_proxy_model as flat_model
|
import ./models/collectibles_item
|
||||||
import ./models/collections_item as collections_item
|
|
||||||
import ./models/collectibles_item as collectibles_item
|
|
||||||
import ./io_interface
|
import ./io_interface
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
View* = ref object of QObject
|
View* = ref object of QObject
|
||||||
delegate: io_interface.AccessInterface
|
delegate: io_interface.AccessInterface
|
||||||
model: collections_model.Model
|
model: Model
|
||||||
flatModel: flat_model.Model
|
|
||||||
|
|
||||||
proc delete*(self: View) =
|
proc delete*(self: View) =
|
||||||
self.flatModel.delete
|
|
||||||
self.model.delete
|
self.model.delete
|
||||||
self.QObject.delete
|
self.QObject.delete
|
||||||
|
|
||||||
|
@ -23,7 +19,7 @@ QtObject:
|
||||||
result.QObject.setup
|
result.QObject.setup
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.model = newModel()
|
result.model = newModel()
|
||||||
result.flatModel = flat_model.newModel(result.model)
|
signalConnect(result.model, "requestFetch(int)", result, "fetchMoreOwnedCollectibles(int)")
|
||||||
|
|
||||||
proc load*(self: View) =
|
proc load*(self: View) =
|
||||||
self.delegate.viewDidLoad()
|
self.delegate.viewDidLoad()
|
||||||
|
@ -35,21 +31,9 @@ QtObject:
|
||||||
read = getModel
|
read = getModel
|
||||||
notify = modelChanged
|
notify = modelChanged
|
||||||
|
|
||||||
proc flatModelChanged*(self: View) {.signal.}
|
proc fetchMoreOwnedCollectibles*(self: View, limit: int) {.slot.} =
|
||||||
proc getFlatModel(self: View): QVariant {.slot.} =
|
self.delegate.fetchOwnedCollectibles(limit)
|
||||||
return newQVariant(self.flatModel)
|
|
||||||
QtProperty[QVariant] flatModel:
|
|
||||||
read = getFlatModel
|
|
||||||
notify = flatModelChanged
|
|
||||||
|
|
||||||
proc fetchOwnedCollections*(self: View) {.slot.} =
|
proc setCollectibles*(self: View, collectibles: seq[Item], append: bool, allLoaded: bool) =
|
||||||
self.delegate.fetchOwnedCollections()
|
self.model.setItems(collectibles, append)
|
||||||
|
self.model.setAllCollectiblesLoaded(allLoaded)
|
||||||
proc fetchOwnedCollectibles*(self: View, collectionSlug: string) {.slot.} =
|
|
||||||
self.delegate.fetchOwnedCollectibles(collectionSlug)
|
|
||||||
|
|
||||||
proc setCollections*(self: View, collections: seq[collections_item.Item], collectionsLoaded: bool) =
|
|
||||||
self.model.setCollections(collections, collectionsLoaded)
|
|
||||||
|
|
||||||
proc setCollectibles*(self: View, collectionsSlug: string, collectibles: seq[collectibles_item.Item], collectiblesLoaded: bool) =
|
|
||||||
self.model.updateCollectionCollectibles(collectionsSlug, collectibles, collectiblesLoaded)
|
|
||||||
|
|
|
@ -1,28 +1,8 @@
|
||||||
type
|
|
||||||
FetchOwnedCollectionsTaskArg = ref object of QObjectTaskArg
|
|
||||||
chainId*: int
|
|
||||||
address*: string
|
|
||||||
|
|
||||||
const fetchOwnedCollectionsTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
|
||||||
let arg = decode[FetchOwnedCollectionsTaskArg](argEncoded)
|
|
||||||
let output = %* {
|
|
||||||
"chainId": arg.chainId,
|
|
||||||
"address": arg.address,
|
|
||||||
"collections": ""
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
let response = collectibles.getOpenseaCollectionsByOwner(arg.chainId, arg.address)
|
|
||||||
output["collections"] = response.result
|
|
||||||
except Exception as e:
|
|
||||||
let errDesription = e.msg
|
|
||||||
error "error fetchOwnedCollectionsTaskArg: ", errDesription
|
|
||||||
arg.finish(output)
|
|
||||||
|
|
||||||
type
|
type
|
||||||
FetchOwnedCollectiblesTaskArg = ref object of QObjectTaskArg
|
FetchOwnedCollectiblesTaskArg = ref object of QObjectTaskArg
|
||||||
chainId*: int
|
chainId*: int
|
||||||
address*: string
|
address*: string
|
||||||
collectionSlug: string
|
cursor: string
|
||||||
limit: int
|
limit: int
|
||||||
|
|
||||||
const fetchOwnedCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
const fetchOwnedCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
|
@ -30,11 +10,11 @@ const fetchOwnedCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, n
|
||||||
let output = %* {
|
let output = %* {
|
||||||
"chainId": arg.chainId,
|
"chainId": arg.chainId,
|
||||||
"address": arg.address,
|
"address": arg.address,
|
||||||
"collectionSlug": arg.collectionSlug,
|
"cursor": arg.cursor,
|
||||||
"collectibles": ""
|
"collectibles": ""
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
let response = collectibles.getOpenseaAssetsByOwnerAndCollection(arg.chainId, arg.address, arg.collectionSlug, arg.limit)
|
let response = collectibles.getOpenseaAssetsByOwnerWithCursor(arg.chainId, arg.address, arg.cursor, arg.limit)
|
||||||
output["collectibles"] = response.result
|
output["collectibles"] = response.result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDesription = e.msg
|
let errDesription = e.msg
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import json, Tables, stint, strformat, strutils
|
import json, Tables, stint, strformat, strutils
|
||||||
|
|
||||||
|
# Unique identifier for collectible on a specific chain
|
||||||
|
type
|
||||||
|
UniqueID* = object
|
||||||
|
contractAddress*: string
|
||||||
|
tokenId*: UInt256
|
||||||
|
|
||||||
type CollectibleTraitType* {.pure.} = enum
|
type CollectibleTraitType* {.pure.} = enum
|
||||||
Properties = 0,
|
Properties = 0,
|
||||||
|
@ -11,7 +16,6 @@ type CollectionTrait* = ref object
|
||||||
|
|
||||||
type CollectionDto* = ref object
|
type CollectionDto* = ref object
|
||||||
name*, slug*, imageUrl*: string
|
name*, slug*, imageUrl*: string
|
||||||
ownedAssetCount*: Uint256
|
|
||||||
trait*: Table[string, CollectionTrait]
|
trait*: Table[string, CollectionTrait]
|
||||||
|
|
||||||
type CollectibleTrait* = ref object
|
type CollectibleTrait* = ref object
|
||||||
|
@ -20,7 +24,7 @@ type CollectibleTrait* = ref object
|
||||||
type CollectibleDto* = ref object
|
type CollectibleDto* = ref object
|
||||||
id*: int
|
id*: int
|
||||||
tokenId*: Uint256
|
tokenId*: Uint256
|
||||||
name*, description*, permalink*, imageThumbnailUrl*, imageUrl*, address*, backgroundColor*: string
|
address*, collectionSlug*, name*, description*, permalink*, imageThumbnailUrl*, imageUrl*, backgroundColor*: string
|
||||||
properties*, rankings*, statistics*: seq[CollectibleTrait]
|
properties*, rankings*, statistics*: seq[CollectibleTrait]
|
||||||
|
|
||||||
proc newCollectibleDto*: CollectibleDto =
|
proc newCollectibleDto*: CollectibleDto =
|
||||||
|
@ -31,6 +35,14 @@ proc newCollectibleDto*: CollectibleDto =
|
||||||
proc isValid*(self: CollectibleDto): bool =
|
proc isValid*(self: CollectibleDto): bool =
|
||||||
return self.id >= 0
|
return self.id >= 0
|
||||||
|
|
||||||
|
proc newCollectionDto*: CollectionDto =
|
||||||
|
return CollectionDto(
|
||||||
|
slug: ""
|
||||||
|
)
|
||||||
|
|
||||||
|
proc isValid*(self: CollectionDto): bool =
|
||||||
|
return self.slug != ""
|
||||||
|
|
||||||
proc isNumeric(s: string): bool =
|
proc isNumeric(s: string): bool =
|
||||||
try:
|
try:
|
||||||
discard s.parseFloat()
|
discard s.parseFloat()
|
||||||
|
@ -39,14 +51,14 @@ proc isNumeric(s: string): bool =
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc `$`*(self: CollectionDto): string =
|
proc `$`*(self: CollectionDto): string =
|
||||||
return fmt"CollectionDto(name:{self.name}, slug:{self.slug}, owned asset count:{self.ownedAssetCount})"
|
return fmt"CollectionDto(name:{self.name}, slug:{self.slug})"
|
||||||
|
|
||||||
proc `$`*(self: CollectibleDto): string =
|
proc `$`*(self: CollectibleDto): string =
|
||||||
return fmt"CollectibleDto(id:{self.id}, token_id:{self.tokenId}, name:{self.name}, description:{self.description}, permalink:{self.permalink}, address:{self.address}, imageUrl: {self.imageUrl}, imageThumbnailUrl: {self.imageThumbnailUrl}, backgroundColor: {self.backgroundColor})"
|
return fmt"CollectibleDto(id:{self.id}, address:{self.address}, tokenId:{self.tokenId}, collectionSlug:{self.collectionSlug}, name:{self.name}, description:{self.description}, permalink:{self.permalink}, imageUrl: {self.imageUrl}, imageThumbnailUrl: {self.imageThumbnailUrl}, backgroundColor: {self.backgroundColor})"
|
||||||
|
|
||||||
proc getCollectionTraits*(jsonCollection: JsonNode): Table[string, CollectionTrait] =
|
proc getCollectionTraits*(jsonCollection: JsonNode): Table[string, CollectionTrait] =
|
||||||
var traitList: Table[string, CollectionTrait] = initTable[string, CollectionTrait]()
|
var traitList: Table[string, CollectionTrait] = initTable[string, CollectionTrait]()
|
||||||
for key, value in jsonCollection{"traits"}:
|
for key, value in jsonCollection{"traits"}.getFields():
|
||||||
traitList[key] = CollectionTrait(min: value{"min"}.getFloat, max: value{"max"}.getFloat)
|
traitList[key] = CollectionTrait(min: value{"min"}.getFloat, max: value{"max"}.getFloat)
|
||||||
return traitList
|
return traitList
|
||||||
|
|
||||||
|
@ -55,7 +67,6 @@ proc toCollectionDto*(jsonCollection: JsonNode): CollectionDto =
|
||||||
name: jsonCollection{"name"}.getStr,
|
name: jsonCollection{"name"}.getStr,
|
||||||
slug: jsonCollection{"slug"}.getStr,
|
slug: jsonCollection{"slug"}.getStr,
|
||||||
imageUrl: jsonCollection{"image_url"}.getStr,
|
imageUrl: jsonCollection{"image_url"}.getStr,
|
||||||
ownedAssetCount: stint.parse(jsonCollection{"owned_asset_count"}.getStr, Uint256),
|
|
||||||
trait: getCollectionTraits(jsonCollection)
|
trait: getCollectionTraits(jsonCollection)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,13 +90,14 @@ proc getTrait*(jsonAsset: JsonNode, traitType: CollectibleTraitType): seq[Collec
|
||||||
proc toCollectibleDto*(jsonAsset: JsonNode): CollectibleDto =
|
proc toCollectibleDto*(jsonAsset: JsonNode): CollectibleDto =
|
||||||
return CollectibleDto(
|
return CollectibleDto(
|
||||||
id: jsonAsset{"id"}.getInt,
|
id: jsonAsset{"id"}.getInt,
|
||||||
|
address: jsonAsset{"asset_contract"}{"address"}.getStr,
|
||||||
tokenId: stint.parse(jsonAsset{"token_id"}.getStr, Uint256),
|
tokenId: stint.parse(jsonAsset{"token_id"}.getStr, Uint256),
|
||||||
|
collectionSlug: jsonAsset{"collection"}{"slug"}.getStr,
|
||||||
name: jsonAsset{"name"}.getStr,
|
name: jsonAsset{"name"}.getStr,
|
||||||
description: jsonAsset{"description"}.getStr,
|
description: jsonAsset{"description"}.getStr,
|
||||||
permalink: jsonAsset{"permalink"}.getStr,
|
permalink: jsonAsset{"permalink"}.getStr,
|
||||||
imageThumbnailUrl: jsonAsset{"image_thumbnail_url"}.getStr,
|
imageThumbnailUrl: jsonAsset{"image_thumbnail_url"}.getStr,
|
||||||
imageUrl: jsonAsset{"image_url"}.getStr,
|
imageUrl: jsonAsset{"image_url"}.getStr,
|
||||||
address: jsonAsset{"asset_contract"}{"address"}.getStr,
|
|
||||||
backgroundColor: jsonAsset{"background_color"}.getStr,
|
backgroundColor: jsonAsset{"background_color"}.getStr,
|
||||||
properties: getTrait(jsonAsset, CollectibleTraitType.Properties),
|
properties: getTrait(jsonAsset, CollectibleTraitType.Properties),
|
||||||
rankings: getTrait(jsonAsset, CollectibleTraitType.Rankings),
|
rankings: getTrait(jsonAsset, CollectibleTraitType.Rankings),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import NimQml, Tables, chronicles, sequtils, json, sugar, stint, hashes
|
import NimQml, Tables, chronicles, sequtils, json, sugar, stint, hashes, strformat, times
|
||||||
import ../../../app/core/eventemitter
|
import ../../../app/core/eventemitter
|
||||||
import ../../../app/core/tasks/[qt, threadpool]
|
import ../../../app/core/tasks/[qt, threadpool]
|
||||||
|
|
||||||
|
@ -16,29 +16,14 @@ logScope:
|
||||||
topics = "collectible-service"
|
topics = "collectible-service"
|
||||||
|
|
||||||
# Signals which may be emitted by this service:
|
# Signals which may be emitted by this service:
|
||||||
const SIGNAL_OWNED_COLLECTIONS_UPDATED* = "ownedCollectionsUpdated"
|
const SIGNAL_OWNED_COLLECTIBLES_UPDATE_STARTED* = "ownedCollectiblesUpdateStarted"
|
||||||
const SIGNAL_OWNED_COLLECTIBLES_UPDATED* = "ownedCollectiblesUpdated"
|
const SIGNAL_OWNED_COLLECTIBLES_UPDATE_FINISHED* = "ownedCollectiblesUpdateFinished"
|
||||||
const SIGNAL_COLLECTIBLES_UPDATED* = "collectiblesUpdated"
|
const SIGNAL_COLLECTIBLES_UPDATED* = "collectiblesUpdated"
|
||||||
|
|
||||||
# Maximum number of collectibles to be fetched at a time
|
|
||||||
const limit = 200
|
|
||||||
|
|
||||||
# Unique identifier for collectible in a specific chain
|
|
||||||
type
|
|
||||||
UniqueID* = object
|
|
||||||
contractAddress*: string
|
|
||||||
tokenId*: UInt256
|
|
||||||
|
|
||||||
type
|
|
||||||
OwnedCollectionsUpdateArgs* = ref object of Args
|
|
||||||
chainId*: int
|
|
||||||
address*: string
|
|
||||||
|
|
||||||
type
|
type
|
||||||
OwnedCollectiblesUpdateArgs* = ref object of Args
|
OwnedCollectiblesUpdateArgs* = ref object of Args
|
||||||
chainId*: int
|
chainId*: int
|
||||||
address*: string
|
address*: string
|
||||||
collectionSlug*: string
|
|
||||||
|
|
||||||
type
|
type
|
||||||
CollectiblesUpdateArgs* = ref object of Args
|
CollectiblesUpdateArgs* = ref object of Args
|
||||||
|
@ -46,32 +31,47 @@ type
|
||||||
ids*: seq[UniqueID]
|
ids*: seq[UniqueID]
|
||||||
|
|
||||||
type
|
type
|
||||||
CollectionData* = ref object
|
CollectiblesData* = ref object
|
||||||
collection*: CollectionDto
|
isFetching*: bool
|
||||||
collectiblesLoaded*: bool
|
allLoaded*: bool
|
||||||
collectibles*: OrderedTableRef[int, CollectibleDto] # [collectibleId, CollectibleDto]
|
lastLoadWasFromStart*: bool
|
||||||
|
lastLoadFromStartTimestamp*: DateTime
|
||||||
proc newCollectionData*(collection: CollectionDto): CollectionData =
|
lastLoadCount*: int
|
||||||
new(result)
|
previousCursor*: string
|
||||||
result.collection = collection
|
nextCursor*: string
|
||||||
result.collectiblesLoaded = false
|
ids*: seq[UniqueID]
|
||||||
result.collectibles = newOrderedTable[int, CollectibleDto]()
|
|
||||||
|
|
||||||
type
|
|
||||||
CollectionsData* = ref object
|
|
||||||
collectionsLoaded*: bool
|
|
||||||
collections*: OrderedTableRef[string, CollectionData] # [collectionSlug, CollectionData]
|
|
||||||
|
|
||||||
proc newCollectionsData*(): CollectionsData =
|
proc newCollectiblesData*(): CollectiblesData =
|
||||||
new(result)
|
new(result)
|
||||||
result.collectionsLoaded = false
|
result.isFetching = false
|
||||||
result.collections = newOrderedTable[string, CollectionData]()
|
result.allLoaded = false
|
||||||
|
result.lastLoadWasFromStart = false
|
||||||
|
result.lastLoadFromStartTimestamp = now() - initDuration(weeks = 1)
|
||||||
|
result.lastLoadCount = 0
|
||||||
|
result.previousCursor = ""
|
||||||
|
result.nextCursor = ""
|
||||||
|
result.ids = @[]
|
||||||
|
|
||||||
|
proc `$`*(self: CollectiblesData): string =
|
||||||
|
return fmt"""CollectiblesData(
|
||||||
|
isFetching:{self.isFetching},
|
||||||
|
allLoaded:{self.allLoaded},
|
||||||
|
lastLoadWasFromStart:{self.lastLoadWasFromStart},
|
||||||
|
lastLoadFromStartTimestamp:{self.lastLoadFromStartTimestamp},
|
||||||
|
lastLoadCount:{self.lastLoadCount},
|
||||||
|
previousCursor:{self.previousCursor},
|
||||||
|
nextCursor:{self.nextCursor},
|
||||||
|
ids:{self.ids}
|
||||||
|
)"""
|
||||||
|
|
||||||
type
|
type
|
||||||
AdressesData* = TableRef[string, CollectionsData] # [address, CollectionsData]
|
AdressesData = TableRef[string, CollectiblesData] # [address, CollectiblesData]
|
||||||
|
|
||||||
type
|
type
|
||||||
ChainsData* = TableRef[int, AdressesData] # [chainId, AdressesData]
|
ChainsData = TableRef[int, AdressesData] # [chainId, AdressesData]
|
||||||
|
|
||||||
|
type
|
||||||
|
CollectiblesResult = tuple[success: bool, collectibles: seq[CollectibleDto], collections: seq[CollectionDto], previousCursor: string, nextCursor: string]
|
||||||
|
|
||||||
proc hash(x: UniqueID): Hash =
|
proc hash(x: UniqueID): Hash =
|
||||||
result = x.contractAddress.hash !& x.tokenId.hash
|
result = x.contractAddress.hash !& x.tokenId.hash
|
||||||
|
@ -84,7 +84,8 @@ QtObject:
|
||||||
threadpool: ThreadPool
|
threadpool: ThreadPool
|
||||||
networkService: network_service.Service
|
networkService: network_service.Service
|
||||||
ownershipData: ChainsData
|
ownershipData: ChainsData
|
||||||
data: TableRef[int, TableRef[UniqueID, CollectibleDto]] # [chainId, [UniqueID, CollectibleDto]]
|
collectibles: TableRef[int, TableRef[UniqueID, CollectibleDto]] # [chainId, [UniqueID, CollectibleDto]]
|
||||||
|
collections: TableRef[int, TableRef[string, CollectionDto]] # [chainId, [slug, CollectionDto]]
|
||||||
|
|
||||||
proc delete*(self: Service) =
|
proc delete*(self: Service) =
|
||||||
self.QObject.delete
|
self.QObject.delete
|
||||||
|
@ -100,115 +101,126 @@ QtObject:
|
||||||
result.threadpool = threadpool
|
result.threadpool = threadpool
|
||||||
result.networkService = networkService
|
result.networkService = networkService
|
||||||
result.ownershipData = newTable[int, AdressesData]()
|
result.ownershipData = newTable[int, AdressesData]()
|
||||||
result.data = newTable[int, TableRef[UniqueID, CollectibleDto]]()
|
result.collectibles = newTable[int, TableRef[UniqueID, CollectibleDto]]()
|
||||||
|
result.collections = newTable[int, TableRef[string, CollectionDto]]()
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc insertAddressIfNeeded*(self: Service, chainId: int, address: string) =
|
proc prepareOwnershipData(self: Service, chainId: int, address: string, reset: bool = false) =
|
||||||
if not self.ownershipData.hasKey(chainId):
|
if not self.ownershipData.hasKey(chainId):
|
||||||
self.ownershipData[chainId] = newTable[string, CollectionsData]()
|
self.ownershipData[chainId] = newTable[string, CollectiblesData]()
|
||||||
|
|
||||||
let chainData = self.ownershipData[chainId]
|
let chainData = self.ownershipData[chainId]
|
||||||
if not chainData.hasKey(address):
|
if reset or not chainData.hasKey(address):
|
||||||
chainData[address] = newCollectionsData()
|
chainData[address] = newCollectiblesData()
|
||||||
|
|
||||||
proc updateOwnedCollectionsCache*(self: Service, chainId: int, address: string, collections: seq[CollectionDto]) =
|
let addressData = self.ownershipData[chainId][address]
|
||||||
|
addressData.lastLoadWasFromStart = reset
|
||||||
|
if reset:
|
||||||
|
addressData.lastLoadFromStartTimestamp = now()
|
||||||
|
|
||||||
|
|
||||||
|
proc updateOwnedCollectibles(self: Service, chainId: int, address: string, previousCursor: string, nextCursor: string, collectibles: seq[CollectibleDto]) =
|
||||||
try:
|
try:
|
||||||
let oldAddressData = self.ownershipData[chainId][address]
|
let collectiblesData = self.ownershipData[chainId][address]
|
||||||
|
collectiblesData.previousCursor = previousCursor
|
||||||
# Start with empty object. Only add newly received collections, so removed ones are discarded
|
collectiblesData.nextCursor = nextCursor
|
||||||
let newAddressData = newCollectionsData()
|
collectiblesData.allLoaded = (nextCursor == "")
|
||||||
for collection in collections:
|
|
||||||
newAddressData.collections[collection.slug] = newCollectionData(collection)
|
|
||||||
if oldAddressData.collections.hasKey(collection.slug):
|
|
||||||
let oldCollection = oldAddressData.collections[collection.slug]
|
|
||||||
let newCollection = newAddressData.collections[collection.slug]
|
|
||||||
# Take collectibles from old collection
|
|
||||||
newCollection.collectiblesLoaded = oldCollection.collectiblesLoaded
|
|
||||||
newCollection.collectibles = oldCollection.collectibles
|
|
||||||
|
|
||||||
newAddressData.collectionsLoaded = true
|
|
||||||
self.ownershipData[chainId][address] = newAddressData
|
|
||||||
|
|
||||||
var data = OwnedCollectionsUpdateArgs()
|
|
||||||
data.chainId = chainId
|
|
||||||
data.address = address
|
|
||||||
|
|
||||||
self.events.emit(SIGNAL_OWNED_COLLECTIONS_UPDATED, data)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
let errDesription = e.msg
|
|
||||||
error "error: ", errDesription
|
|
||||||
|
|
||||||
proc updateOwnedCollectiblesCache*(self: Service, chainId: int, address: string, collectionSlug: string, collectibles: seq[CollectibleDto]) =
|
|
||||||
try:
|
|
||||||
let collection = self.ownershipData[chainId][address].collections[collectionSlug]
|
|
||||||
collection.collectibles.clear()
|
|
||||||
|
|
||||||
|
var count = 0
|
||||||
for collectible in collectibles:
|
for collectible in collectibles:
|
||||||
collection.collectibles[collectible.id] = collectible
|
let newId = UniqueID(
|
||||||
collection.collectiblesLoaded = true
|
contractAddress: collectible.address,
|
||||||
|
tokenId: collectible.tokenId
|
||||||
var data = OwnedCollectiblesUpdateArgs()
|
)
|
||||||
data.chainId = chainId
|
if not collectiblesData.ids.any(id => newId == id):
|
||||||
data.address = address
|
collectiblesData.ids.add(newId)
|
||||||
data.collectionSlug = collectionSlug
|
count = count + 1
|
||||||
self.events.emit(SIGNAL_OWNED_COLLECTIBLES_UPDATED, data)
|
collectiblesData.lastLoadCount = count
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDesription = e.msg
|
let errDesription = e.msg
|
||||||
error "error: ", errDesription
|
error "error: ", errDesription
|
||||||
|
|
||||||
proc updateCollectiblesCache*(self: Service, chainId: int, collectibles: seq[CollectibleDto]) =
|
proc updateCollectiblesCache*(self: Service, chainId: int, collectibles: seq[CollectibleDto], collections: seq[CollectionDto]) =
|
||||||
if not self.data.hasKey(chainId):
|
if not self.collectibles.hasKey(chainId):
|
||||||
self.data[chainId] = newTable[UniqueID, CollectibleDto]()
|
self.collectibles[chainId] = newTable[UniqueID, CollectibleDto]()
|
||||||
|
|
||||||
|
if not self.collections.hasKey(chainId):
|
||||||
|
self.collections[chainId] = newTable[string, CollectionDto]()
|
||||||
|
|
||||||
var data = CollectiblesUpdateArgs()
|
var data = CollectiblesUpdateArgs()
|
||||||
data.chainId = chainId
|
data.chainId = chainId
|
||||||
|
|
||||||
|
for collection in collections:
|
||||||
|
let slug = collection.slug
|
||||||
|
self.collections[chainId][slug] = collection
|
||||||
|
|
||||||
|
|
||||||
for collectible in collectibles:
|
for collectible in collectibles:
|
||||||
let id = UniqueID(
|
let id = UniqueID(
|
||||||
contractAddress: collectible.address,
|
contractAddress: collectible.address,
|
||||||
tokenId: collectible.tokenId
|
tokenId: collectible.tokenId
|
||||||
)
|
)
|
||||||
self.data[chainId][id] = collectible
|
self.collectibles[chainId][id] = collectible
|
||||||
data.ids.add(id)
|
data.ids.add(id)
|
||||||
|
|
||||||
self.events.emit(SIGNAL_COLLECTIBLES_UPDATED, data)
|
self.events.emit(SIGNAL_COLLECTIBLES_UPDATED, data)
|
||||||
|
|
||||||
proc getOwnedCollections*(self: Service, chainId: int, address: string) : CollectionsData =
|
proc getOwnedCollectibles*(self: Service, chainId: int, address: string) : CollectiblesData =
|
||||||
try:
|
try:
|
||||||
return self.ownershipData[chainId][address]
|
return self.ownershipData[chainId][address]
|
||||||
except:
|
except:
|
||||||
discard
|
discard
|
||||||
return newCollectionsData()
|
return newCollectiblesData()
|
||||||
|
|
||||||
proc getOwnedCollection*(self: Service, chainId: int, address: string, collectionSlug: string) : CollectionData =
|
|
||||||
try:
|
|
||||||
return self.ownershipData[chainId][address].collections[collectionSlug]
|
|
||||||
except:
|
|
||||||
discard
|
|
||||||
return newCollectionData(CollectionDto())
|
|
||||||
|
|
||||||
proc getCollectible*(self: Service, chainId: int, id: UniqueID) : CollectibleDto =
|
proc getCollectible*(self: Service, chainId: int, id: UniqueID) : CollectibleDto =
|
||||||
try:
|
try:
|
||||||
return self.data[chainId][id]
|
return self.collectibles[chainId][id]
|
||||||
except:
|
except:
|
||||||
discard
|
discard
|
||||||
return newCollectibleDto()
|
return newCollectibleDto()
|
||||||
|
|
||||||
proc onRxCollectibles*(self: Service, response: string) {.slot.} =
|
proc getCollection*(self: Service, chainId: int, slug: string) : CollectionDto =
|
||||||
|
try:
|
||||||
|
return self.collections[chainId][slug]
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
return newCollectionDto()
|
||||||
|
|
||||||
|
proc processCollectiblesResult(responseObj: JsonNode) : CollectiblesResult =
|
||||||
|
result.success = false
|
||||||
|
let collectiblesContainerJson = responseObj["collectibles"]
|
||||||
|
if collectiblesContainerJson.kind == JObject:
|
||||||
|
let previousCursorJson = collectiblesContainerJson["previous"]
|
||||||
|
let nextCursorJson = collectiblesContainerJson["next"]
|
||||||
|
let collectiblesJson = collectiblesContainerJson["assets"]
|
||||||
|
|
||||||
|
if previousCursorJson.kind == JString and nextCursorJson.kind == JString:
|
||||||
|
result.previousCursor = previousCursorJson.getStr()
|
||||||
|
result.nextCursor = nextCursorJson.getStr()
|
||||||
|
for collectibleJson in collectiblesJson.getElems():
|
||||||
|
if collectibleJson.kind == JObject:
|
||||||
|
result.collectibles.add(collectibleJson.toCollectibleDto())
|
||||||
|
let collectionJson = collectibleJson["collection"]
|
||||||
|
if collectionJson.kind == JObject:
|
||||||
|
result.collections.add(collectionJson.toCollectionDto())
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
result.success = true
|
||||||
|
|
||||||
|
proc onRxCollectibles(self: Service, response: string) {.slot.} =
|
||||||
try:
|
try:
|
||||||
let responseObj = response.parseJson
|
let responseObj = response.parseJson
|
||||||
if (responseObj.kind == JObject):
|
if (responseObj.kind == JObject):
|
||||||
let chainIdJson = responseObj["chainId"]
|
let chainIdJson = responseObj["chainId"]
|
||||||
let collectiblesJson = responseObj["collectibles"]
|
if chainIdJson.kind == JInt:
|
||||||
|
|
||||||
if (chainIdJson.kind == JInt and
|
|
||||||
collectiblesJson.kind == JArray):
|
|
||||||
let chainId = chainIdJson.getInt()
|
let chainId = chainIdJson.getInt()
|
||||||
let collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
|
let (success, collectibles, collections, _, _) = processCollectiblesResult(responseObj)
|
||||||
self.updateCollectiblesCache(chainId, collectibles)
|
if success:
|
||||||
|
self.updateCollectiblesCache(chainId, collectibles, collections)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDescription = e.msg
|
let errDescription = e.msg
|
||||||
error "error onRxCollectibles: ", errDescription
|
error "error onRxCollectibles: ", errDescription
|
||||||
|
@ -223,95 +235,63 @@ QtObject:
|
||||||
contractAddress: id.contractAddress,
|
contractAddress: id.contractAddress,
|
||||||
tokenID: id.tokenId.toString()
|
tokenID: id.tokenId.toString()
|
||||||
)),
|
)),
|
||||||
limit: limit
|
limit: len(ids)
|
||||||
)
|
|
||||||
self.threadpool.start(arg)
|
|
||||||
|
|
||||||
proc onRxOwnedCollections*(self: Service, response: string) {.slot.} =
|
|
||||||
try:
|
|
||||||
let responseObj = response.parseJson
|
|
||||||
if (responseObj.kind == JObject):
|
|
||||||
let chainIdJson = responseObj["chainId"]
|
|
||||||
let addressJson = responseObj["address"]
|
|
||||||
|
|
||||||
let validAccount = (chainIdJson.kind == JInt and
|
|
||||||
addressJson.kind == JString)
|
|
||||||
if (validAccount):
|
|
||||||
let chainId = chainIdJson.getInt()
|
|
||||||
let address = addressJson.getStr()
|
|
||||||
|
|
||||||
var collections: seq[CollectionDto]
|
|
||||||
let collectionsJson = responseObj["collections"]
|
|
||||||
if (collectionsJson.kind == JArray):
|
|
||||||
collections = map(collectionsJson.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
|
|
||||||
|
|
||||||
self.updateOwnedCollectionsCache(chainId, address, collections)
|
|
||||||
except Exception as e:
|
|
||||||
let errDescription = e.msg
|
|
||||||
error "error onRxOwnedCollections: ", errDescription
|
|
||||||
|
|
||||||
proc fetchOwnedCollections*(self: Service, chainId: int, address: string) =
|
|
||||||
self.insertAddressIfNeeded(chainId, address)
|
|
||||||
|
|
||||||
let arg = FetchOwnedCollectionsTaskArg(
|
|
||||||
tptr: cast[ByteAddress](fetchOwnedCollectionsTaskArg),
|
|
||||||
vptr: cast[ByteAddress](self.vptr),
|
|
||||||
slot: "onRxOwnedCollections",
|
|
||||||
chainId: chainId,
|
|
||||||
address: address,
|
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
proc onRxOwnedCollectibles*(self: Service, response: string) {.slot.} =
|
proc onRxOwnedCollectibles(self: Service, response: string) {.slot.} =
|
||||||
var data = OwnedCollectiblesUpdateArgs()
|
var data = OwnedCollectiblesUpdateArgs()
|
||||||
try:
|
try:
|
||||||
let responseObj = response.parseJson
|
let responseObj = response.parseJson
|
||||||
if (responseObj.kind == JObject):
|
if (responseObj.kind == JObject):
|
||||||
let chainIdJson = responseObj["chainId"]
|
let chainIdJson = responseObj["chainId"]
|
||||||
let addressJson = responseObj["address"]
|
let addressJson = responseObj["address"]
|
||||||
let collectionSlugJson = responseObj["collectionSlug"]
|
if (chainIdJson.kind == JInt and
|
||||||
|
addressJson.kind == JString):
|
||||||
let validCollection = (chainIdJson.kind == JInt and
|
data.chainId = chainIdJson.getInt()
|
||||||
addressJson.kind == JString and
|
data.address = addressJson.getStr()
|
||||||
collectionSlugJson.kind == JString)
|
self.ownershipData[data.chainId][data.address].isFetching = false
|
||||||
if (validCollection):
|
let (success, collectibles, collections, prevCursor, nextCursor) = processCollectiblesResult(responseObj)
|
||||||
let chainId = chainIdJson.getInt()
|
if success:
|
||||||
let address = addressJson.getStr()
|
self.updateCollectiblesCache(data.chainId, collectibles, collections)
|
||||||
let collectionSlug = collectionSlugJson.getStr()
|
self.updateOwnedCollectibles(data.chainId, data.address, prevCursor, nextCursor, collectibles)
|
||||||
|
|
||||||
var collectibles: seq[CollectibleDto]
|
|
||||||
let collectiblesJson = responseObj["collectibles"]
|
|
||||||
if (collectiblesJson.kind == JArray):
|
|
||||||
collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
|
|
||||||
self.updateOwnedCollectiblesCache(chainId, address, collectionSlug, collectibles)
|
|
||||||
self.updateCollectiblesCache(data.chainId, collectibles)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDescription = e.msg
|
let errDescription = e.msg
|
||||||
error "error onRxOwnedCollectibles: ", errDescription
|
error "error onRxOwnedCollectibles: ", errDescription
|
||||||
|
self.events.emit(SIGNAL_OWNED_COLLECTIBLES_UPDATE_FINISHED, data)
|
||||||
|
|
||||||
proc fetchOwnedCollectibles*(self: Service, chainId: int, address: string, collectionSlug: string) =
|
proc resetOwnedCollectibles*(self: Service, chainId: int, address: string) =
|
||||||
self.insertAddressIfNeeded(chainId, address)
|
self.prepareOwnershipData(chainId, address, true)
|
||||||
let collections = self.ownershipData[chainId][address].collections
|
var data = OwnedCollectiblesUpdateArgs()
|
||||||
|
data.chainId = chainId
|
||||||
|
data.address = address
|
||||||
|
self.events.emit(SIGNAL_OWNED_COLLECTIBLES_UPDATE_FINISHED, data)
|
||||||
|
|
||||||
if not collections.hasKey(collectionSlug):
|
proc fetchOwnedCollectibles*(self: Service, chainId: int, address: string, limit: int) =
|
||||||
error "error fetchOwnedCollectibles: Attempting to fetch collectibles from unknown collection: ", collectionSlug
|
self.prepareOwnershipData(chainId, address, false)
|
||||||
|
|
||||||
|
let collectiblesData = self.ownershipData[chainId][address]
|
||||||
|
|
||||||
|
if collectiblesData.isFetching:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if collectiblesData.allLoaded:
|
||||||
|
return
|
||||||
|
|
||||||
|
collectiblesData.isFetching = true
|
||||||
|
|
||||||
|
var data = OwnedCollectiblesUpdateArgs()
|
||||||
|
data.chainId = chainId
|
||||||
|
data.address = address
|
||||||
|
self.events.emit(SIGNAL_OWNED_COLLECTIBLES_UPDATE_STARTED, data)
|
||||||
|
|
||||||
let arg = FetchOwnedCollectiblesTaskArg(
|
let arg = FetchOwnedCollectiblesTaskArg(
|
||||||
tptr: cast[ByteAddress](fetchOwnedCollectiblesTaskArg),
|
tptr: cast[ByteAddress](fetchOwnedCollectiblesTaskArg),
|
||||||
vptr: cast[ByteAddress](self.vptr),
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
slot: "onRxOwnedCollectibles",
|
slot: "onRxOwnedCollectibles",
|
||||||
chainId: chainId,
|
chainId: chainId,
|
||||||
address: address,
|
address: address,
|
||||||
collectionSlug: collectionSlug,
|
cursor: collectiblesData.nextCursor,
|
||||||
limit: limit
|
limit: limit
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
proc fetchAllOwnedCollectibles*(self: Service, chainId: int, address: string) =
|
|
||||||
try:
|
|
||||||
for collectionSlug, _ in self.ownershipData[chainId][address].collections:
|
|
||||||
self.fetchOwnedCollectibles(chainId, address, collectionSlug)
|
|
||||||
except Exception as e:
|
|
||||||
let errDescription = e.msg
|
|
||||||
error "error fetchAllOwnedCollectibles: ", errDescription
|
|
||||||
|
|
|
@ -217,8 +217,12 @@ QtObject:
|
||||||
for tx in historyData["history"].getElems():
|
for tx in historyData["history"].getElems():
|
||||||
transactions.add(tx.toTransactionDto())
|
transactions.add(tx.toTransactionDto())
|
||||||
|
|
||||||
for c in historyData["collectibles"].getElems():
|
let collectiblesContainerJson = historyData["collectibles"]
|
||||||
collectibles.add(c.toCollectibleDto())
|
if collectiblesContainerJson.kind == JObject:
|
||||||
|
let collectiblesJson = collectiblesContainerJson["assets"]
|
||||||
|
if collectiblesJson.kind == JArray:
|
||||||
|
for c in collectiblesJson.getElems():
|
||||||
|
collectibles.add(c.toCollectibleDto())
|
||||||
|
|
||||||
if self.allTxLoaded.hasKey(address):
|
if self.allTxLoaded.hasKey(address):
|
||||||
self.allTxLoaded[address] = self.allTxLoaded[address] and allTxLoaded
|
self.allTxLoaded[address] = self.allTxLoaded[address] and allTxLoaded
|
||||||
|
|
|
@ -18,14 +18,10 @@ proc `==`*(a, b: NFTUniqueID): bool =
|
||||||
result = a.contractAddress == b.contractAddress and
|
result = a.contractAddress == b.contractAddress and
|
||||||
a.tokenID == b.tokenID
|
a.tokenID == b.tokenID
|
||||||
|
|
||||||
rpc(getOpenseaCollectionsByOwner, "wallet"):
|
rpc(getOpenseaAssetsByOwnerWithCursor, "wallet"):
|
||||||
chainId: int
|
chainId: int
|
||||||
address: string
|
address: string
|
||||||
|
cursor: string
|
||||||
rpc(getOpenseaAssetsByOwnerAndCollection, "wallet"):
|
|
||||||
chainId: int
|
|
||||||
address: string
|
|
||||||
collectionSlug: string
|
|
||||||
limit: int
|
limit: int
|
||||||
|
|
||||||
rpc(getOpenseaAssetsByNFTUniqueID, "wallet"):
|
rpc(getOpenseaAssetsByNFTUniqueID, "wallet"):
|
||||||
|
|
|
@ -33,6 +33,7 @@ ColumnLayout {
|
||||||
font.pixelSize: isNarrowMode ? 15 : 22
|
font.pixelSize: isNarrowMode ? 15 : 22
|
||||||
lineHeight: isNarrowMode ? 22 : 30
|
lineHeight: isNarrowMode ? 22 : 30
|
||||||
lineHeightMode: Text.FixedHeight
|
lineHeightMode: Text.FixedHeight
|
||||||
|
elide: Text.ElideRight
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +58,7 @@ ColumnLayout {
|
||||||
id: collectibleIdTopRow
|
id: collectibleIdTopRow
|
||||||
sourceComponent: collectibleIdComponent
|
sourceComponent: collectibleIdComponent
|
||||||
visible: !root.isNarrowMode
|
visible: !root.isNarrowMode
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
Binding {
|
Binding {
|
||||||
target: collectibleIdTopRow.item
|
target: collectibleIdTopRow.item
|
||||||
|
@ -74,6 +76,7 @@ ColumnLayout {
|
||||||
id: collectibleIdBottomRow
|
id: collectibleIdBottomRow
|
||||||
sourceComponent: collectibleIdComponent
|
sourceComponent: collectibleIdComponent
|
||||||
visible: root.isNarrowMode
|
visible: root.isNarrowMode
|
||||||
|
Layout.maximumWidth: root.width - parent.spacing - networkTag.width
|
||||||
|
|
||||||
Binding {
|
Binding {
|
||||||
target: collectibleIdBottomRow.item
|
target: collectibleIdBottomRow.item
|
||||||
|
|
|
@ -28,8 +28,7 @@ QtObject {
|
||||||
property string signingPhrase: walletSection.signingPhrase
|
property string signingPhrase: walletSection.signingPhrase
|
||||||
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp
|
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp
|
||||||
|
|
||||||
property var collections: walletSectionCollectibles.model
|
property var flatCollectibles: walletSectionCollectibles.model
|
||||||
property var flatCollectibles: walletSectionCollectibles.flatModel
|
|
||||||
property var currentCollectible: walletSectionCurrentCollectible
|
property var currentCollectible: walletSectionCurrentCollectible
|
||||||
|
|
||||||
property var savedAddresses: SortFilterProxyModel {
|
property var savedAddresses: SortFilterProxyModel {
|
||||||
|
@ -185,10 +184,6 @@ QtObject {
|
||||||
return globalUtils.hex2Dec(value)
|
return globalUtils.hex2Dec(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchOwnedCollectibles(slug) {
|
|
||||||
walletSectionCollectibles.fetchOwnedCollectibles(slug)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCollectionMaxValue(traitType, value, maxValue, collectionIndex) {
|
function getCollectionMaxValue(traitType, value, maxValue, collectionIndex) {
|
||||||
// Not Refactored Yet
|
// Not Refactored Yet
|
||||||
// if(maxValue !== "")
|
// if(maxValue !== "")
|
||||||
|
@ -198,8 +193,8 @@ QtObject {
|
||||||
// walletModelV2Inst.collectiblesView.collections.getCollectionTraitMaxValue(collectionIndex, traitType).toString();
|
// walletModelV2Inst.collectiblesView.collections.getCollectionTraitMaxValue(collectionIndex, traitType).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectCollectible(slug, id) {
|
function selectCollectible(address, tokenId) {
|
||||||
walletSectionCurrentCollectible.update(slug, id)
|
walletSectionCurrentCollectible.update(address, tokenId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNameForSavedWalletAddress(address) {
|
function getNameForSavedWalletAddress(address) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Controls 2.13
|
||||||
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.Controls 0.1
|
||||||
|
|
||||||
import shared.panels 1.0
|
import shared.panels 1.0
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
@ -15,9 +16,7 @@ Item {
|
||||||
property var collectiblesModel
|
property var collectiblesModel
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
signal collectibleClicked(string collectionSlug, int collectibleId)
|
signal collectibleClicked(string address, string tokenId)
|
||||||
|
|
||||||
readonly property bool areCollectionsLoaded: root.collectiblesModel.collectionsLoaded
|
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
|
@ -25,7 +24,7 @@ Item {
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
if (root.areCollectionsLoaded && root.collectiblesModel.collectionCount === 0)
|
if (root.collectiblesModel.allCollectiblesLoaded && root.collectiblesModel.count === 0)
|
||||||
return empty;
|
return empty;
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
|
@ -49,18 +48,19 @@ Item {
|
||||||
StatusGridView {
|
StatusGridView {
|
||||||
id: gridView
|
id: gridView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
model: root.areCollectionsLoaded ? root.collectiblesModel : Constants.dummyModelItems
|
model: root.collectiblesModel
|
||||||
cellHeight: 229
|
cellHeight: 229
|
||||||
cellWidth: 176
|
cellWidth: 176
|
||||||
delegate: CollectibleView {
|
delegate: CollectibleView {
|
||||||
height: gridView.cellHeight
|
height: gridView.cellHeight
|
||||||
width: gridView.cellWidth
|
width: gridView.cellWidth
|
||||||
collectibleModel: root.areCollectionsLoaded ? model : undefined
|
collectibleModel: model
|
||||||
isLoadingDelegate: !root.areCollectionsLoaded
|
|
||||||
onCollectibleClicked: {
|
onCollectibleClicked: {
|
||||||
root.collectibleClicked(slug, collectibleId);
|
root.collectibleClicked(address, tokenId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrollBar.vertical: StatusScrollBar {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ Item {
|
||||||
CollectiblesView {
|
CollectiblesView {
|
||||||
collectiblesModel: RootStore.flatCollectibles
|
collectiblesModel: RootStore.flatCollectibles
|
||||||
onCollectibleClicked: {
|
onCollectibleClicked: {
|
||||||
RootStore.selectCollectible(collectionSlug, collectibleId)
|
RootStore.selectCollectible(address, tokenId)
|
||||||
stack.currentIndex = 1
|
stack.currentIndex = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import StatusQ.Components 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared.controls 1.0
|
import shared.controls 1.0
|
||||||
|
@ -26,7 +27,7 @@ Item {
|
||||||
asset.name: currentCollectible.collectionImageUrl
|
asset.name: currentCollectible.collectionImageUrl
|
||||||
asset.isImage: true
|
asset.isImage: true
|
||||||
primaryText: currentCollectible.collectionName
|
primaryText: currentCollectible.collectionName
|
||||||
secondaryText: currentCollectible.id
|
secondaryText: "#" + currentCollectible.tokenId
|
||||||
isNarrowMode: root.isNarrowMode
|
isNarrowMode: root.isNarrowMode
|
||||||
networkShortName: currentCollectible.networkShortName
|
networkShortName: currentCollectible.networkShortName
|
||||||
networkColor: currentCollectible.networkColor
|
networkColor: currentCollectible.networkColor
|
||||||
|
|
|
@ -15,14 +15,12 @@ Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var collectibleModel
|
property var collectibleModel
|
||||||
property bool isLoadingDelegate
|
|
||||||
|
|
||||||
signal collectibleClicked(string slug, int collectibleId)
|
signal collectibleClicked(string address, string tokenId)
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
readonly property bool modeDataValid: !!root.collectibleModel && root.collectibleModel !== undefined
|
readonly property bool modeDataValid: !!root.collectibleModel && root.collectibleModel !== undefined && root.collectibleModel.id >= 0
|
||||||
readonly property bool isLoaded: modeDataValid ? root.collectibleModel.collectionCollectiblesLoaded : false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitHeight: 225
|
implicitHeight: 225
|
||||||
|
@ -48,7 +46,7 @@ Item {
|
||||||
color: d.modeDataValid ? root.collectibleModel.backgroundColor : "transparent"
|
color: d.modeDataValid ? root.collectibleModel.backgroundColor : "transparent"
|
||||||
Loader {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: root.isLoadingDelegate
|
active: root.collectibleModel.isLoading
|
||||||
sourceComponent: LoadingComponent {radius: image.radius}
|
sourceComponent: LoadingComponent {radius: image.radius}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +55,7 @@ Item {
|
||||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
Layout.leftMargin: 8
|
Layout.leftMargin: 8
|
||||||
Layout.topMargin: 9
|
Layout.topMargin: 9
|
||||||
Layout.preferredWidth: isLoadingDelegate ? 134 : 144
|
Layout.preferredWidth: root.collectibleModel.isLoading ? 134 : 144
|
||||||
Layout.preferredHeight: 21
|
Layout.preferredHeight: 21
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
@ -65,22 +63,22 @@ Item {
|
||||||
customColor: Theme.palette.directColor1
|
customColor: Theme.palette.directColor1
|
||||||
font.weight: Font.DemiBold
|
font.weight: Font.DemiBold
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
text: isLoadingDelegate ? Constants.dummyText : d.isLoaded && d.modeDataValid ? root.collectibleModel.name : "..."
|
text: root.collectibleModel.isLoading ? Constants.dummyText : d.modeDataValid ? root.collectibleModel.name : "..."
|
||||||
loading: root.isLoadingDelegate
|
loading: root.collectibleModel.isLoading
|
||||||
}
|
}
|
||||||
StatusTextWithLoadingState {
|
StatusTextWithLoadingState {
|
||||||
id: collectionLabel
|
id: collectionLabel
|
||||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
Layout.leftMargin: 8
|
Layout.leftMargin: 8
|
||||||
Layout.preferredWidth: isLoadingDelegate ? 88 : 144
|
Layout.preferredWidth: root.collectibleModel.isLoading ? 88 : 144
|
||||||
Layout.preferredHeight: 18
|
Layout.preferredHeight: 18
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
font.pixelSize: 13
|
font.pixelSize: 13
|
||||||
customColor: Theme.palette.baseColor1
|
customColor: Theme.palette.baseColor1
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
text: isLoadingDelegate ? Constants.dummyText : d.modeDataValid ? root.collectibleModel.collectionName : ""
|
text: root.collectibleModel.isLoading ? Constants.dummyText : d.modeDataValid ? root.collectibleModel.collectionName : "..."
|
||||||
loading: root.isLoadingDelegate
|
loading: root.collectibleModel.isLoading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,15 +88,15 @@ Item {
|
||||||
border.width: 1
|
border.width: 1
|
||||||
border.color: Theme.palette.primaryColor1
|
border.color: Theme.palette.primaryColor1
|
||||||
color: Theme.palette.indirectColor3
|
color: Theme.palette.indirectColor3
|
||||||
visible: d.isLoaded && mouse.containsMouse
|
visible: !root.collectibleModel.isLoading && mouse.containsMouse
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouse
|
id: mouse
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (d.isLoaded) {
|
if (d.modeDataValid && !root.collectibleModel.isLoading) {
|
||||||
root.collectibleClicked(root.collectibleModel.collectionSlug, root.collectibleModel.id);
|
root.collectibleClicked(root.collectibleModel.address, root.collectibleModel.tokenId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f60716412259aece88d899d09fc71de4c4ba5d2e
|
Subproject commit 5ecb7b68eefada3725c360f68fba7ac92b612c82
|
Loading…
Reference in New Issue