mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-11 14:54:48 +00:00
refactor: load gifs asynchronously
Instead of loading recent gifs right on startup eagerly, we postpone the task to when it's actually needed (when the gif popup is opened and the recent gifs tab is activated), and on top of that we also load the data asynchronously to keep the amount of work that needs to be done in a single tick as short as possible. This needs: status-im/status-go#3170 Closes #9437
This commit is contained in:
parent
2ac1216b68
commit
919f3dc6f7
@ -209,7 +209,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||
result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||
result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
|
||||
result.nodeService = node_service.newService(statusFoundation.events, result.settingsService, result.nodeConfigurationService)
|
||||
result.gifService = gif_service.newService(result.settingsService)
|
||||
result.gifService = gif_service.newService(result.settingsService, statusFoundation.events, statusFoundation.threadpool)
|
||||
result.ensService = ens_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||
result.settingsService, result.walletAccountService, result.transactionService,
|
||||
result.networkService, result.tokenService)
|
||||
|
@ -4,11 +4,13 @@ import ../../../../../../app_service/service/community/service as community_serv
|
||||
import ../../../../../../app_service/service/chat/service as chat_service
|
||||
import ../../../../../../app_service/service/gif/service as gif_service
|
||||
import ../../../../../../app_service/service/gif/dto
|
||||
import ../../../../../core/eventemitter
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
sectionId: string
|
||||
events: EventEmitter
|
||||
chatId: string
|
||||
belongsToCommunity: bool
|
||||
communityService: community_service.Service
|
||||
@ -17,6 +19,7 @@ type
|
||||
|
||||
proc newController*(
|
||||
delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
sectionId: string,
|
||||
chatId: string,
|
||||
belongsToCommunity: bool,
|
||||
@ -26,6 +29,7 @@ proc newController*(
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.sectionId = chatId
|
||||
result.chatId = chatId
|
||||
result.belongsToCommunity = belongsToCommunity
|
||||
@ -37,7 +41,13 @@ proc delete*(self: Controller) =
|
||||
discard
|
||||
|
||||
proc init*(self: Controller) =
|
||||
discard
|
||||
self.events.on(SIGNAL_LOAD_RECENT_GIFS_DONE) do(e:Args):
|
||||
let args = GifsArgs(e)
|
||||
self.delegate.loadRecentGifsDone(args.gifs)
|
||||
|
||||
self.events.on(SIGNAL_LOAD_FAVORITE_GIFS_DONE) do(e:Args):
|
||||
let args = GifsArgs(e)
|
||||
self.delegate.loadFavoriteGifsDone(args.gifs)
|
||||
|
||||
proc getChatId*(self: Controller): string =
|
||||
return self.chatId
|
||||
@ -84,6 +94,12 @@ proc getTrendingsGifs*(self: Controller): seq[GifDto] =
|
||||
proc getRecentsGifs*(self: Controller): seq[GifDto] =
|
||||
return self.gifService.getRecents()
|
||||
|
||||
proc loadRecentGifs*(self: Controller) =
|
||||
self.gifService.asyncLoadRecentGifs()
|
||||
|
||||
proc loadFavoriteGifs*(self: Controller) =
|
||||
self.gifService.asyncLoadFavoriteGifs()
|
||||
|
||||
proc getFavoritesGifs*(self: Controller): seq[GifDto] =
|
||||
return self.gifService.getFavorites()
|
||||
|
||||
|
@ -50,9 +50,21 @@ method getTrendingsGifs*(self: AccessInterface): seq[GifDto] {.base.} =
|
||||
method getRecentsGifs*(self: AccessInterface): seq[GifDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method loadRecentGifs*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method loadRecentGifsDone*(self: AccessInterface, gifs: seq[GifDto]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getFavoritesGifs*(self: AccessInterface): seq[GifDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method loadFavoriteGifs*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method loadFavoriteGifsDone*(self: AccessInterface, gifs: seq[GifDto]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method toggleFavoriteGif*(self: AccessInterface, item: GifDto) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -3,6 +3,7 @@ import io_interface
|
||||
import ../io_interface as delegate_interface
|
||||
import view, controller
|
||||
import ../../../../../global/global_singleton
|
||||
import ../../../../../core/eventemitter
|
||||
|
||||
import ../../../../../../app_service/service/chat/service as chat_service
|
||||
import ../../../../../../app_service/service/community/service as community_service
|
||||
@ -21,6 +22,7 @@ type
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
sectionId: string,
|
||||
chatId: string,
|
||||
belongsToCommunity: bool,
|
||||
@ -33,7 +35,7 @@ proc newModule*(
|
||||
result.delegate = delegate
|
||||
result.view = view.newView(result)
|
||||
result.viewVariant = newQVariant(result.view)
|
||||
result.controller = controller.newController(result, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
|
||||
result.controller = controller.newController(result, events, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
@ -98,9 +100,21 @@ method getTrendingsGifs*(self: Module): seq[GifDto] =
|
||||
method getRecentsGifs*(self: Module): seq[GifDto] =
|
||||
return self.controller.getRecentsGifs()
|
||||
|
||||
method loadRecentGifs*(self: Module) =
|
||||
self.controller.loadRecentGifs()
|
||||
|
||||
method loadRecentGifsDone*(self: Module, gifs: seq[GifDto]) =
|
||||
self.view.updateGifColumns(gifs)
|
||||
|
||||
method getFavoritesGifs*(self: Module): seq[GifDto] =
|
||||
return self.controller.getFavoritesGifs()
|
||||
|
||||
method loadFavoriteGifs*(self: Module) =
|
||||
self.controller.loadFavoriteGifs()
|
||||
|
||||
method loadFavoriteGifsDone*(self: Module, gifs: seq[GifDto]) =
|
||||
self.view.updateGifColumns(gifs)
|
||||
|
||||
method toggleFavoriteGif*(self: Module, item: GifDto) =
|
||||
self.controller.toggleFavoriteGif(item)
|
||||
|
||||
|
@ -80,7 +80,7 @@ QtObject:
|
||||
read = getGifColumnC
|
||||
notify = gifLoaded
|
||||
|
||||
proc updateGifColumns(self: View, data: seq[GifDto]) =
|
||||
proc updateGifColumns*(self: View, data: seq[GifDto]) =
|
||||
var columnAData: seq[GifDto] = @[]
|
||||
var columnAHeight = 0
|
||||
var columnBData: seq[GifDto] = @[]
|
||||
@ -115,11 +115,21 @@ QtObject:
|
||||
|
||||
proc getRecentsGifs*(self: View) {.slot.} =
|
||||
let data = self.delegate.getRecentsGifs()
|
||||
if data.len > 0:
|
||||
self.updateGifColumns(data)
|
||||
return
|
||||
|
||||
# recent gifs were not loaded yet, so we do it now
|
||||
self.delegate.loadRecentGifs()
|
||||
|
||||
proc getFavoritesGifs*(self: View) {.slot.} =
|
||||
let data = self.delegate.getFavoritesGifs()
|
||||
if data.len > 0:
|
||||
self.updateGifColumns(data)
|
||||
return
|
||||
|
||||
# favorite gifs were not loaded yet, so we do it now
|
||||
self.delegate.loadFavoriteGifs()
|
||||
|
||||
proc findGifDto(self: View, id: string): GifDto =
|
||||
for item in self.gifColumnAModel.gifs:
|
||||
|
@ -52,7 +52,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitt
|
||||
isUsersListAvailable, settingsService, nodeConfigurationService, contactService, chatService, communityService, messageService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
result.inputAreaModule = input_area_module.newModule(result, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
|
||||
result.inputAreaModule = input_area_module.newModule(result, events, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
|
||||
result.messagesModule = messages_module.newModule(result, events, sectionId, chatId, belongsToCommunity,
|
||||
contactService, communityService, chatService, messageService, mailserversService)
|
||||
result.usersModule =
|
||||
|
19
src/app_service/service/gif/async_tasks.nim
Normal file
19
src/app_service/service/gif/async_tasks.nim
Normal file
@ -0,0 +1,19 @@
|
||||
include ../../common/json_utils
|
||||
include ../../../app/core/tasks/common
|
||||
import ../../../backend/gifs as status_go
|
||||
|
||||
type
|
||||
AsyncGetRecentGifsTaskArg = ref object of QObjectTaskArg
|
||||
|
||||
const asyncGetRecentGifsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[AsyncGetRecentGifsTaskArg](argEncoded)
|
||||
let response = status_go.getRecentGifs()
|
||||
arg.finish(response)
|
||||
|
||||
type
|
||||
AsyncGetFavoriteGifsTaskArg = ref object of QObjectTaskArg
|
||||
|
||||
const asyncGetFavoriteGifsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[AsyncGetFavoriteGifsTaskArg](argEncoded)
|
||||
let response = status_go.getFavoriteGifs()
|
||||
arg.finish(response)
|
@ -4,11 +4,17 @@ import os
|
||||
import uri
|
||||
import chronicles
|
||||
import sequtils
|
||||
import NimQml
|
||||
|
||||
import ../settings/service as settings_service
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../backend/backend
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
import ../../../app/core/[main]
|
||||
import ./dto
|
||||
|
||||
include ./async_tasks
|
||||
|
||||
logScope:
|
||||
topics = "gif-service"
|
||||
|
||||
@ -23,18 +29,35 @@ let TENOR_API_KEY_RESOLVED =
|
||||
else:
|
||||
TENOR_API_KEY
|
||||
|
||||
const SIGNAL_LOAD_RECENT_GIFS_STARTED* = "loadRecentGifsStarted"
|
||||
const SIGNAL_LOAD_RECENT_GIFS_DONE* = "loadRecentGifsDone"
|
||||
|
||||
const SIGNAL_LOAD_FAVORITE_GIFS_STARTED* = "loadFavoriteGifsStarted"
|
||||
const SIGNAL_LOAD_FAVORITE_GIFS_DONE* = "loadFavoriteGifsDone"
|
||||
|
||||
type
|
||||
Service* = ref object of RootObj
|
||||
GifsArgs* = ref object of Args
|
||||
gifs*: seq[GifDto]
|
||||
error*: string
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Service* = ref object of QObject
|
||||
threadpool: ThreadPool
|
||||
settingsService: settings_service.Service
|
||||
favorites: seq[GifDto]
|
||||
recents: seq[GifDto]
|
||||
events: EventEmitter
|
||||
|
||||
proc delete*(self: Service) =
|
||||
discard
|
||||
|
||||
proc newService*(settingsService: settings_service.Service): Service =
|
||||
proc newService*(settingsService: settings_service.Service, events: EventEmitter, threadpool: ThreadPool): Service =
|
||||
result = Service()
|
||||
result.QObject.setup
|
||||
result.settingsService = settingsService
|
||||
result.events = events
|
||||
result.threadpool = threadpool
|
||||
result.favorites = @[]
|
||||
result.recents = @[]
|
||||
|
||||
@ -71,14 +94,62 @@ proc getFavoriteGifs(self: Service) =
|
||||
except Exception as e:
|
||||
error "error: ", procName="getFavoriteGifs", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc asyncLoadRecentGifs*(self: Service) =
|
||||
self.events.emit(SIGNAL_LOAD_RECENT_GIFS_STARTED, Args())
|
||||
try:
|
||||
let arg = AsyncGetRecentGifsTaskArg(
|
||||
tptr: cast[ByteAddress](asyncGetRecentGifsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onAsyncGetRecentGifsDone"
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
except Exception as e:
|
||||
error "Error loading recent gifs", msg = e.msg
|
||||
|
||||
proc onAsyncGetRecentGifsDone*(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 recent gifs", msg = error.message
|
||||
return
|
||||
|
||||
self.recents = map(rpcResponseObj{"result"}.getElems(), settingToGifDto)
|
||||
self.events.emit(SIGNAL_LOAD_RECENT_GIFS_DONE, GifsArgs(gifs: self.recents))
|
||||
except Exception as e:
|
||||
let errMsg = e.msg
|
||||
error "error: ", errMsg
|
||||
|
||||
proc asyncLoadFavoriteGifs*(self: Service) =
|
||||
self.events.emit(SIGNAL_LOAD_FAVORITE_GIFS_STARTED, Args())
|
||||
try:
|
||||
let arg = AsyncGetFavoriteGifsTaskArg(
|
||||
tptr: cast[ByteAddress](asyncGetFavoriteGifsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onAsyncGetFavoriteGifsDone"
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
except Exception as e:
|
||||
error "Error loading favorite gifs", msg = e.msg
|
||||
|
||||
proc onAsyncGetFavoriteGifsDone*(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 favorite gifs", msg = error.message
|
||||
return
|
||||
|
||||
self.favorites = map(rpcResponseObj{"result"}.getElems(), settingToGifDto)
|
||||
self.events.emit(SIGNAL_LOAD_FAVORITE_GIFS_DONE, GifsArgs(gifs: self.favorites))
|
||||
except Exception as e:
|
||||
let errMsg = e.msg
|
||||
error "error: ", errMsg
|
||||
|
||||
proc init*(self: Service) =
|
||||
# set Tenor API Key
|
||||
self.setTenorAPIKey()
|
||||
|
||||
# get recent and favorite gifs on the database
|
||||
self.getRecentGifs()
|
||||
self.getFavoriteGifs()
|
||||
|
||||
proc tenorQuery(self: Service, path: string): seq[GifDto] =
|
||||
try:
|
||||
let response = backend.fetchGifs(path)
|
||||
|
13
src/backend/gifs.nim
Normal file
13
src/backend/gifs.nim
Normal file
@ -0,0 +1,13 @@
|
||||
import json, strutils
|
||||
import core
|
||||
import response_type
|
||||
|
||||
export response_type
|
||||
|
||||
proc getRecentGifs*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* []
|
||||
result = callPrivateRPC("gif_getRecentGifs", payload)
|
||||
|
||||
proc getFavoriteGifs*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* []
|
||||
result = callPrivateRPC("gif_getFavoriteGifs", payload)
|
Loading…
x
Reference in New Issue
Block a user