diff --git a/src/app/modules/main/profile_section/wallet/accounts/module.nim b/src/app/modules/main/profile_section/wallet/accounts/module.nim index 1c32a805c7..be0b64a1cd 100644 --- a/src/app/modules/main/profile_section/wallet/accounts/module.nim +++ b/src/app/modules/main/profile_section/wallet/accounts/module.nim @@ -45,7 +45,7 @@ proc newModule*( result.controller = accountsc.newController(result, walletAccountService) result.collectiblesController = collectiblesc.newController( requestId = int32(backend_collectibles.CollectiblesRequestID.ProfileShowcase), - autofetch = false, + loadType = collectiblesc.LoadType.AutoLoadSingleUpdate, networkService = networkService, events = events ) diff --git a/src/app/modules/main/wallet_section/module.nim b/src/app/modules/main/wallet_section/module.nim index 1153d85ca4..f0aff44ee3 100644 --- a/src/app/modules/main/wallet_section/module.nim +++ b/src/app/modules/main/wallet_section/module.nim @@ -130,7 +130,7 @@ proc newModule*( result.transactionService = transactionService let collectiblesController = collectiblesc.newController( requestId = int32(backend_collectibles.CollectiblesRequestID.WalletAccount), - autofetch = false, + loadType = collectiblesc.LoadType.OnDemand, networkService = networkService, events = events ) diff --git a/src/app/modules/main/wallet_section/send/module.nim b/src/app/modules/main/wallet_section/send/module.nim index 9f0a87666e..b2d3be39f1 100644 --- a/src/app/modules/main/wallet_section/send/module.nim +++ b/src/app/modules/main/wallet_section/send/module.nim @@ -76,7 +76,7 @@ proc newModule*( transactionService, keycardService) result.collectiblesController = collectiblesc.newController( requestId = int32(backend_collectibles.CollectiblesRequestID.WalletSend), - autofetch = true, + loadType = collectiblesc.LoadType.AutoLoadSingleUpdate, networkService = networkService, events = events ) diff --git a/src/app/modules/shared_models/collectibles_entry.nim b/src/app/modules/shared_models/collectibles_entry.nim index c8818178f5..6cfbf67877 100644 --- a/src/app/modules/shared_models/collectibles_entry.nim +++ b/src/app/modules/shared_models/collectibles_entry.nim @@ -338,9 +338,9 @@ QtObject: QtProperty[string] networkIconUrl: read = getNetworkIconURL - proc updateData*(self: CollectiblesEntry, update: backend.Collectible) = + proc updateDataIfSameID*(self: CollectiblesEntry, update: backend.Collectible): bool = if self.id != update.id: - return + return false self.setData(update) @@ -361,4 +361,5 @@ QtObject: self.communityNameChanged() self.communityColorChanged() self.communityPrivilegesLevelChanged() - self.communityImageChanged() \ No newline at end of file + self.communityImageChanged() + return true \ No newline at end of file diff --git a/src/app/modules/shared_models/collectibles_model.nim b/src/app/modules/shared_models/collectibles_model.nim index 643778d236..3964e9eda7 100644 --- a/src/app/modules/shared_models/collectibles_model.nim +++ b/src/app/modules/shared_models/collectibles_model.nim @@ -350,8 +350,7 @@ QtObject: let entry = self.items[i] for j in countdown(updates.high, 0): let update = updates[j] - if entry.getCollectibleUniqueID() == update.id: - entry.updateData(update) + if entry.updateDataIfSameID(update): let index = self.createIndex(i, 0, nil) defer: index.delete self.dataChanged(index, index) diff --git a/src/app/modules/shared_modules/collectible_details/controller.nim b/src/app/modules/shared_modules/collectible_details/controller.nim index b06c6685db..cb569d5c25 100644 --- a/src/app/modules/shared_modules/collectible_details/controller.nim +++ b/src/app/modules/shared_modules/collectible_details/controller.nim @@ -82,7 +82,8 @@ QtObject: for jsonCollectible in jsonObj.getElems(): let collectible = fromJson(jsonCollectible, backend_collectibles.Collectible) - self.detailedEntry.updateData(collectible) # Will only update if UniqueID matches + if self.detailedEntry.updateDataIfSameID(collectible): + break proc getDetailedCollectible*(self: Controller, chainId: int, contractAddress: string, tokenId: string) {.slot.} = self.setIsDetailedEntryLoading(true) diff --git a/src/app/modules/shared_modules/collectibles/controller.nim b/src/app/modules/shared_modules/collectibles/controller.nim index 54cbd1c7b8..0a3060e62a 100644 --- a/src/app/modules/shared_modules/collectibles/controller.nim +++ b/src/app/modules/shared_modules/collectibles/controller.nim @@ -14,6 +14,18 @@ import app_service/service/network/service as network_service const FETCH_BATCH_COUNT_DEFAULT = 50 +type + LoadType* {.pure.} = enum + AutoLoadSingleUpdate, # load all items and update the model once with full list + AutoLoadPaginated, # load items in batches (keep loading until the end of the list) and update the model appending each batch. + OnDemand # load items in batches (on demand when loadMoreItems is called) and update the model appending each batch. + +proc isAutoLoad(self: LoadType): bool = + return self == LoadType.AutoLoadSingleUpdate or self == LoadType.AutoLoadPaginated + +proc isPaginated(self: LoadType): bool = + return self == LoadType.AutoLoadPaginated or self == LoadType.OnDemand + QtObject: type Controller* = ref object of QObject @@ -21,6 +33,7 @@ QtObject: model: Model fetchFromStart: bool + tempItems: seq[CollectiblesEntry] eventsHandler: EventsHandler @@ -31,7 +44,7 @@ QtObject: ownershipStatus: Table[string, Table[int, OwnershipStatus]] # Table[address][chainID] -> OwnershipStatus requestId: int32 - autofetch: bool + loadType: LoadType dataType: backend_collectibles.CollectibleDataType fetchCriteria: backend_collectibles.FetchCriteria @@ -116,7 +129,10 @@ QtObject: var offset = 0 if not self.fetchFromStart: - offset = self.model.getCollectiblesCount() + if self.loadType.isPaginated(): + offset = self.model.getCollectiblesCount() + else: + offset = self.tempItems.len self.fetchFromStart = false let response = backend_collectibles.getOwnedCollectiblesAsync(self.requestId, self.chainIds, self.addresses, self.filter, offset, FETCH_BATCH_COUNT_DEFAULT, self.dataType, self.fetchCriteria) @@ -130,9 +146,15 @@ QtObject: let network = self.networkService.getNetwork(chainID) return getExtraData(network) - proc processGetOwnedCollectiblesResponse(self: Controller, response: JsonNode) = - self.model.setIsFetching(false) + proc setTempItems(self: Controller, newItems: seq[CollectiblesEntry], offset: int) = + if offset == 0: + self.tempItems = @[] + elif offset != self.tempItems.len: + error "invalid offset" + return + self.tempItems.add(newItems) + proc processGetOwnedCollectiblesResponse(self: Controller, response: JsonNode) = let res = fromJson(response, backend_collectibles.GetOwnedCollectiblesResponse) let isError = res.errorCode != backend_collectibles.ErrorCodeSuccess @@ -140,6 +162,7 @@ QtObject: if isError: error "error fetching collectibles entries: ", res.errorCode self.model.setIsError(true) + self.model.setIsFetching(false) return try: @@ -147,15 +170,30 @@ QtObject: let extradata = self.getExtraData(header.id.contractID.chainID) newCollectibleDetailsFullEntry(header, extradata) )) - self.model.setItems(items, res.offset, res.hasMore) + if self.loadType.isPaginated(): + self.model.setItems(items, res.offset, res.hasMore) + else: + 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.tempItems = @[] except Exception as e: error "Error converting activity entries: ", e.msg + self.model.setIsFetching(false) self.setOwnershipStatus(res.ownershipStatus) - if self.autofetch and res.hasMore: + if self.loadType.isAutoLoad() and res.hasMore: self.loadMoreItems() + proc updateTempItems(self: Controller, updates: seq[backend_collectibles.Collectible]) = + for i in countdown(self.tempItems.high, 0): + let entry = self.tempItems[i] + for j in countdown(updates.high, 0): + if entry.updateDataIfSameID(updates[j]): + break + proc processCollectiblesDataUpdate(self: Controller, jsonObj: JsonNode) = if jsonObj.kind != JArray: error "processCollectiblesDataUpdate expected an array" @@ -165,12 +203,15 @@ QtObject: let collectible = fromJson(jsonCollectible, backend_collectibles.Collectible) collectibles.add(collectible) self.model.updateItems(collectibles) + if not self.loadType.isPaginated(): + self.updateTempItems(collectibles) proc resetModel(self: Controller) {.slot.} = + self.tempItems = @[] self.model.setItems(@[], 0, true) self.fetchFromStart = true - if self.autofetch: - self.loadMoreItems() + if self.loadType.isAutoLoad(): + self.loadMoreItems() proc setupEventHandlers(self: Controller) = self.eventsHandler.onOwnedCollectiblesFilteringDone(proc (jsonObj: JsonNode) = @@ -205,7 +246,7 @@ QtObject: requestId: int32, networkService: network_service.Service, events: EventEmitter, - autofetch: bool = true, + loadType: LoadType, dataType: backend_collectibles.CollectibleDataType = backend_collectibles.CollectibleDataType.Header, fetchCriteria: backend_collectibles.FetchCriteria = backend_collectibles.FetchCriteria( fetchType: backend_collectibles.FetchType.NeverFetch, @@ -213,7 +254,7 @@ QtObject: new(result, delete) result.requestId = requestId - result.autofetch = autofetch + result.loadType = loadType result.dataType = dataType result.fetchCriteria = fetchCriteria