parent
45adf0f411
commit
20733272f2
|
@ -42,6 +42,7 @@ proc init*(self: Controller) =
|
|||
self.events.on(SIGNAL_COLLECTIONS_UPDATED) do(e:Args):
|
||||
let args = CollectionsUpdateArgs(e)
|
||||
self.refreshCollections(args.chainId, args.address)
|
||||
self.collectibleService.fetchAllCollectibles(args.chainId, args.address)
|
||||
|
||||
self.events.on(SIGNAL_COLLECTIBLES_UPDATED) do(e:Args):
|
||||
let args = CollectiblesUpdateArgs(e)
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
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)
|
|
@ -1,9 +1,9 @@
|
|||
import NimQml, Tables, strutils, strformat
|
||||
import NimQml, Tables, strutils, strformat, sequtils
|
||||
|
||||
import ./collectibles_item, ./collectible_trait_model
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
CollectibleRole* {.pure.} = enum
|
||||
Id = UserRole + 1,
|
||||
Name
|
||||
ImageUrl
|
||||
|
@ -26,37 +26,39 @@ QtObject:
|
|||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newModel*(): Model =
|
||||
proc newModel*(items: seq[Item]): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
result.items = items
|
||||
|
||||
proc newModel*(): Model =
|
||||
return newModel(@[])
|
||||
|
||||
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.} =
|
||||
proc getCount*(self: Model): int {.slot.} =
|
||||
self.items.len
|
||||
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
method rowCount*(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
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",
|
||||
CollectibleRole.Id.int:"id",
|
||||
CollectibleRole.Name.int:"name",
|
||||
CollectibleRole.ImageUrl.int:"imageUrl",
|
||||
CollectibleRole.BackgroundColor.int:"backgroundColor",
|
||||
CollectibleRole.Description.int:"description",
|
||||
CollectibleRole.Permalink.int:"permalink",
|
||||
CollectibleRole.Properties.int:"properties",
|
||||
CollectibleRole.Rankings.int:"rankings",
|
||||
CollectibleRole.Stats.int:"stats",
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -67,36 +69,42 @@ QtObject:
|
|||
return
|
||||
|
||||
let item = self.items[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
let enumRole = role.CollectibleRole
|
||||
|
||||
case enumRole:
|
||||
of ModelRole.Id:
|
||||
of CollectibleRole.Id:
|
||||
result = newQVariant(item.getId())
|
||||
of ModelRole.Name:
|
||||
of CollectibleRole.Name:
|
||||
result = newQVariant(item.getName())
|
||||
of ModelRole.ImageUrl:
|
||||
of CollectibleRole.ImageUrl:
|
||||
result = newQVariant(item.getImageUrl())
|
||||
of ModelRole.BackgroundColor:
|
||||
of CollectibleRole.BackgroundColor:
|
||||
result = newQVariant(item.getBackgroundColor())
|
||||
of ModelRole.Description:
|
||||
of CollectibleRole.Description:
|
||||
result = newQVariant(item.getDescription())
|
||||
of ModelRole.Permalink:
|
||||
of CollectibleRole.Permalink:
|
||||
result = newQVariant(item.getPermalink())
|
||||
of ModelRole.Properties:
|
||||
of CollectibleRole.Properties:
|
||||
let traits = newTraitModel()
|
||||
traits.setItems(item.getProperties())
|
||||
result = newQVariant(traits)
|
||||
of ModelRole.Rankings:
|
||||
of CollectibleRole.Rankings:
|
||||
let traits = newTraitModel()
|
||||
traits.setItems(item.getRankings())
|
||||
result = newQVariant(traits)
|
||||
of ModelRole.Stats:
|
||||
of CollectibleRole.Stats:
|
||||
let traits = newTraitModel()
|
||||
traits.setItems(item.getStats())
|
||||
result = newQVariant(traits)
|
||||
|
||||
proc getItem*(self: Model, index: int): Item =
|
||||
return self.items[index]
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
self.items = items
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
||||
self.beginResetModel()
|
||||
self.items = items
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
||||
|
||||
proc appendItems*(self: Model, items: seq[Item]) =
|
||||
self.setItems(concat(self.items, items))
|
|
@ -0,0 +1,16 @@
|
|||
import sequtils, sugar
|
||||
import ../../../../../../app_service/service/collectible/dto
|
||||
import collectibles_item, collectible_trait_item
|
||||
|
||||
proc collectibleToItem*(c: CollectibleDto) : Item =
|
||||
return initItem(
|
||||
c.id,
|
||||
c.name,
|
||||
c.imageUrl,
|
||||
c.backgroundColor,
|
||||
c.description,
|
||||
c.permalink,
|
||||
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.statistics.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue))
|
||||
)
|
|
@ -17,8 +17,7 @@ proc initItem*(name, slug, imageUrl: string, ownedAssetCount: int, collectiblesL
|
|||
result.imageUrl = imageUrl
|
||||
result.ownedAssetCount = ownedAssetCount
|
||||
result.collectiblesLoaded = collectiblesLoaded
|
||||
result.collectiblesModel = collectibles_model.newModel()
|
||||
result.collectiblesModel.setItems(collectibles)
|
||||
result.collectiblesModel = collectibles_model.newModel(collectibles)
|
||||
|
||||
proc initItem*(): Item =
|
||||
result = initItem("", "", "", 0, false, @[])
|
||||
|
|
|
@ -4,8 +4,9 @@ import ./collections_item as collections_item
|
|||
|
||||
import ./collectibles_model as collectibles_model
|
||||
import ./collectibles_item as collectibles_item
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
CollectionRole* {.pure.} = enum
|
||||
Name = UserRole + 1,
|
||||
Slug
|
||||
ImageUrl
|
||||
|
@ -36,34 +37,30 @@ QtObject:
|
|||
result &= fmt"""[{i}]:({$self.items[i]})"""
|
||||
|
||||
proc countChanged(self: Model) {.signal.}
|
||||
|
||||
proc getCount(self: Model): int {.slot.} =
|
||||
proc getCount*(self: Model): int {.slot.} =
|
||||
self.items.len
|
||||
|
||||
QtProperty[int] collectionsLoaded:
|
||||
read = getCollectionsLoaded
|
||||
notify = collectionsLoadedChanged
|
||||
|
||||
proc collectionsLoadedChanged(self: Model) {.signal.}
|
||||
|
||||
proc getCollectionsLoaded(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] =
|
||||
{
|
||||
ModelRole.Name.int:"name",
|
||||
ModelRole.Slug.int:"slug",
|
||||
ModelRole.ImageUrl.int:"imageUrl",
|
||||
ModelRole.OwnedAssetCount.int:"ownedAssetCount",
|
||||
ModelRole.CollectiblesLoaded.int:"collectiblesLoaded",
|
||||
ModelRole.CollectiblesModel.int:"collectiblesModel"
|
||||
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 =
|
||||
|
@ -74,29 +71,39 @@ QtObject:
|
|||
return
|
||||
|
||||
let item = self.items[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
let enumRole = role.CollectionRole
|
||||
|
||||
case enumRole:
|
||||
of ModelRole.Name:
|
||||
of CollectionRole.Name:
|
||||
result = newQVariant(item.getName())
|
||||
of ModelRole.Slug:
|
||||
of CollectionRole.Slug:
|
||||
result = newQVariant(item.getSlug())
|
||||
of ModelRole.ImageUrl:
|
||||
of CollectionRole.ImageUrl:
|
||||
result = newQVariant(item.getImageUrl())
|
||||
of ModelRole.OwnedAssetCount:
|
||||
of CollectionRole.OwnedAssetCount:
|
||||
result = newQVariant(item.getOwnedAssetCount())
|
||||
of ModelRole.CollectiblesLoaded:
|
||||
of CollectionRole.CollectiblesLoaded:
|
||||
result = newQVariant(item.getCollectiblesLoaded())
|
||||
of ModelRole.CollectiblesModel:
|
||||
of CollectionRole.CollectiblesModel:
|
||||
result = newQVariant(item.getCollectiblesModel())
|
||||
|
||||
proc setItems*(self: Model, items: seq[collections_item.Item]) =
|
||||
proc setCollections*(self: Model, items: seq[collections_item.Item], collectionsLoaded: bool) =
|
||||
self.beginResetModel()
|
||||
self.items = items
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
||||
self.collectionsLoaded = true
|
||||
self.collectionsLoadedChanged()
|
||||
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:
|
||||
|
@ -104,15 +111,21 @@ QtObject:
|
|||
return i
|
||||
return -1
|
||||
|
||||
proc updateCollectionCollectibles*(self: Model, slug: string, collectibles: seq[collectibles_item.Item]) =
|
||||
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 index = self.createIndex(idx, 0, nil)
|
||||
|
||||
let collectiblesModel = self.items[idx].getCollectiblesModel()
|
||||
collectiblesModel.setItems(collectibles)
|
||||
self.dataChanged(index, index, @[ModelRole.CollectiblesModel.int])
|
||||
self.emitDataChanged(idx, idx, CollectionRole.CollectiblesModel.int)
|
||||
|
||||
if not self.items[idx].getCollectiblesLoaded():
|
||||
self.items[idx].collectiblesLoaded = true
|
||||
self.dataChanged(index, index, @[ModelRole.CollectiblesLoaded.int])
|
||||
if self.items[idx].getCollectiblesLoaded() != collectiblesLoaded:
|
||||
self.items[idx].collectiblesLoaded = collectiblesLoaded
|
||||
self.emitDataChanged(idx, idx, CollectionRole.CollectiblesLoaded.int)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
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))
|
||||
)
|
|
@ -6,15 +6,17 @@ import ../../../../core/eventemitter
|
|||
import ./io_interface, ./view, ./controller
|
||||
import ../io_interface as delegate_interface
|
||||
import ../../../../../app_service/service/collectible/service as collectible_service
|
||||
import ../../../../../app_service/service/collectible/service as collectible_dto
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
|
||||
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/collectible_trait_item as collectible_trait_item
|
||||
import ./models/collections_item as collections_item
|
||||
import ./models/collectibles_utils
|
||||
import ./models/collectibles_model as collectibles_model
|
||||
|
||||
export io_interface
|
||||
|
||||
|
@ -86,37 +88,31 @@ method switchAccount*(self: Module, accountIndex: int) =
|
|||
|
||||
self.currentCollectibleModule.setCurrentAddress(network, self.address)
|
||||
|
||||
proc collectibleToItem(c: collectible_dto.CollectibleDto) : collectibles_item.Item =
|
||||
return collectibles_item.initItem(
|
||||
c.id,
|
||||
c.name,
|
||||
c.imageUrl,
|
||||
c.backgroundColor,
|
||||
c.description,
|
||||
c.permalink,
|
||||
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.statistics.map(t => initTrait(t.traitType, t.value, t.displayType, t.maxValue))
|
||||
)
|
||||
|
||||
proc collectionToItem(c: CollectionData) : collections_item.Item =
|
||||
return collections_item.initItem(
|
||||
c.collection.name,
|
||||
c.collection.slug,
|
||||
c.collection.imageUrl,
|
||||
c.collection.ownedAssetCount,
|
||||
c.collectiblesLoaded,
|
||||
toSeq(c.collectibles.values).map(c => collectibleToItem(c))
|
||||
)
|
||||
proc collectionToItem(self: Module, collection: CollectionData) : collections_item.Item =
|
||||
var item = collectionToItem(collection)
|
||||
#[ Skeleton items are disabled until problem with OpenSea API is researched.
|
||||
OpenSea is telling us the address owns a certain amount of NFTs from a certain collection, but
|
||||
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) =
|
||||
self.view.setCollections(
|
||||
toSeq(collections.collections.values).map(c => collectionToItem(c))
|
||||
toSeq(collections.collections.values).map(c => self.collectionToItem(c)),
|
||||
collections.collectionsLoaded
|
||||
)
|
||||
|
||||
method updateCollection*(self: Module, collection: CollectionData) =
|
||||
self.view.setCollectibles(collection.collection.slug,
|
||||
toSeq(collection.collectibles.values).map(c => collectibleToItem(c))
|
||||
toSeq(collection.collectibles.values).map(c => collectibleToItem(c)),
|
||||
collection.collectiblesLoaded
|
||||
)
|
||||
|
||||
method fetchCollections*(self: Module) =
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import NimQml
|
||||
|
||||
import ./models/collections_model
|
||||
import ./models/collections_model as collections_model
|
||||
import ./models/collectibles_flat_proxy_model as flat_model
|
||||
import ./models/collections_item as collections_item
|
||||
import ./models/collectibles_item as collectibles_item
|
||||
import ./io_interface
|
||||
|
@ -9,12 +10,12 @@ QtObject:
|
|||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
model: Model
|
||||
modelVariant: QVariant
|
||||
model: collections_model.Model
|
||||
flatModel: flat_model.Model
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.flatModel.delete
|
||||
self.model.delete
|
||||
self.modelVariant.delete
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
|
@ -22,28 +23,33 @@ QtObject:
|
|||
result.QObject.setup
|
||||
result.delegate = delegate
|
||||
result.model = newModel()
|
||||
result.modelVariant = newQVariant(result.model)
|
||||
result.flatModel = flat_model.newModel(result.model)
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc modelChanged*(self: View) {.signal.}
|
||||
|
||||
proc getModel(self: View): QVariant {.slot.} =
|
||||
return self.modelVariant
|
||||
|
||||
return newQVariant(self.model)
|
||||
QtProperty[QVariant] model:
|
||||
read = getModel
|
||||
notify = modelChanged
|
||||
|
||||
proc setCollections*(self: View, collections: seq[collections_item.Item]) =
|
||||
self.model.setItems(collections)
|
||||
|
||||
proc setCollectibles*(self: View, collectionsSlug: string, collectibles: seq[collectibles_item.Item]) =
|
||||
self.model.updateCollectionCollectibles(collectionsSlug, collectibles)
|
||||
proc flatModelChanged*(self: View) {.signal.}
|
||||
proc getFlatModel(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.flatModel)
|
||||
QtProperty[QVariant] flatModel:
|
||||
read = getFlatModel
|
||||
notify = flatModelChanged
|
||||
|
||||
proc fetchCollections*(self: View) {.slot.} =
|
||||
self.delegate.fetchCollections()
|
||||
|
||||
proc fetchCollectibles*(self: View, collectionSlug: string) {.slot.} =
|
||||
self.delegate.fetchCollectibles(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)
|
||||
|
|
|
@ -165,11 +165,12 @@ QtObject:
|
|||
data.chainId = chainIdJson.getInt()
|
||||
data.address = addressJson.getStr()
|
||||
|
||||
var collections: seq[CollectionDto]
|
||||
let collectionsJson = responseObj["collections"]
|
||||
if (collectionsJson.kind == JArray):
|
||||
let collections = map(collectionsJson.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
|
||||
self.setCollections(data.chainId, data.address, collections)
|
||||
self.events.emit(SIGNAL_COLLECTIONS_UPDATED, data)
|
||||
collections = map(collectionsJson.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
|
||||
self.setCollections(data.chainId, data.address, collections)
|
||||
self.events.emit(SIGNAL_COLLECTIONS_UPDATED, data)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error onRxCollections: ", errDescription
|
||||
|
@ -208,11 +209,12 @@ QtObject:
|
|||
data.address = addressJson.getStr()
|
||||
data.collectionSlug = collectionSlugJson.getStr()
|
||||
|
||||
var collectibles: seq[CollectibleDto]
|
||||
let collectiblesJson = responseObj["collectibles"]
|
||||
if (collectiblesJson.kind == JArray):
|
||||
let collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
|
||||
self.setCollectibles(data.chainId, data.address, data.collectionSlug, collectibles)
|
||||
self.events.emit(SIGNAL_COLLECTIBLES_UPDATED, data)
|
||||
collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
|
||||
self.setCollectibles(data.chainId, data.address, data.collectionSlug, collectibles)
|
||||
self.events.emit(SIGNAL_COLLECTIBLES_UPDATED, data)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error onRxCollectibles: ", errDescription
|
||||
|
@ -241,3 +243,11 @@ QtObject:
|
|||
limit: limit
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc fetchAllCollectibles*(self: Service, chainId: int, address: string) =
|
||||
try:
|
||||
for collectionSlug, _ in self.data[chainId][address].collections:
|
||||
self.fetchCollectibles(chainId, address, collectionSlug)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error fetchAllCollectibles: ", errDescription
|
||||
|
|
|
@ -31,6 +31,7 @@ QtObject {
|
|||
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp
|
||||
|
||||
property var collections: walletSectionCollectibles.model
|
||||
property var flatCollectibles: walletSectionCollectibles.flatModel
|
||||
property var currentCollectible: walletSectionCurrentCollectible
|
||||
|
||||
property var savedAddresses: walletSectionSavedAddresses.model
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import utils 1.0
|
||||
import shared 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import "../stores"
|
||||
import "../popups"
|
||||
import "collectibles"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var collectiblesModel
|
||||
width: parent.width
|
||||
|
||||
signal collectibleClicked(string collectionSlug, int collectibleId)
|
||||
|
||||
readonly property bool areCollectionsLoaded: root.collectiblesModel.collectionsLoaded
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
sourceComponent: {
|
||||
if (!RootStore.collections.collectionsLoaded)
|
||||
if (!root.areCollectionsLoaded)
|
||||
{
|
||||
return loading
|
||||
} else if (RootStore.collections.count === 0) {
|
||||
} else if (root.collectiblesModel.collectionCount === 0) {
|
||||
return empty;
|
||||
} else if (root.collectiblesModel.count === 0) {
|
||||
return loading
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
@ -64,42 +65,21 @@ Item {
|
|||
|
||||
Component {
|
||||
id: loaded
|
||||
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
|
||||
Column {
|
||||
id: collectiblesSection
|
||||
width: root.width
|
||||
|
||||
Repeater {
|
||||
objectName: "collectionsRepeater"
|
||||
id: collectionsRepeater
|
||||
model: RootStore.collections
|
||||
delegate: StatusExpandableItem {
|
||||
id: collectionDelegate
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
primaryText: model.name
|
||||
asset.name: model.imageUrl
|
||||
asset.isImage: true
|
||||
type: StatusExpandableItem.Type.Secondary
|
||||
expandableComponent: CollectibleCollectionView {
|
||||
collectionImageUrl: model.imageUrl
|
||||
collectiblesLoaded: model.collectiblesLoaded
|
||||
collectiblesModel: model.collectiblesModel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
onCollectibleClicked: {
|
||||
RootStore.selectCollectible(model.slug, collectibleId)
|
||||
root.collectibleClicked(model.slug, collectibleId);
|
||||
}
|
||||
}
|
||||
onExpandedChanged: {
|
||||
if(expanded) {
|
||||
RootStore.fetchCollectibles(model.slug)
|
||||
}
|
||||
}
|
||||
StatusGridView {
|
||||
id: gridView
|
||||
anchors.fill: parent
|
||||
model: root.collectiblesModel
|
||||
cellHeight: 229
|
||||
cellWidth: 176
|
||||
delegate: Item {
|
||||
height: gridView.cellHeight
|
||||
width: gridView.cellWidth
|
||||
CollectibleView {
|
||||
collectibleModel: model
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: 4
|
||||
onCollectibleClicked: {
|
||||
root.collectibleClicked(slug, collectibleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,9 @@ Item {
|
|||
}
|
||||
}
|
||||
CollectiblesView {
|
||||
collectiblesModel: RootStore.flatCollectibles
|
||||
onCollectibleClicked: {
|
||||
RootStore.selectCollectible(collectionSlug, collectibleId)
|
||||
stack.currentIndex = 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import shared.panels 1.0
|
||||
|
||||
import "../../stores"
|
||||
import utils 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string collectionImageUrl: ""
|
||||
property bool collectiblesLoaded: false
|
||||
property var collectiblesModel
|
||||
|
||||
width: parent.width
|
||||
height: contentLoader.height
|
||||
|
||||
signal collectibleClicked(int collectibleId)
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
width: parent.width
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 16
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
sourceComponent: {
|
||||
if (!root.collectiblesLoaded) {
|
||||
return loading
|
||||
} else if (root.collectiblesModel.count === 0) {
|
||||
return empty
|
||||
}
|
||||
return loaded
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loading
|
||||
|
||||
Item {
|
||||
id: loadingIndicator
|
||||
height: 164
|
||||
StatusLoadingIndicator {
|
||||
width: 20
|
||||
height: 20
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: empty
|
||||
|
||||
Item {
|
||||
id: emptyContainer
|
||||
height: 164
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Style.current.secondaryText
|
||||
text: qsTr("No collectibles available")
|
||||
font.pixelSize: 15
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loaded
|
||||
|
||||
Flow {
|
||||
width: parent.width
|
||||
|
||||
bottomPadding: 16
|
||||
spacing: 24
|
||||
|
||||
Component {
|
||||
id: collectibleDelegate
|
||||
|
||||
StatusRoundedImage {
|
||||
id: image
|
||||
width: 146
|
||||
height: 146
|
||||
radius: 16
|
||||
image.source: model.imageUrl
|
||||
border.color: Theme.palette.baseColor2
|
||||
border.width: 1
|
||||
showLoadingIndicator: true
|
||||
color: model.backgroundColor
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: image.width
|
||||
height: image.height
|
||||
radius: image.radius
|
||||
border.width: 1
|
||||
border.color: Theme.palette.primaryColor1
|
||||
color: Theme.palette.indirectColor3
|
||||
visible: mouse.containsMouse
|
||||
}
|
||||
MouseArea {
|
||||
id: mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
root.collectibleClicked(model.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
objectName: "collectiblesRepeater"
|
||||
model: root.collectiblesModel
|
||||
delegate: collectibleDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import shared.panels 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var collectibleModel
|
||||
|
||||
implicitHeight: 225
|
||||
implicitWidth: 176
|
||||
|
||||
signal collectibleClicked(string slug, int collectibleId)
|
||||
|
||||
readonly property bool isLoaded: root.collectibleModel.collectionCollectiblesLoaded
|
||||
|
||||
ColumnLayout {
|
||||
//Layout.fillHeight: true
|
||||
//Layout.fillWidth: true
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 0
|
||||
|
||||
StatusRoundedImage {
|
||||
id: image
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.topMargin: 8
|
||||
Layout.bottomMargin: 0
|
||||
implicitWidth: 160
|
||||
implicitHeight: 160
|
||||
radius: 12
|
||||
image.source: root.collectibleModel.imageUrl
|
||||
border.color: Theme.palette.baseColor2
|
||||
border.width: 1
|
||||
showLoadingIndicator: true
|
||||
color: root.collectibleModel.backgroundColor
|
||||
}
|
||||
StatusBaseText {
|
||||
id: collectibleLabel
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.topMargin: 9
|
||||
Layout.preferredWidth: 144
|
||||
Layout.preferredHeight: 21
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
font.weight: Font.DemiBold
|
||||
elide: Text.ElideRight
|
||||
text: isLoaded ? root.collectibleModel.name : "..."
|
||||
}
|
||||
StatusBaseText {
|
||||
id: collectionLabel
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.topMargin: 0
|
||||
Layout.preferredWidth: 144
|
||||
Layout.preferredHeight: 18
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.baseColor1
|
||||
elide: Text.ElideRight
|
||||
text: root.collectibleModel.collectionName
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 18
|
||||
border.width: 1
|
||||
border.color: Theme.palette.primaryColor1
|
||||
color: Theme.palette.indirectColor3
|
||||
visible: root.isLoaded && mouse.containsMouse
|
||||
}
|
||||
MouseArea {
|
||||
id: mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
if (root.isLoaded) {
|
||||
root.collectibleClicked(root.collectibleModel.collectionSlug, root.collectibleModel.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue