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 ../../../../../../app_service/service/collectible/service as collectible_service
import ../../../../../core/eventemitter
type
Controller* = ref object of RootObj
delegate: io_interface.AccessInterface
events: EventEmitter
collectibleService: collectible_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
events: EventEmitter,
collectibleService: collectible_service.Service
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.collectibleService = collectibleService
proc delete*(self: Controller) =
discard
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] =
return self.collectibleService.getCollectibles(address, collectionSlug)
proc fetch*(self: Controller, address: string, collectionSlug: string) =
self.collectibleService.getCollectiblesAsync(address, collectionSlug)

View File

@ -1,3 +1,4 @@
import ../../../../../../app_service/service/collectible/service as collectible_service
import ./item
type
@ -13,10 +14,13 @@ method load*(self: AccessInterface) {.base.} =
method isLoaded*(self: AccessInterface): bool {.base.} =
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.} =
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")
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 as delegate_interface
import ../../../../../../app_service/service/collectible/service as collectible_service
import ../../../../../core/eventemitter
export io_interface
@ -15,12 +16,12 @@ type
moduleLoaded: bool
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 =
result = Module()
result.delegate = delegate
result.view = newView(result)
result.controller = controller.newController(result, collectibleService)
result.controller = controller.newController(result, events, collectibleService)
result.moduleLoaded = false
method delete*(self: Module) =
@ -43,7 +44,9 @@ method setCurrentAddress*(self: Module, address: string) =
self.currentAddress = address
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(
c.id,
c.name,

View File

@ -31,7 +31,7 @@ proc newModule*(
result.controller = newController(result, walletAccountService)
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.currentCollectibleModule = currentCollectibleModule.newModule(result, collectibleService, result.collectionsModule, result.collectiblesModule)

View File

@ -5,13 +5,38 @@ type
const getCollectionsTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[GetCollectionsTaskArg](argEncoded)
let output = %* {
"chainId": arg.chainId,
"address": arg.address,
"collections": ""
}
try:
let response = backend.getOpenseaCollectionsByOwner(arg.chainId, arg.address)
arg.finish(response.result)
output["collections"] = response.result
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
arg.finish("")
error "error getCollectionsTaskArg: ", errDesription
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
GetCollectionsArgs* = ref object of Args
chainId*: int
address*: string
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:
type
Service* = ref object of QObject
@ -47,37 +59,74 @@ QtObject:
proc init*(self: Service) =
discard
proc getNetwork*(self: Service): NetworkDto =
return self.networkService.getNetworkForCollectibles()
proc onGetCollections*(self: Service, response: string) {.slot.} =
var data = GetCollectionsArgs()
try:
let responseObj = response.parseJson
if (responseObj.kind != JArray):
self.events.emit(GetCollections, GetCollectionsArgs())
return
let collections = map(responseObj.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
self.events.emit(GetCollections, GetCollectionsArgs(collections: collections))
except:
self.events.emit(GetCollections, GetCollectionsArgs())
if (responseObj.kind == JObject):
let chainIdJson = responseObj["chainId"]
let addressJson = responseObj["address"]
let validAccount = (chainIdJson.kind == JInt and
addressJson.kind == JString)
if (validAccount):
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) =
let arg = GetCollectionsTaskArg(
tptr: cast[ByteAddress](getCollectionsTaskArg),
vptr: cast[ByteAddress](self.vptr),
slot: "onGetCollections",
chainId: self.networkService.getNetworkForCollectibles().chainId,
chainId: self.getNetwork().chainId,
address: address,
)
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:
let chainId = self.getNetwork().chainId
let response = backend.getOpenseaAssetsByOwnerAndCollection(chainId, address, collectionSlug, limit)
return map(response.result.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
let responseObj = response.parseJson
if (responseObj.kind == JObject):
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:
let errDesription = e.msg
error "error: ", errDesription
return
error "error onGetCollectibles: ", errDesription
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)