fix(@desktop/chat): Improve installing stickers code to handle disconnected state better

Use async task to install stickers

Issue #6567
This commit is contained in:
Michal Iskierko 2022-12-30 21:26:46 +01:00 committed by Michał Iskierko
parent ac56bbdfdd
commit 0cd2419f59
8 changed files with 85 additions and 8 deletions

View File

@ -107,6 +107,10 @@ proc init*(self: Controller) =
return
self.delegate.onUserAuthenticated(args.password)
self.events.on(SIGNAL_STICKER_PACK_INSTALLED) do(e: Args):
let args = StickerPackInstalledArgs(e)
self.delegate.onStickerPackInstalled(args.packId)
proc buy*(self: Controller, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): tuple[response: string, success: bool] =
self.stickerService.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)

View File

@ -49,6 +49,9 @@ method estimate*(self: AccessInterface, packId: string, address: string, price:
method installStickerPack*(self: AccessInterface, packId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onStickerPackInstalled*(self: AccessInterface, packId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method uninstallStickerPack*(self: AccessInterface, packId: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -26,6 +26,7 @@ QtObject:
delegate: io_interface.AccessInterface
packs*: seq[StickerPackView]
packIdToRetrieve*: int
foundStickers*: QVariant
proc setup(self: StickerPackList) = self.QAbstractListModel.setup
@ -123,6 +124,18 @@ QtObject:
let packInfo = self.packs[self.packIdToRetrieve]
result = newQVariant(packInfo.stickers)
# We cannot return QVariant from the proc which has arguments.
# First findStickersById has to be called, then getFoundStickers
proc findStickersById*(self: StickerPackList, packId: string) {.slot.} =
self.foundStickers = newQVariant()
for item in self.packs:
if(item.pack.id == packId):
self.foundStickers = newQVariant(item.stickers)
break
proc getFoundStickers*(self: StickerPackList): QVariant {.slot.} =
return self.foundStickers
proc rowData*(self: StickerPackList, row: int, data: string): string {.slot.} =
if row < 0 or (row > self.packs.len - 1):
return

View File

@ -137,6 +137,9 @@ method getNumInstalledStickerPacks*(self: Module): int =
method installStickerPack*(self: Module, packId: string) =
self.controller.installStickerPack(packId)
method onStickerPackInstalled*(self: Module, packId: string) =
self.view.onStickerPackInstalled(packId)
method uninstallStickerPack*(self: Module, packId: string) =
self.controller.uninstallStickerPack(packId)

View File

@ -67,6 +67,8 @@ QtObject:
proc stickerPacksLoaded*(self: View) {.signal.}
proc stickerPackInstalled*(self: View, packId: string) {.signal.}
proc packsLoadFailedChanged*(self: View) {.signal.}
proc installedStickerPacksUpdated*(self: View) {.signal.}
@ -87,8 +89,11 @@ QtObject:
proc install*(self: View, packId: string) {.slot.} =
self.delegate.installStickerPack(packId)
proc onStickerPackInstalled*(self:View, packId: string) =
self.stickerPacks.updateStickerPackInList(packId, true, false)
self.installedStickerPacksUpdated()
self.stickerPackInstalled(packId)
proc resetBuyAttempt*(self: View, packId: string) {.slot.} =
self.stickerPacks.updateStickerPackInList(packId, false, false)

View File

@ -10,6 +10,10 @@ type
ObtainMarketStickerPacksTaskArg = ref object of QObjectTaskArg
chainId*: int
running*: ByteAddress # pointer to threadpool's `.running` Atomic[bool]
InstallStickerPackTaskArg = ref object of QObjectTaskArg
packId*: string
chainId*: int
hasKey*: bool
proc getMarketStickerPacks*(running: var Atomic[bool], chainId: int):
tuple[stickers: Table[string, StickerPackDto], error: string] =
@ -51,3 +55,21 @@ const obtainMarketStickerPacksTask: Task = proc(argEncoded: string) {.gcsafe, ni
packs.add(stickerPack)
let tpl: tuple[packs: seq[StickerPackDto], error: string] = (packs, error)
arg.finish(tpl)
const installStickerPackTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[InstallStickerPackTaskArg](argEncoded)
if not arg.hasKey:
arg.finish(false)
return
var installed = false
try:
let installResponse = status_stickers.install(arg.chainId, arg.packId)
if installResponse.error == nil:
installed = true
else:
let err = Json.decode($installResponse.error, RpcError)
error "Error installing stickers", message = err.message
except RpcException:
error "Error installing stickers", message = getCurrentExceptionMsg()
let tpl: tuple[packId: string, installed: bool] = (arg.packId, installed)
arg.finish(tpl)

View File

@ -50,6 +50,8 @@ type
packID*: string
transactionType*: string
revertReason*: string
StickerPackInstalledArgs* = ref object of Args
packId*: string
# Signals which may be emitted by this service:
const SIGNAL_STICKER_PACK_LOADED* = "stickerPackLoaded"
@ -58,6 +60,7 @@ const SIGNAL_ALL_STICKER_PACKS_LOAD_FAILED* = "allStickerPacksLoadFailed"
const SIGNAL_STICKER_GAS_ESTIMATED* = "stickerGasEstimated"
const SIGNAL_STICKER_TRANSACTION_CONFIRMED* = "stickerTransactionConfirmed"
const SIGNAL_STICKER_TRANSACTION_REVERTED* = "stickerTransactionReverted"
const SIGNAL_STICKER_PACK_INSTALLED* = "stickerPackInstalled"
QtObject:
type Service* = ref object of QObject
@ -329,21 +332,33 @@ QtObject:
for stickerJson in recentResponse.result:
result = stickerJson.toStickerDto() & result
except RpcException:
error "Error obtaining installed stickers", message = getCurrentExceptionMsg()
error "Error getting recent stickers", message = getCurrentExceptionMsg()
proc getNumInstalledStickerPacks*(self: Service): int =
try:
let installedResponse = status_stickers.installed()
return installedResponse.result.len
except RpcException:
error "Error obtaining installed stickers", message = getCurrentExceptionMsg()
error "Error getting installed stickers number", message = getCurrentExceptionMsg()
return 0
proc installStickerPack*(self: Service, packId: string) =
let chainId = self.networkService.getNetworkForStickers().chainId
if not self.marketStickerPacks.hasKey(packId):
return
let installResponse = status_stickers.install(chainId, packId)
let arg = InstallStickerPackTaskArg(
tptr: cast[ByteAddress](installStickerPackTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onStickerPackInstalled",
chainId: self.networkService.getNetworkForStickers().chainId,
packId: packId,
hasKey: self.marketStickerPacks.hasKey(packId)
)
self.threadpool.start(arg)
proc onStickerPackInstalled*(self: Service, installedPackJson: string) {.slot.} =
let installedPack = Json.decode(installedPackJson, tuple[packId: string, installed: bool])
if installedPack.installed:
self.events.emit(SIGNAL_STICKER_PACK_INSTALLED, StickerPackInstalledArgs(
packId: installedPack.packId
))
proc uninstallStickerPack*(self: Service, packId: string) =
try:

View File

@ -82,9 +82,8 @@ Popup {
stickerPacks: d.stickerPackList
packId: stickerPackListView.selectedPackId
onInstallClicked: {
//starts async task
stickersModule.install(packId)
stickerGrid.model = stickers
stickerPackListView.itemAt(index).clicked()
}
onUninstallClicked: {
stickersModule.uninstall(packId)
@ -97,6 +96,19 @@ Popup {
stickersContainer.visible = true
}
Connections {
target: root.store.stickersModuleInst
function onStickerPackInstalled(packId) {
const idx = stickersModule.stickerPacks.findIndexById(packId, false);
if (idx === -1) {
return
}
stickersModule.stickerPacks.findStickersById(packId)
stickerGrid.model = stickersModule.stickerPacks.getFoundStickers()
stickerPackListView.itemAt(idx).clicked()
}
}
Loader {
id: marketLoader
anchors.centerIn: parent