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 "communityColor": result = item.getCommunityColor()
|
||||||
of "communityPrivilegesLevel": result = $item.getCommunityPrivilegesLevel()
|
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]) =
|
proc appendCollectibleItems(self: Model, newItems: seq[CollectiblesEntry]) =
|
||||||
if len(newItems) == 0:
|
if len(newItems) == 0:
|
||||||
return
|
return
|
||||||
|
@ -240,23 +246,58 @@ QtObject:
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
self.countChanged()
|
self.countChanged()
|
||||||
|
|
||||||
proc removeCollectibleItems(self: Model) =
|
proc removeCollectibleItem(self: Model, idx: int) =
|
||||||
if self.items.len <= 0:
|
if idx < 0 or idx >= self.items.len:
|
||||||
return
|
return
|
||||||
|
|
||||||
let parentModelIndex = newQModelIndex()
|
let parentModelIndex = newQModelIndex()
|
||||||
defer: parentModelIndex.delete
|
defer: parentModelIndex.delete
|
||||||
|
|
||||||
# Start from the beginning
|
self.beginRemoveRows(parentModelIndex, idx, idx)
|
||||||
let startIdx = 0
|
self.items.delete(idx)
|
||||||
# End at the last real item
|
|
||||||
let endIdx = startIdx + self.items.len - 1
|
|
||||||
|
|
||||||
self.beginRemoveRows(parentModelIndex, startIdx, endIdx)
|
|
||||||
self.items = @[]
|
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
self.countChanged()
|
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] =
|
proc getItems*(self: Model): seq[CollectiblesEntry] =
|
||||||
return self.items
|
return self.items
|
||||||
|
|
||||||
|
@ -268,16 +309,24 @@ QtObject:
|
||||||
|
|
||||||
proc setItems*(self: Model, newItems: seq[CollectiblesEntry], offset: int, hasMore: bool) =
|
proc setItems*(self: Model, newItems: seq[CollectiblesEntry], offset: int, hasMore: bool) =
|
||||||
if offset == 0:
|
if offset == 0:
|
||||||
self.removeCollectibleItems()
|
self.resetCollectibleItems(newItems)
|
||||||
elif offset != self.getCount():
|
elif offset != self.getCount():
|
||||||
error "invalid offset"
|
error "invalid offset"
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
self.appendCollectibleItems(newItems)
|
self.appendCollectibleItems(newItems)
|
||||||
self.setHasMore(hasMore)
|
self.setHasMore(hasMore)
|
||||||
|
|
||||||
proc itemsUpdated(self: Model) {.signal.}
|
# Checks the diff between the current list and the new list, appends new items,
|
||||||
proc updateItems*(self: Model, updates: seq[backend_collectibles.Collectible]) =
|
# 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
|
var anyUpdated = false
|
||||||
for i in countdown(self.items.high, 0):
|
for i in countdown(self.items.high, 0):
|
||||||
let entry = self.items[i]
|
let entry = self.items[i]
|
||||||
|
@ -290,7 +339,7 @@ QtObject:
|
||||||
anyUpdated = true
|
anyUpdated = true
|
||||||
break
|
break
|
||||||
if anyUpdated:
|
if anyUpdated:
|
||||||
self.itemsUpdated()
|
self.itemsDataUpdated()
|
||||||
|
|
||||||
proc getImageUrl*(self: Model, id: string): string {.slot.} =
|
proc getImageUrl*(self: Model, id: string): string {.slot.} =
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
|
|
|
@ -38,7 +38,7 @@ QtObject:
|
||||||
result.setup
|
result.setup
|
||||||
|
|
||||||
signalConnect(result.flatModel, "countChanged()", result, "refreshItems()")
|
signalConnect(result.flatModel, "countChanged()", result, "refreshItems()")
|
||||||
signalConnect(result.flatModel, "itemsUpdated()", result, "refreshItems()")
|
signalConnect(result.flatModel, "itemsDataUpdated()", result, "refreshItems()")
|
||||||
|
|
||||||
# Forward declaration
|
# Forward declaration
|
||||||
proc refreshItems*(self: Model)
|
proc refreshItems*(self: Model)
|
||||||
|
|
|
@ -181,7 +181,7 @@ QtObject:
|
||||||
self.setTempItems(items, res.offset)
|
self.setTempItems(items, res.offset)
|
||||||
# If we reached the end of the list, commit the items to the model
|
# If we reached the end of the list, commit the items to the model
|
||||||
if not res.hasMore:
|
if not res.hasMore:
|
||||||
self.model.setItems(self.tempItems, 0, false)
|
self.model.updateItems(self.tempItems)
|
||||||
self.tempItems = @[]
|
self.tempItems = @[]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error converting activity entries: ", e.msg
|
error "Error converting activity entries: ", e.msg
|
||||||
|
@ -207,7 +207,7 @@ QtObject:
|
||||||
for jsonCollectible in jsonObj.getElems():
|
for jsonCollectible in jsonObj.getElems():
|
||||||
let collectible = fromJson(jsonCollectible, backend_collectibles.Collectible)
|
let collectible = fromJson(jsonCollectible, backend_collectibles.Collectible)
|
||||||
collectibles.add(collectible)
|
collectibles.add(collectible)
|
||||||
self.model.updateItems(collectibles)
|
self.model.updateItemsData(collectibles)
|
||||||
if not self.loadType.isPaginated():
|
if not self.loadType.isPaginated():
|
||||||
self.updateTempItems(collectibles)
|
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