feat(@wallet): update collectibles model only with changes
Fixes #13254
This commit is contained in:
parent
2fa65968c0
commit
48f8fb3e55
|
@ -223,6 +223,12 @@ QtObject:
|
|||
of "communityColor": result = item.getCommunityColor()
|
||||
of "communityPrivilegesLevel": result = $item.getCommunityPrivilegesLevel()
|
||||
|
||||
proc resetCollectibleItems(self: Model, newItems: seq[CollectiblesEntry] = @[]) =
|
||||
self.beginResetModel()
|
||||
self.items = newItems
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
||||
|
||||
proc appendCollectibleItems(self: Model, newItems: seq[CollectiblesEntry]) =
|
||||
if len(newItems) == 0:
|
||||
return
|
||||
|
@ -239,23 +245,58 @@ QtObject:
|
|||
self.items.insert(newItems, startIdx)
|
||||
self.endInsertRows()
|
||||
self.countChanged()
|
||||
|
||||
proc removeCollectibleItems(self: Model) =
|
||||
if self.items.len <= 0:
|
||||
|
||||
proc removeCollectibleItem(self: Model, idx: int) =
|
||||
if idx < 0 or idx >= self.items.len:
|
||||
return
|
||||
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
# Start from the beginning
|
||||
let startIdx = 0
|
||||
# End at the last real item
|
||||
let endIdx = startIdx + self.items.len - 1
|
||||
|
||||
self.beginRemoveRows(parentModelIndex, startIdx, endIdx)
|
||||
self.items = @[]
|
||||
|
||||
self.beginRemoveRows(parentModelIndex, idx, idx)
|
||||
self.items.delete(idx)
|
||||
self.endRemoveRows()
|
||||
self.countChanged()
|
||||
|
||||
proc updateCollectibleItems(self: Model, newItems: seq[CollectiblesEntry]) =
|
||||
if len(self.items) == 0:
|
||||
# Current list is empty, just replace with new list
|
||||
self.resetCollectibleItems(newItems)
|
||||
return
|
||||
|
||||
if len(newItems) == 0:
|
||||
# New list is empty, just remove all items
|
||||
self.resetCollectibleItems()
|
||||
return
|
||||
|
||||
var newTable = initTable[string, int](len(newItems))
|
||||
for i in 0 ..< len(newItems):
|
||||
newTable.add(newItems[i].getID(), i)
|
||||
|
||||
# Needs to be built in sequential index order
|
||||
var oldIndicesToRemove: seq[int] = @[]
|
||||
for idx in 0 ..< len(self.items):
|
||||
let uid = self.items[idx].getID()
|
||||
if not newTable.hasKey(uid):
|
||||
# Item in old list but not in new -> Must remove
|
||||
oldIndicesToRemove.add(idx)
|
||||
else:
|
||||
# Item both in old and new lists -> Nothing to do in the current list,
|
||||
# remove from the new list so it only holds new items.
|
||||
newTable.del(uid)
|
||||
|
||||
if len(oldIndicesToRemove) > 0:
|
||||
var removedItems = 0
|
||||
for idx in oldIndicesToRemove:
|
||||
let updatedIdx = idx - removedItems
|
||||
self.removeCollectibleItem(updatedIdx)
|
||||
removedItems += 1
|
||||
self.countChanged()
|
||||
|
||||
var newItemsToAdd: seq[CollectiblesEntry] = @[]
|
||||
for uid, idx in newTable:
|
||||
newItemsToAdd.add(newItems[idx])
|
||||
self.appendCollectibleItems(newItemsToAdd)
|
||||
|
||||
proc getItems*(self: Model): seq[CollectiblesEntry] =
|
||||
return self.items
|
||||
|
@ -268,16 +309,24 @@ QtObject:
|
|||
|
||||
proc setItems*(self: Model, newItems: seq[CollectiblesEntry], offset: int, hasMore: bool) =
|
||||
if offset == 0:
|
||||
self.removeCollectibleItems()
|
||||
self.resetCollectibleItems(newItems)
|
||||
elif offset != self.getCount():
|
||||
error "invalid offset"
|
||||
return
|
||||
|
||||
self.appendCollectibleItems(newItems)
|
||||
else:
|
||||
self.appendCollectibleItems(newItems)
|
||||
self.setHasMore(hasMore)
|
||||
|
||||
proc itemsUpdated(self: Model) {.signal.}
|
||||
proc updateItems*(self: Model, updates: seq[backend_collectibles.Collectible]) =
|
||||
# Checks the diff between the current list and the new list, appends new items,
|
||||
# removes missing items.
|
||||
# We assume the order of the items in the input could change, and we don't care
|
||||
# about the order of the items in the model.
|
||||
proc updateItems*(self: Model, newItems: seq[CollectiblesEntry]) =
|
||||
self.updateCollectibleItems(newItems)
|
||||
self.setHasMore(false)
|
||||
|
||||
proc itemsDataUpdated(self: Model) {.signal.}
|
||||
proc updateItemsData*(self: Model, updates: seq[backend_collectibles.Collectible]) =
|
||||
var anyUpdated = false
|
||||
for i in countdown(self.items.high, 0):
|
||||
let entry = self.items[i]
|
||||
|
@ -290,7 +339,7 @@ QtObject:
|
|||
anyUpdated = true
|
||||
break
|
||||
if anyUpdated:
|
||||
self.itemsUpdated()
|
||||
self.itemsDataUpdated()
|
||||
|
||||
proc getImageUrl*(self: Model, id: string): string {.slot.} =
|
||||
for item in self.items:
|
||||
|
|
|
@ -38,7 +38,7 @@ QtObject:
|
|||
result.setup
|
||||
|
||||
signalConnect(result.flatModel, "countChanged()", result, "refreshItems()")
|
||||
signalConnect(result.flatModel, "itemsUpdated()", result, "refreshItems()")
|
||||
signalConnect(result.flatModel, "itemsDataUpdated()", result, "refreshItems()")
|
||||
|
||||
# Forward declaration
|
||||
proc refreshItems*(self: Model)
|
||||
|
|
|
@ -181,7 +181,7 @@ QtObject:
|
|||
self.setTempItems(items, res.offset)
|
||||
# If we reached the end of the list, commit the items to the model
|
||||
if not res.hasMore:
|
||||
self.model.setItems(self.tempItems, 0, false)
|
||||
self.model.updateItems(self.tempItems)
|
||||
self.tempItems = @[]
|
||||
except Exception as e:
|
||||
error "Error converting activity entries: ", e.msg
|
||||
|
@ -207,7 +207,7 @@ QtObject:
|
|||
for jsonCollectible in jsonObj.getElems():
|
||||
let collectible = fromJson(jsonCollectible, backend_collectibles.Collectible)
|
||||
collectibles.add(collectible)
|
||||
self.model.updateItems(collectibles)
|
||||
self.model.updateItemsData(collectibles)
|
||||
if not self.loadType.isPaginated():
|
||||
self.updateTempItems(collectibles)
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
import unittest
|
||||
|
||||
import stint, strutils, random
|
||||
|
||||
import backend/collectibles_types
|
||||
import app/modules/shared_models/collectibles_model
|
||||
import app/modules/shared_models/collectibles_entry
|
||||
|
||||
proc createTestCollectible(seed: int): CollectiblesEntry =
|
||||
let data = Collectible(
|
||||
dataType: UniqueID,
|
||||
id: CollectibleUniqueID(
|
||||
contractID: ContractID(
|
||||
address: seed.toHex,
|
||||
chainID: seed mod 4
|
||||
),
|
||||
tokenID: u256(seed)
|
||||
)
|
||||
)
|
||||
let extradata = ExtraData(
|
||||
networkShortName: "Chain" & seed.toHex,
|
||||
networkColor: "Color" & seed.toHex,
|
||||
networkIconURL: "URL" & seed.toHex,
|
||||
)
|
||||
return newCollectibleDetailsFullEntry(data, extradata)
|
||||
|
||||
proc createTestCollectibles(seed: int, count: int): seq[CollectiblesEntry] =
|
||||
result = @[]
|
||||
for i in 0..<count:
|
||||
result.add(createTestCollectible(seed + i))
|
||||
|
||||
suite "collectibles model":
|
||||
test "Collectible list set":
|
||||
let collectibles = createTestCollectibles(0, 15)
|
||||
let moreCollectibles = createTestCollectibles(100, 10)
|
||||
let model = newModel()
|
||||
|
||||
model.setItems(collectibles, 0, false)
|
||||
check(model.getItems() == collectibles)
|
||||
|
||||
# Wrong offset, should not change the list
|
||||
model.setItems(collectibles, 20, false)
|
||||
check(model.getItems() == collectibles)
|
||||
|
||||
# Right offset, should append
|
||||
model.setItems(moreCollectibles, 15, false)
|
||||
check(model.getItems() == collectibles & moreCollectibles)
|
||||
|
||||
# 0 offset, should replace
|
||||
model.setItems(moreCollectibles, 0, false)
|
||||
check(model.getItems() == moreCollectibles)
|
||||
|
||||
test "Collectible list update":
|
||||
let oldCollectibles = createTestCollectibles(0, 15)
|
||||
let model = newModel()
|
||||
|
||||
model.updateItems(oldCollectibles)
|
||||
check(model.getItems() == oldCollectibles)
|
||||
|
||||
model.updateItems(oldCollectibles)
|
||||
check(model.getItems() == oldCollectibles)
|
||||
|
||||
var newCollectibles = oldCollectibles
|
||||
newCollectibles.del(0)
|
||||
newCollectibles.del(2)
|
||||
newCollectibles.del(7)
|
||||
for newC in createTestCollectibles(100, 7):
|
||||
newCollectibles.add(newC)
|
||||
|
||||
var r = initRand(678)
|
||||
r.shuffle(newCollectibles)
|
||||
|
||||
model.updateItems(newCollectibles)
|
||||
|
||||
for c in model.getItems():
|
||||
check(c in newCollectibles)
|
||||
|
||||
for c in newCollectibles:
|
||||
check(c in model.getItems())
|
||||
|
||||
model.updateItems(@[])
|
||||
check(model.getItems().len == 0)
|
Loading…
Reference in New Issue