fix(@desktop/wallet) make collection expansion more responsive

Collection fetch is now non-blocking

Fixes #8406
This commit is contained in:
Dario Gabriel Lipicar 2022-11-29 15:33:35 -03:00 committed by dlipicar
parent 473da3790b
commit f0744ed61d
6 changed files with 118 additions and 31 deletions

View File

@ -1,25 +1,31 @@
import io_interface import io_interface
import ../../../../../../app_service/service/collectible/service as collectible_service import ../../../../../../app_service/service/collectible/service as collectible_service
import ../../../../../core/eventemitter
type type
Controller* = ref object of RootObj Controller* = ref object of RootObj
delegate: io_interface.AccessInterface delegate: io_interface.AccessInterface
events: EventEmitter
collectibleService: collectible_service.Service collectibleService: collectible_service.Service
proc newController*( proc newController*(
delegate: io_interface.AccessInterface, delegate: io_interface.AccessInterface,
events: EventEmitter,
collectibleService: collectible_service.Service collectibleService: collectible_service.Service
): Controller = ): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate
result.events = events
result.collectibleService = collectibleService result.collectibleService = collectibleService
proc delete*(self: Controller) = proc delete*(self: Controller) =
discard discard
proc init*(self: Controller) = proc init*(self: Controller) =
discard self.events.on(GetCollectibles) do(e:Args):
let args = GetCollectiblesArgs(e)
self.delegate.setCollectibles(args.collectionSlug, args.collectibles)
proc fetch*(self: Controller, address: string, collectionSlug: string): seq[collectible_service.CollectibleDto] = proc fetch*(self: Controller, address: string, collectionSlug: string) =
return self.collectibleService.getCollectibles(address, collectionSlug) self.collectibleService.getCollectiblesAsync(address, collectionSlug)

View File

@ -1,3 +1,4 @@
import ../../../../../../app_service/service/collectible/service as collectible_service
import ./item import ./item
type type
@ -13,10 +14,13 @@ method load*(self: AccessInterface) {.base.} =
method isLoaded*(self: AccessInterface): bool {.base.} = method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method setCurrentAddress*(self: AccessInterface, address: string) {.base.} =
raise newException(ValueError, "No implementation available")
method fetch*(self: AccessInterface, collectionSlug: string) {.base.} = method fetch*(self: AccessInterface, collectionSlug: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method setCurrentAddress*(self: AccessInterface, address: string) {.base.} = method setCollectibles*(self: AccessInterface, collectionSlug: string, collectibles: seq[CollectibleDto]) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getCollectible*(self: AccessInterface, collectionSlug: string, id: int) : Item {.base.} = method getCollectible*(self: AccessInterface, collectionSlug: string, id: int) : Item {.base.} =

View File

@ -4,6 +4,7 @@ import ../../../../../global/global_singleton
import ./io_interface, ./view, ./controller, ./item import ./io_interface, ./view, ./controller, ./item
import ../io_interface as delegate_interface import ../io_interface as delegate_interface
import ../../../../../../app_service/service/collectible/service as collectible_service import ../../../../../../app_service/service/collectible/service as collectible_service
import ../../../../../core/eventemitter
export io_interface export io_interface
@ -15,12 +16,12 @@ type
moduleLoaded: bool moduleLoaded: bool
currentAddress: string currentAddress: string
proc newModule*(delegate: delegate_interface.AccessInterface, collectibleService: collectible_service.Service): proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, collectibleService: collectible_service.Service):
Module = Module =
result = Module() result = Module()
result.delegate = delegate result.delegate = delegate
result.view = newView(result) result.view = newView(result)
result.controller = controller.newController(result, collectibleService) result.controller = controller.newController(result, events, collectibleService)
result.moduleLoaded = false result.moduleLoaded = false
method delete*(self: Module) = method delete*(self: Module) =
@ -43,7 +44,9 @@ method setCurrentAddress*(self: Module, address: string) =
self.currentAddress = address self.currentAddress = address
method fetch*(self: Module, collectionSlug: string) = method fetch*(self: Module, collectionSlug: string) =
let collectibles = self.controller.fetch(self.currentAddress, collectionSlug) self.controller.fetch(self.currentAddress, collectionSlug)
method setCollectibles*(self: Module, collectionSlug: string, collectibles: seq[CollectibleDto]) =
let items = collectibles.map(c => initItem( let items = collectibles.map(c => initItem(
c.id, c.id,
c.name, c.name,

View File

@ -31,7 +31,7 @@ proc newModule*(
result.controller = newController(result, walletAccountService) result.controller = newController(result, walletAccountService)
result.moduleLoaded = false result.moduleLoaded = false
result.collectiblesModule = collectibles_module.newModule(result, collectibleService) result.collectiblesModule = collectibles_module.newModule(result, events, collectibleService)
result.collectionsModule = collectionsModule.newModule(result, events, collectibleService) result.collectionsModule = collectionsModule.newModule(result, events, collectibleService)
result.currentCollectibleModule = currentCollectibleModule.newModule(result, collectibleService, result.collectionsModule, result.collectiblesModule) result.currentCollectibleModule = currentCollectibleModule.newModule(result, collectibleService, result.collectionsModule, result.collectiblesModule)

View File

@ -5,13 +5,38 @@ type
const getCollectionsTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = const getCollectionsTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[GetCollectionsTaskArg](argEncoded) let arg = decode[GetCollectionsTaskArg](argEncoded)
let output = %* {
"chainId": arg.chainId,
"address": arg.address,
"collections": ""
}
try: try:
let response = backend.getOpenseaCollectionsByOwner(arg.chainId, arg.address) let response = backend.getOpenseaCollectionsByOwner(arg.chainId, arg.address)
arg.finish(response.result) output["collections"] = response.result
except Exception as e: except Exception as e:
let errDesription = e.msg let errDesription = e.msg
error "error: ", errDesription error "error getCollectionsTaskArg: ", errDesription
arg.finish("") arg.finish(output)
type
GetCollectiblesTaskArg = ref object of QObjectTaskArg
chainId*: int
address*: string
collectionSlug: string
limit: int
const getCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[GetCollectiblesTaskArg](argEncoded)
let output = %* {
"chainId": arg.chainId,
"address": arg.address,
"collectionSlug": arg.collectionSlug,
"collectibles": ""
}
try:
let response = backend.getOpenseaAssetsByOwnerAndCollection(arg.chainId, arg.address, arg.collectionSlug, arg.limit)
output["collectibles"] = response.result
except Exception as e:
let errDesription = e.msg
error "error getCollectiblesTaskArg: ", errDesription
arg.finish(output)

View File

@ -21,8 +21,20 @@ const GetCollections* = "get-collections"
type type
GetCollectionsArgs* = ref object of Args GetCollectionsArgs* = ref object of Args
chainId*: int
address*: string
collections*: seq[CollectionDto] collections*: seq[CollectionDto]
const GetCollectibles* = "get-collectibles"
type
GetCollectiblesArgs* = ref object of Args
chainId*: int
address*: string
collectionSlug*: string
collectibles*: seq[CollectibleDto]
error*: string
QtObject: QtObject:
type type
Service* = ref object of QObject Service* = ref object of QObject
@ -47,37 +59,74 @@ QtObject:
proc init*(self: Service) = proc init*(self: Service) =
discard discard
proc getNetwork*(self: Service): NetworkDto =
return self.networkService.getNetworkForCollectibles()
proc onGetCollections*(self: Service, response: string) {.slot.} = proc onGetCollections*(self: Service, response: string) {.slot.} =
var data = GetCollectionsArgs()
try: try:
let responseObj = response.parseJson let responseObj = response.parseJson
if (responseObj.kind != JArray): if (responseObj.kind == JObject):
self.events.emit(GetCollections, GetCollectionsArgs()) let chainIdJson = responseObj["chainId"]
return let addressJson = responseObj["address"]
let collections = map(responseObj.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto()) let validAccount = (chainIdJson.kind == JInt and
self.events.emit(GetCollections, GetCollectionsArgs(collections: collections)) addressJson.kind == JString)
except: if (validAccount):
self.events.emit(GetCollections, GetCollectionsArgs()) data.chainId = chainIdJson.getInt()
data.address = addressJson.getStr()
let collectionsJson = responseObj["collections"]
if (collectionsJson.kind == JArray):
data.collections = map(collectionsJson.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
except Exception as e:
let errDesription = e.msg
error "error onGetCollections: ", errDesription
self.events.emit(GetCollections, data)
proc getCollectionsAsync*(self: Service, address: string) = proc getCollectionsAsync*(self: Service, address: string) =
let arg = GetCollectionsTaskArg( let arg = GetCollectionsTaskArg(
tptr: cast[ByteAddress](getCollectionsTaskArg), tptr: cast[ByteAddress](getCollectionsTaskArg),
vptr: cast[ByteAddress](self.vptr), vptr: cast[ByteAddress](self.vptr),
slot: "onGetCollections", slot: "onGetCollections",
chainId: self.networkService.getNetworkForCollectibles().chainId, chainId: self.getNetwork().chainId,
address: address, address: address,
) )
self.threadpool.start(arg) self.threadpool.start(arg)
proc getNetwork*(self: Service): NetworkDto =
return self.networkService.getNetworkForCollectibles()
proc getCollectibles*(self: Service, address: string, collectionSlug: string): seq[CollectibleDto] = proc onGetCollectibles*(self: Service, response: string) {.slot.} =
var data = GetCollectiblesArgs()
try: try:
let chainId = self.getNetwork().chainId let responseObj = response.parseJson
let response = backend.getOpenseaAssetsByOwnerAndCollection(chainId, address, collectionSlug, limit) if (responseObj.kind == JObject):
return map(response.result.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto()) let chainIdJson = responseObj["chainId"]
let addressJson = responseObj["address"]
let collectionSlugJson = responseObj["collectionSlug"]
let validCollection = (chainIdJson.kind == JInt and
addressJson.kind == JString and
collectionSlugJson.kind == JString)
if (validCollection):
data.chainId = chainIdJson.getInt()
data.address = addressJson.getStr()
data.collectionSlug = collectionSlugJson.getStr()
let collectiblesJson = responseObj["collectibles"]
if (collectiblesJson.kind == JArray):
data.collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
except Exception as e: except Exception as e:
let errDesription = e.msg let errDesription = e.msg
error "error: ", errDesription error "error onGetCollectibles: ", errDesription
return self.events.emit(GetCollectibles, data)
proc getCollectiblesAsync*(self: Service, address: string, collectionSlug: string) =
let arg = GetCollectiblesTaskArg(
tptr: cast[ByteAddress](getCollectiblesTaskArg),
vptr: cast[ByteAddress](self.vptr),
slot: "onGetCollectibles",
chainId: self.getNetwork().chainId,
address: address,
collectionSlug: collectionSlug,
limit: limit
)
self.threadpool.start(arg)