refactor: make loading installed sticker packs asynchronous

This is a continuation of the effort to improve out app's startup time.
With these changes, installed stickers are only loaded when the sticker
popup is opened.

They are also loaded asynchronously to not block the main thread.

Closes #9435
This commit is contained in:
Pascal Precht 2023-02-08 15:05:06 +01:00 committed by Jonathan Rainville
parent 433ea71d62
commit ce33c195cc
7 changed files with 81 additions and 22 deletions

View File

@ -54,9 +54,6 @@ proc delete*(self: Controller) =
proc init*(self: Controller) =
let installedStickers = self.stickerService.getInstalledStickerPacks()
self.delegate.populateInstalledStickerPacks(installedStickers)
self.events.on(SIGNAL_NETWORK_DISCONNECTED) do(e: Args):
self.disconnected = true
self.delegate.clearStickerPacks()
@ -85,6 +82,11 @@ proc init*(self: Controller) =
args.isPending
)
self.events.on(SIGNAL_LOAD_INSTALLED_STICKER_PACKS_DONE) do(e: Args):
let args = StickerPacksArgs(e)
self.delegate.installedStickerPacksLoaded()
self.delegate.populateInstalledStickerPacks(args.packs)
self.events.on(SIGNAL_ALL_STICKER_PACKS_LOADED) do(e: Args):
self.delegate.allPacksLoaded()
@ -122,6 +124,9 @@ proc getRecentStickers*(self: Controller): seq[StickerDto] =
proc loadRecentStickers*(self: Controller) =
self.stickerService.asyncLoadRecentStickers()
proc loadInstalledStickerPacks*(self: Controller) =
self.stickerService.asyncLoadInstalledStickerPacks()
proc estimate*(self: Controller, packId: string, address: string, price: string, uuid: string) =
self.stickerService.estimate(packId, address, price, uuid)

View File

@ -28,7 +28,10 @@ method getRecentStickers*(self: AccessInterface) {.base.} =
method loadRecentStickers*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getInstalledStickerPacks*(self: AccessInterface): Table[string, StickerPackDto] {.base.} =
method getInstalledStickerPacks*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method installedStickerPacksLoaded*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method obtainMarketStickerPacks*(self: AccessInterface) {.base.} =

View File

@ -125,9 +125,6 @@ method onUserAuthenticated*(self: Module, password: string) =
self.view.stickerPacks.updateStickerPackInList(self.tmpBuyStickersTransactionDetails.packId, false, true)
self.view.transactionWasSent($(%*{"success": success, "result": response}))
method getInstalledStickerPacks*(self: Module): Table[string, StickerPackDto] =
self.controller.getInstalledStickerPacks()
method obtainMarketStickerPacks*(self: Module) =
self.controller.obtainMarketStickerPacks()
@ -140,6 +137,9 @@ method installStickerPack*(self: Module, packId: string) =
method onStickerPackInstalled*(self: Module, packId: string) =
self.view.onStickerPackInstalled(packId)
method installedStickerPacksLoaded*(self: Module) =
self.view.setInstalledStickerPacksLoaded(true)
method uninstallStickerPack*(self: Module, packId: string) =
self.controller.uninstallStickerPack(packId)
@ -164,13 +164,10 @@ method addRecentStickerToList*(self: Module, sticker: StickerDto) =
self.view.addRecentStickerToList(initItem(sticker.hash, sticker.packId, sticker.url))
method getRecentStickers*(self: Module) =
let data = self.controller.getRecentStickers()
if data.len > 0:
for sticker in data:
self.addRecentStickerToList(sticker)
return
self.controller.loadRecentStickers()
method getInstalledStickerPacks*(self: Module) =
self.controller.loadInstalledStickerPacks()
method clearStickerPacks*(self: Module) =
self.view.clearStickerPacks()

View File

@ -9,6 +9,7 @@ QtObject:
View* = ref object of QObject
delegate: io_interface.AccessInterface
packsLoaded*: bool
installedStickerPacksLoaded*: bool
packsLoadFailed*: bool
stickerPacks*: StickerPackList
recentStickers*: StickerList
@ -24,6 +25,7 @@ QtObject:
result.delegate = delegate
result.stickerPacks = newStickerPackList(result.delegate)
result.recentStickers = newStickerList(result.delegate)
result.installedStickerPacksLoaded = false
proc load*(self: View, signingPhrase: string, stickersMarketAddress: string) =
self.signingPhrase = signingPhrase
@ -78,6 +80,7 @@ QtObject:
proc populateInstalledStickerPacks*(self: View, installedStickerPacks: seq[PackItem]) =
for stickerPack in installedStickerPacks:
if not self.stickerPacks.hasKey(stickerPack.id):
self.addStickerPackToList(stickerPack, isInstalled = true, isBought = true, isPending = false)
proc getNumInstalledStickerPacks(self: View): int {.slot.} =
@ -98,6 +101,12 @@ QtObject:
proc resetBuyAttempt*(self: View, packId: string) {.slot.} =
self.stickerPacks.updateStickerPackInList(packId, false, false)
proc setInstalledStickerPacksLoaded*(self: View, flag: bool) =
self.installedStickerPacksLoaded = flag
proc getInstalledStickerPacksLoaded*(self: View): bool =
return self.installedStickerPacksloaded
proc uninstall*(self: View, packId: string) {.slot.} =
self.delegate.uninstallStickerPack(packId)
self.delegate.removeRecentStickers(packId)
@ -147,6 +156,10 @@ QtObject:
proc getRecentStickers(self: View) {.slot.} =
self.delegate.getRecentStickers()
proc getInstalledStickerPacks(self: View) {.slot.} =
if not self.installedStickerPacksLoaded:
self.delegate.getInstalledStickerPacks()
proc send*(self: View, channelId: string, hash: string, replyTo: string, pack: string, url: string) {.slot.} =
let sticker = initItem(hash, pack, url)
self.addRecentStickerToList(sticker)

View File

@ -14,12 +14,18 @@ type
chainId*: int
hasKey*: bool
AsyncGetRecentStickersTaskArg* = ref object of QObjectTaskArg
AsyncGetInstalledStickerPacksTaskArg* = ref object of QObjectTaskArg
const asyncGetRecentStickersTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncGetRecentStickersTaskArg](argEncoded)
let response = status_stickers.recent()
arg.finish(response)
const asyncGetInstalledStickerPacksTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncGetInstalledStickerPacksTaskArg](argEncoded)
let response = status_stickers.installed()
arg.finish(response)
proc getMarketStickerPacks*(chainId: int):
tuple[stickers: Table[string, StickerPackDto], error: string] =
result = (initTable[string, StickerPackDto](), "")

View File

@ -53,6 +53,8 @@ type
packId*: string
StickersArgs* = ref object of Args
stickers*: seq[StickerDto]
StickerPacksArgs* = ref object of Args
packs*: Table[string, StickerPackDto]
# Signals which may be emitted by this service:
const SIGNAL_STICKER_PACK_LOADED* = "stickerPackLoaded"
@ -65,6 +67,9 @@ const SIGNAL_STICKER_PACK_INSTALLED* = "stickerPackInstalled"
const SIGNAL_LOAD_RECENT_STICKERS_STARTED* = "loadRecentStickersStarted"
const SIGNAL_LOAD_RECENT_STICKERS_FAILED* = "loadRecentStickersFailed"
const SIGNAL_LOAD_RECENT_STICKERS_DONE* = "loadRecentStickersDone"
const SIGNAL_LOAD_INSTALLED_STICKER_PACKS_STARTED* = "loadInstalledStickerPacksStarted"
const SIGNAL_LOAD_INSTALLED_STICKER_PACKS_FAILED* = "loadInstalledStickerPacksFailed"
const SIGNAL_LOAD_INSTALLED_STICKER_PACKS_DONE* = "loadInstalledStickerPacksDone"
QtObject:
type Service* = ref object of QObject
@ -78,6 +83,7 @@ QtObject:
networkService: network_service.Service
chatService: chat_service.Service
tokenService: token_service.Service
installedStickerPacks: Table[string, StickerPackDto]
# Forward declaration
proc obtainMarketStickerPacks*(self: Service)
@ -107,15 +113,10 @@ QtObject:
result.chatService = chatService
result.marketStickerPacks = initTable[string, StickerPackDto]()
result.recentStickers = @[]
result.installedStickerPacks = initTable[string, StickerPackDto]()
proc getInstalledStickerPacks*(self: Service): Table[string, StickerPackDto] =
result = initTable[string, StickerPackDto]()
try:
let installedResponse = status_stickers.installed()
for (packID, stickerPackJson) in installedResponse.result.pairs():
result[packID] = stickerPackJson.toStickerPackDto()
except RpcException:
error "Error obtaining installed stickers", message = getCurrentExceptionMsg()
return self.installedStickerPacks
proc getStickerMarketAddress*(self: Service): string =
try:
@ -362,6 +363,35 @@ QtObject:
error "error: ", errMsg
self.events.emit(SIGNAL_LOAD_RECENT_STICKERS_FAILED, Args())
proc asyncLoadInstalledStickerPacks*(self: Service) =
self.events.emit(SIGNAL_LOAD_INSTALLED_STICKER_PACKS_STARTED, Args())
try:
let arg = AsyncGetInstalledStickerPacksTaskArg(
tptr: cast[ByteAddress](asyncGetInstalledStickerPacksTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onAsyncGetInstalledStickerPacksDone"
)
self.threadpool.start(arg)
except Exception as e:
error "Error loading installed sticker packs", msg = e.msg
proc onAsyncGetInstalledStickerPacksDone*(self: Service, response: string) {.slot.} =
try:
let rpcResponseObj = response.parseJson
if (rpcResponseObj{"error"}.kind != JNull):
let error = Json.decode($rpcResponseObj["error"], RpcError)
error "error loading installed sticker packs", msg = error.message
return
var stickerPacks: Table[string, StickerPackDto] = initTable[string, StickerPackDto]()
for (packID, stickerPackJson) in rpcResponseObj{"result"}.pairs():
self.installedStickerPacks[packID] = stickerPackJson.toStickerPackDto()
self.events.emit(SIGNAL_LOAD_INSTALLED_STICKER_PACKS_DONE, StickerPacksArgs(packs: self.installedStickerPacks))
except Exception as e:
let errMsg = e.msg
error "error: ", errMsg
self.events.emit(SIGNAL_LOAD_INSTALLED_STICKER_PACKS_FAILED, Args())
proc getNumInstalledStickerPacks*(self: Service): int =
try:
let installedResponse = status_stickers.installed()

View File

@ -38,6 +38,10 @@ Popup {
function getRecentStickers() {
store.stickersModuleInst.getRecentStickers()
}
function getInstalledStickerPacks() {
store.stickersModuleInst.getInstalledStickerPacks()
}
}
enabled: !!d.recentStickers && !!d.stickerPackList
@ -61,6 +65,7 @@ Popup {
}
onAboutToShow: {
d.getInstalledStickerPacks()
if (stickerGrid.packId == -1) {
d.getRecentStickers()
}