feat: call getPreviewData (url unfurling) in a separate thread

Fixes #1678
This commit is contained in:
Jonathan Rainville 2021-01-15 15:33:32 -05:00 committed by Iuri Matias
parent 0daf355f54
commit 444072f599
4 changed files with 53 additions and 22 deletions

View File

@ -1,6 +1,7 @@
import NimQml, Tables, json, sequtils, chronicles, times, re, sugar, strutils, os, strformat
import ../../status/status
import ../../status/mailservers
import ../../status/libstatus/chat as libstatus_chat
import ../../status/libstatus/accounts/constants
import ../../status/libstatus/mailservers as status_mailservers
import ../../status/libstatus/types
@ -386,11 +387,17 @@ QtObject:
proc copyToClipboard*(self: ChatsView, content: string) {.slot.} =
setClipBoardText(content)
proc getLinkPreviewData*(self: ChatsView, link: string): string {.slot.} =
try:
$self.status.chat.getLinkPreviewData(link)
except RpcException as e:
$ %* { "error": e.msg }
proc linkPreviewDataWasReceived*(self: ChatsView, previewData: string) {.signal.}
proc linkPreviewDataReceived(self: ChatsView, previewData: string) {.slot.} =
self.linkPreviewDataWasReceived(previewData)
proc getLinkPreviewData*(self: ChatsView, link: string, uuid: string) {.slot.} =
spawnAndSend(self, "linkPreviewDataReceived") do:
var success: bool
# We need to call directly on libstatus because going through the status model is not thread safe
let response = libstatus_chat.getLinkPreviewData(link, success)
$(%* { "result": %response, "success": %success, "uuid": %uuid })
proc joinChat*(self: ChatsView, channel: string, chatTypeInt: int): int {.slot.} =
self.status.chat.join(channel, ChatType(chatTypeInt))

View File

@ -218,9 +218,6 @@ proc clearHistory*(self: ChatModel, chatId: string) =
let chat = self.channels[chatId]
self.events.emit("chatHistoryCleared", ChannelArgs(chat: chat))
proc getLinkPreviewData*(self: ChatModel, link: string): JsonNode =
result = status_chat.getLinkPreviewData(link)
proc setActiveChannel*(self: ChatModel, chatId: string) =
self.events.emit("activeChannelChanged", ChatIdArg(chatId: chatId))

View File

@ -201,14 +201,16 @@ proc muteChat*(chatId: string): string =
proc unmuteChat*(chatId: string): string =
result = callPrivateRPC("unmuteChat".prefix, %*[chatId])
proc getLinkPreviewData*(link: string): JsonNode =
proc getLinkPreviewData*(link: string, success: var bool): JsonNode =
let
responseStr = callPrivateRPC("getLinkPreviewData".prefix, %*[link])
response = Json.decode(responseStr, RpcResponseTyped[JsonNode], allowUnknownFields = false)
if not response.error.isNil:
raise newException(RpcException, fmt"""Error getting link preview data for '{link}': {response.error.message}""")
success = false
return %* { "error": fmt"""Error getting link preview data for '{link}': {response.error.message}""" }
success = true
response.result
proc getAllComunities*(): seq[Community] =

View File

@ -12,6 +12,7 @@ Column {
property string linkUrls: ""
property var container
property bool isCurrentUser: false
readonly property string uuid: Utils.uuid()
spacing: Style.current.halfPadding
ListModel {
@ -32,6 +33,7 @@ Column {
delegate: Loader {
id: linkMessageLoader
property bool fetched: false
property var linkData
property int linkWidth: linksRepeater.width
active: true
@ -51,6 +53,37 @@ Column {
linkMessageLoader.sourceComponent = linkMessageLoader.getSourceComponent()
}
}
Connections {
target: chatsModel
onLinkPreviewDataWasReceived: {
let response
try {
response = JSON.parse(previewData)
} catch (e) {
console.error(previewData, e)
return
}
if (response.uuid !== root.uuid) return
if (!response.success) {
console.error(response.result.error)
return undefined
}
linkData = response.result
if (linkData.contentType.startsWith("image/")) {
return linkMessageLoader.sourceComponent = unfurledImageComponent
}
if (linkData.site && linkData.title) {
linkData.address = link
return linkMessageLoader.sourceComponent = unfurledLinkComponent
}
}
}
function getSourceComponent() {
// Reset the height in case we set it to 0 below. See note below
@ -75,19 +108,11 @@ Column {
return enableLinkComponent
}
if (linkWhiteListed) {
const data = chatsModel.getLinkPreviewData(link)
linkData = JSON.parse(data)
if (linkData.error) {
console.error(linkData.error)
return undefined
}
if (linkData.contentType.startsWith("image/")) {
return unfurledImageComponent
}
if (linkData.site && linkData.title) {
linkData.address = link
return unfurledLinkComponent
if (fetched) {
return
}
fetched = true
return chatsModel.getLinkPreviewData(link, root.uuid)
}
// setting the height to 0 allows the "enable link" dialog to
// disappear correctly when appSettings.neverAskAboutUnfurlingAgain