refactor(messages): make message sending async (#15237)
Fixes #12411 Makes message sending async and adds a placeholder "Sending.." message
This commit is contained in:
parent
033bf99974
commit
8ca51c34cc
|
@ -95,6 +95,18 @@ proc init*(self: Controller) =
|
||||||
self.unfurlingPlanActiveRequest = ""
|
self.unfurlingPlanActiveRequest = ""
|
||||||
self.handleUnfurlingPlan(self.unfurlingPlanActiveRequestUnfurlAfter)
|
self.handleUnfurlingPlan(self.unfurlingPlanActiveRequestUnfurlAfter)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_SENDING_SUCCESS) do(e:Args):
|
||||||
|
let args = MessageSendingSuccess(e)
|
||||||
|
if self.chatId != args.chat.id:
|
||||||
|
return
|
||||||
|
self.delegate.onSendingMessageSuccess()
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_SENDING_FAILED) do(e:Args):
|
||||||
|
let args = MessageSendingFailure(e)
|
||||||
|
if self.chatId != args.chatId:
|
||||||
|
return
|
||||||
|
self.delegate.onSendingMessageFailure()
|
||||||
|
|
||||||
proc getChatId*(self: Controller): string =
|
proc getChatId*(self: Controller): string =
|
||||||
return self.chatId
|
return self.chatId
|
||||||
|
|
||||||
|
@ -116,9 +128,9 @@ proc sendImages*(self: Controller,
|
||||||
msg: string,
|
msg: string,
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
preferredUsername: string = "",
|
preferredUsername: string = "",
|
||||||
linkPreviews: seq[LinkPreview]): string =
|
linkPreviews: seq[LinkPreview]) =
|
||||||
self.resetLinkPreviews()
|
self.resetLinkPreviews()
|
||||||
self.chatService.sendImages(
|
self.chatService.asyncSendImages(
|
||||||
self.chatId,
|
self.chatId,
|
||||||
imagePathsAndDataJson,
|
imagePathsAndDataJson,
|
||||||
msg,
|
msg,
|
||||||
|
@ -134,7 +146,7 @@ proc sendChatMessage*(self: Controller,
|
||||||
preferredUsername: string = "",
|
preferredUsername: string = "",
|
||||||
linkPreviews: seq[LinkPreview]) =
|
linkPreviews: seq[LinkPreview]) =
|
||||||
self.resetLinkPreviews()
|
self.resetLinkPreviews()
|
||||||
self.chatService.sendChatMessage(self.chatId,
|
self.chatService.asyncSendChatMessage(self.chatId,
|
||||||
msg,
|
msg,
|
||||||
replyTo,
|
replyTo,
|
||||||
contentType,
|
contentType,
|
||||||
|
|
|
@ -22,7 +22,7 @@ method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
||||||
method sendChatMessage*(self: AccessInterface, msg: string, replyTo: string, contentType: int, linkPreviews: seq[LinkPreview]) {.base.} =
|
method sendChatMessage*(self: AccessInterface, msg: string, replyTo: string, contentType: int, linkPreviews: seq[LinkPreview]) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method sendImages*(self: AccessInterface, imagePathsJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview]): string {.base.} =
|
method sendImages*(self: AccessInterface, imagePathsJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview]) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method requestAddressForTransaction*(self: AccessInterface, fromAddress: string, amount: string, tokenAddress: string) {.base.} =
|
method requestAddressForTransaction*(self: AccessInterface, fromAddress: string, amount: string, tokenAddress: string) {.base.} =
|
||||||
|
@ -138,3 +138,9 @@ method setUrls*(self: AccessInterface, urls: seq[string]) {.base.} =
|
||||||
|
|
||||||
method getContactDetails*(self: AccessInterface, contactId: string): ContactDetails {.base.} =
|
method getContactDetails*(self: AccessInterface, contactId: string): ContactDetails {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onSendingMessageSuccess*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onSendingMessageFailure*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
|
@ -65,7 +65,7 @@ method getModuleAsVariant*(self: Module): QVariant =
|
||||||
proc getChatId*(self: Module): string =
|
proc getChatId*(self: Module): string =
|
||||||
return self.controller.getChatId()
|
return self.controller.getChatId()
|
||||||
|
|
||||||
method sendImages*(self: Module, imagePathsAndDataJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview]): string =
|
method sendImages*(self: Module, imagePathsAndDataJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview]) =
|
||||||
self.controller.sendImages(imagePathsAndDataJson, msg, replyTo, singletonInstance.userProfile.getPreferredName(), linkPreviews)
|
self.controller.sendImages(imagePathsAndDataJson, msg, replyTo, singletonInstance.userProfile.getPreferredName(), linkPreviews)
|
||||||
|
|
||||||
method sendChatMessage*(
|
method sendChatMessage*(
|
||||||
|
@ -136,3 +136,9 @@ method setUrls*(self: Module, urls: seq[string]) =
|
||||||
|
|
||||||
method getContactDetails*(self: Module, contactId: string): ContactDetails =
|
method getContactDetails*(self: Module, contactId: string): ContactDetails =
|
||||||
return self.controller.getContactDetails(contactId)
|
return self.controller.getContactDetails(contactId)
|
||||||
|
|
||||||
|
method onSendingMessageSuccess*(self: Module) =
|
||||||
|
self.view.emitSendingMessageSuccess()
|
||||||
|
|
||||||
|
method onSendingMessageFailure*(self: Module) =
|
||||||
|
self.view.emitSendingMessageFailure()
|
||||||
|
|
|
@ -15,10 +15,13 @@ QtObject:
|
||||||
linkPreviewModelVariant: QVariant
|
linkPreviewModelVariant: QVariant
|
||||||
urlsModel: urls_model.Model
|
urlsModel: urls_model.Model
|
||||||
urlsModelVariant: QVariant
|
urlsModelVariant: QVariant
|
||||||
|
sendingInProgress: bool
|
||||||
askToEnableLinkPreview: bool
|
askToEnableLinkPreview: bool
|
||||||
emojiReactionsModel: emoji_reactions_model.Model
|
emojiReactionsModel: emoji_reactions_model.Model
|
||||||
emojiReactionsModelVariant: QVariant
|
emojiReactionsModelVariant: QVariant
|
||||||
|
|
||||||
|
proc setSendingInProgress*(self: View, value: bool)
|
||||||
|
|
||||||
proc delete*(self: View) =
|
proc delete*(self: View) =
|
||||||
self.QObject.delete
|
self.QObject.delete
|
||||||
self.preservedPropertiesVariant.delete
|
self.preservedPropertiesVariant.delete
|
||||||
|
@ -53,11 +56,13 @@ QtObject:
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
contentType: int) {.slot.} =
|
contentType: int) {.slot.} =
|
||||||
# FIXME: Update this when `setText` is async.
|
# FIXME: Update this when `setText` is async.
|
||||||
|
self.setSendingInProgress(true)
|
||||||
self.delegate.setText(msg, false)
|
self.delegate.setText(msg, false)
|
||||||
self.delegate.sendChatMessage(msg, replyTo, contentType, self.linkPreviewModel.getUnfuledLinkPreviews())
|
self.delegate.sendChatMessage(msg, replyTo, contentType, self.linkPreviewModel.getUnfuledLinkPreviews())
|
||||||
|
|
||||||
proc sendImages*(self: View, imagePathsAndDataJson: string, msg: string, replyTo: string): string {.slot.} =
|
proc sendImages*(self: View, imagePathsAndDataJson: string, msg: string, replyTo: string) {.slot.} =
|
||||||
# FIXME: Update this when `setText` is async.
|
# FIXME: Update this when `setText` is async.
|
||||||
|
self.setSendingInProgress(true)
|
||||||
self.delegate.setText(msg, false)
|
self.delegate.setText(msg, false)
|
||||||
self.delegate.sendImages(imagePathsAndDataJson, msg, replyTo, self.linkPreviewModel.getUnfuledLinkPreviews())
|
self.delegate.sendImages(imagePathsAndDataJson, msg, replyTo, self.linkPreviewModel.getUnfuledLinkPreviews())
|
||||||
|
|
||||||
|
@ -154,3 +159,21 @@ QtObject:
|
||||||
QtProperty[QVariant] urlsModel:
|
QtProperty[QVariant] urlsModel:
|
||||||
read = getUrlsModel
|
read = getUrlsModel
|
||||||
notify = urlsModelChanged
|
notify = urlsModelChanged
|
||||||
|
|
||||||
|
proc sendingInProgressChanged(self: View) {.signal.}
|
||||||
|
proc getSendingInProgress*(self: View): bool {.slot.} =
|
||||||
|
return self.sendingInProgress
|
||||||
|
|
||||||
|
QtProperty[bool] sendingInProgress:
|
||||||
|
read = getSendingInProgress
|
||||||
|
notify = sendingInProgressChanged
|
||||||
|
|
||||||
|
proc setSendingInProgress*(self: View, value: bool) =
|
||||||
|
self.sendingInProgress = value
|
||||||
|
self.sendingInProgressChanged()
|
||||||
|
|
||||||
|
proc emitSendingMessageSuccess*(self: View) =
|
||||||
|
self.setSendingInProgress(false)
|
||||||
|
|
||||||
|
proc emitSendingMessageFailure*(self: View) =
|
||||||
|
self.setSendingInProgress(false)
|
||||||
|
|
|
@ -79,10 +79,10 @@ proc init*(self: Controller) =
|
||||||
self.delegate.onSendingMessageSuccess(args.message)
|
self.delegate.onSendingMessageSuccess(args.message)
|
||||||
|
|
||||||
self.events.on(SIGNAL_SENDING_FAILED) do(e:Args):
|
self.events.on(SIGNAL_SENDING_FAILED) do(e:Args):
|
||||||
let args = ChatArgs(e)
|
let args = MessageSendingFailure(e)
|
||||||
if(self.chatId != args.chatId):
|
if(self.chatId != args.chatId):
|
||||||
return
|
return
|
||||||
self.delegate.onSendingMessageError()
|
self.delegate.onSendingMessageError(args.error)
|
||||||
|
|
||||||
self.events.on(SIGNAL_ENVELOPE_SENT) do(e:Args):
|
self.events.on(SIGNAL_ENVELOPE_SENT) do(e:Args):
|
||||||
let args = EnvelopeSentArgs(e)
|
let args = EnvelopeSentArgs(e)
|
||||||
|
|
|
@ -60,7 +60,7 @@ method messagesAdded*(self: AccessInterface, messages: seq[MessageDto]) {.base.}
|
||||||
method onSendingMessageSuccess*(self: AccessInterface, message: MessageDto) {.base.} =
|
method onSendingMessageSuccess*(self: AccessInterface, message: MessageDto) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method onSendingMessageError*(self: AccessInterface) {.base.} =
|
method onSendingMessageError*(self: AccessInterface, error: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method onEnvelopeSent*(self: AccessInterface, messagesIds: seq[string]) {.base.} =
|
method onEnvelopeSent*(self: AccessInterface, messagesIds: seq[string]) {.base.} =
|
||||||
|
|
|
@ -433,8 +433,8 @@ method onSendingMessageSuccess*(self: Module, message: MessageDto) =
|
||||||
self.view.emitSendingMessageSuccessSignal()
|
self.view.emitSendingMessageSuccessSignal()
|
||||||
self.removeNewMessagesMarker()
|
self.removeNewMessagesMarker()
|
||||||
|
|
||||||
method onSendingMessageError*(self: Module) =
|
method onSendingMessageError*(self: Module, error: string) =
|
||||||
self.view.emitSendingMessageErrorSignal()
|
self.view.emitSendingMessageErrorSignal(error)
|
||||||
|
|
||||||
method onEnvelopeSent*(self: Module, messagesIds: seq[string]) =
|
method onEnvelopeSent*(self: Module, messagesIds: seq[string]) =
|
||||||
for messageId in messagesIds:
|
for messageId in messagesIds:
|
||||||
|
|
|
@ -106,10 +106,10 @@ QtObject:
|
||||||
proc emitSendingMessageSuccessSignal*(self: View) =
|
proc emitSendingMessageSuccessSignal*(self: View) =
|
||||||
self.messageSuccessfullySent()
|
self.messageSuccessfullySent()
|
||||||
|
|
||||||
proc sendingMessageFailed*(self: View) {.signal.}
|
proc sendingMessageFailed*(self: View, error: string) {.signal.}
|
||||||
|
|
||||||
proc emitSendingMessageErrorSignal*(self: View) =
|
proc emitSendingMessageErrorSignal*(self: View, error: string) =
|
||||||
self.sendingMessageFailed()
|
self.sendingMessageFailed(error)
|
||||||
|
|
||||||
proc deleteMessage*(self: View, messageId: string) {.slot.} =
|
proc deleteMessage*(self: View, messageId: string) {.slot.} =
|
||||||
self.delegate.deleteMessage(messageId)
|
self.delegate.deleteMessage(messageId)
|
||||||
|
|
|
@ -151,7 +151,7 @@ proc sendSticker*(
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
sticker: StickerDto,
|
sticker: StickerDto,
|
||||||
preferredUsername: string) =
|
preferredUsername: string) =
|
||||||
self.stickerService.sendSticker(channelId, replyTo, sticker, preferredUsername)
|
self.stickerService.asyncSendSticker(channelId, replyTo, sticker, preferredUsername)
|
||||||
|
|
||||||
proc wei2Eth*(self: Controller, price: Stuint[256]): string =
|
proc wei2Eth*(self: Controller, price: Stuint[256]): string =
|
||||||
eth_utils.wei2Eth(price)
|
eth_utils.wei2Eth(price)
|
||||||
|
|
|
@ -62,3 +62,77 @@ proc asyncCheckAllChannelsPermissionsTask(argEncoded: string) {.gcsafe, nimcall.
|
||||||
"communityId": arg.communityId,
|
"communityId": arg.communityId,
|
||||||
"error": e.msg,
|
"error": e.msg,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
type
|
||||||
|
AsyncSendMessageTaskArg = ref object of QObjectTaskArg
|
||||||
|
chatId: string
|
||||||
|
processedMsg: string
|
||||||
|
replyTo: string
|
||||||
|
contentType: int
|
||||||
|
preferredUsername: string
|
||||||
|
communityId: string
|
||||||
|
standardLinkPreviews: JsonNode
|
||||||
|
statusLinkPreviews: JsonNode
|
||||||
|
|
||||||
|
const asyncSendMessageTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
|
let arg = decode[AsyncSendMessageTaskArg](argEncoded)
|
||||||
|
try:
|
||||||
|
|
||||||
|
let response = status_chat.sendChatMessage(
|
||||||
|
arg.chatId,
|
||||||
|
arg.processedMsg,
|
||||||
|
arg.replyTo,
|
||||||
|
arg.contentType,
|
||||||
|
arg.preferredUsername,
|
||||||
|
arg.standardLinkPreviews,
|
||||||
|
arg.statusLinkPreviews,
|
||||||
|
arg.communityId)
|
||||||
|
|
||||||
|
arg.finish(%* {
|
||||||
|
"response": response,
|
||||||
|
"chatId": arg.chatId,
|
||||||
|
"error": "",
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
arg.finish(%* {
|
||||||
|
"error": e.msg,
|
||||||
|
"chatId": arg.chatId,
|
||||||
|
})
|
||||||
|
|
||||||
|
type
|
||||||
|
AsyncSendImagesTaskArg = ref object of QObjectTaskArg
|
||||||
|
chatId: string
|
||||||
|
imagePathsAndDataJson: string
|
||||||
|
tempDir: string
|
||||||
|
msg: string
|
||||||
|
replyTo: string
|
||||||
|
preferredUsername: string
|
||||||
|
linkPreviews: JsonNode
|
||||||
|
|
||||||
|
const asyncSendImagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
|
let arg = decode[AsyncSendImagesTaskArg](argEncoded)
|
||||||
|
try:
|
||||||
|
var images = Json.decode(arg.imagePathsAndDataJson, seq[string])
|
||||||
|
var imagePaths: seq[string] = @[]
|
||||||
|
|
||||||
|
for imagePathOrSource in images.mitems:
|
||||||
|
let imagePath = image_resizer(imagePathOrSource, 2000, arg.tempDir)
|
||||||
|
if imagePath != "":
|
||||||
|
imagePaths.add(imagePath)
|
||||||
|
|
||||||
|
let response = status_chat.sendImages(arg.chatId, imagePaths, arg.msg, arg.replyTo, arg.preferredUsername,
|
||||||
|
arg.linkPreviews)
|
||||||
|
|
||||||
|
for imagePath in imagePaths:
|
||||||
|
removeFile(imagePath)
|
||||||
|
|
||||||
|
arg.finish(%* {
|
||||||
|
"response": response,
|
||||||
|
"chatId": arg.chatId,
|
||||||
|
"error": "",
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
arg.finish(%* {
|
||||||
|
"error": e.msg,
|
||||||
|
"chatId": arg.chatId,
|
||||||
|
})
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import NimQml, Tables, json, sequtils, stew/shims/strformat, chronicles, os, strutils, uuids, base64
|
import NimQml, Tables, json, sequtils, chronicles, os, strutils, uuids, base64
|
||||||
import std/[times, os]
|
import std/[times, os]
|
||||||
|
|
||||||
import ../../../app/core/tasks/[qt, threadpool]
|
import ../../../app/core/tasks/[qt, threadpool]
|
||||||
import ./dto/chat as chat_dto
|
import ./dto/chat as chat_dto
|
||||||
import ../message/dto/message as message_dto
|
import ../message/dto/message as message_dto
|
||||||
import ../message/dto/link_preview
|
import ../message/dto/[link_preview, standard_link_preview, status_link_preview]
|
||||||
import ../activity_center/dto/notification as notification_dto
|
import ../activity_center/dto/notification as notification_dto
|
||||||
import ../community/dto/community as community_dto
|
import ../community/dto/community as community_dto
|
||||||
import ../contacts/service as contact_service
|
import ../contacts/service as contact_service
|
||||||
|
@ -47,6 +47,10 @@ type
|
||||||
chat*: ChatDto
|
chat*: ChatDto
|
||||||
message*: MessageDto
|
message*: MessageDto
|
||||||
|
|
||||||
|
MessageSendingFailure* = ref object of Args
|
||||||
|
chatId*: string
|
||||||
|
error*: string
|
||||||
|
|
||||||
MessageArgs* = ref object of Args
|
MessageArgs* = ref object of Args
|
||||||
id*: string
|
id*: string
|
||||||
channel*: string
|
channel*: string
|
||||||
|
@ -420,36 +424,46 @@ QtObject:
|
||||||
error "Error deleting channel", chatId, msg = e.msg
|
error "Error deleting channel", chatId, msg = e.msg
|
||||||
return
|
return
|
||||||
|
|
||||||
proc sendImages*(self: Service,
|
proc asyncSendImages*(self: Service,
|
||||||
chatId: string,
|
chatId: string,
|
||||||
imagePathsAndDataJson: string,
|
imagePathsAndDataJson: string,
|
||||||
msg: string,
|
msg: string,
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
preferredUsername: string = "",
|
preferredUsername: string = "",
|
||||||
linkPreviews: seq[LinkPreview] = @[]): string =
|
linkPreviews: seq[LinkPreview] = @[]) =
|
||||||
result = ""
|
|
||||||
|
|
||||||
|
let arg = AsyncSendImagesTaskArg(
|
||||||
|
tptr: asyncSendImagesTask,
|
||||||
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
|
slot: "onAsyncSendImagesDone",
|
||||||
|
chatId: chatId,
|
||||||
|
imagePathsAndDataJson: imagePathsAndDataJson,
|
||||||
|
tempDir: TMPDIR,
|
||||||
|
msg: msg,
|
||||||
|
replyTo: replyTo,
|
||||||
|
preferredUsername: preferredUsername,
|
||||||
|
linkPreviews: %linkPreviews,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
|
proc onAsyncSendImagesDone*(self: Service, rpcResponseJson: string) {.slot.} =
|
||||||
|
let rpcResponseObj = rpcResponseJson.parseJson
|
||||||
try:
|
try:
|
||||||
var images = Json.decode(imagePathsAndDataJson, seq[string])
|
|
||||||
let base64JPGPrefix = "data:image/jpeg;base64,"
|
|
||||||
var imagePaths: seq[string] = @[]
|
|
||||||
|
|
||||||
for imagePathOrSource in images.mitems:
|
let errorString = rpcResponseObj{"error"}.getStr()
|
||||||
let imagePath = image_resizer(imagePathOrSource, 2000, TMPDIR)
|
if errorString != "":
|
||||||
if imagePath != "":
|
raise newException(CatchableError, errorString)
|
||||||
imagePaths.add(imagePath)
|
|
||||||
|
|
||||||
let response = status_chat.sendImages(chatId, imagePaths, msg, replyTo, preferredUsername, linkPreviews)
|
let rpcResponse = Json.decode($rpcResponseObj["response"], RpcResponse[JsonNode])
|
||||||
|
|
||||||
for imagePath in imagePaths:
|
discard self.processMessengerResponse(rpcResponse)
|
||||||
removeFile(imagePath)
|
|
||||||
|
|
||||||
discard self.processMessengerResponse(response)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error sending images", msg = e.msg
|
error "Error sending images", msg = e.msg
|
||||||
result = fmt"Error sending images: {e.msg}"
|
self.events.emit(SIGNAL_SENDING_FAILED, MessageSendingFailure(chatId: rpcResponseObj["chatId"].getStr, error: e.msg))
|
||||||
|
|
||||||
proc sendChatMessage*(
|
proc asyncSendChatMessage*(self: Service,
|
||||||
self: Service,
|
|
||||||
chatId: string,
|
chatId: string,
|
||||||
msg: string,
|
msg: string,
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
|
@ -461,20 +475,43 @@ QtObject:
|
||||||
let allKnownContacts = self.contactService.getContactsByGroup(ContactsGroup.AllKnownContacts)
|
let allKnownContacts = self.contactService.getContactsByGroup(ContactsGroup.AllKnownContacts)
|
||||||
let processedMsg = message_common.replaceMentionsWithPubKeys(allKnownContacts, msg)
|
let processedMsg = message_common.replaceMentionsWithPubKeys(allKnownContacts, msg)
|
||||||
|
|
||||||
let response = status_chat.sendChatMessage(
|
let (standardLinkPreviews, statusLinkPreviews) = extractLinkPreviewsLists(linkPreviews)
|
||||||
chatId,
|
|
||||||
processedMsg,
|
|
||||||
replyTo,
|
|
||||||
contentType,
|
|
||||||
preferredUsername,
|
|
||||||
linkPreviews,
|
|
||||||
communityId) # Only send a community ID for the community invites
|
|
||||||
|
|
||||||
let (chats, messages) = self.processMessengerResponse(response)
|
let arg = AsyncSendMessageTaskArg(
|
||||||
if chats.len == 0 or messages.len == 0:
|
tptr: asyncSendMessageTask,
|
||||||
self.events.emit(SIGNAL_SENDING_FAILED, ChatArgs(chatId: chatId))
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
|
slot: "onAsyncSendMessageDone",
|
||||||
|
chatId: chatId,
|
||||||
|
processedMsg: processedMsg,
|
||||||
|
replyTo: replyTo,
|
||||||
|
contentType: contentType,
|
||||||
|
preferredUsername: preferredUsername,
|
||||||
|
communityId: communityId, # Only send a community ID for the community invites
|
||||||
|
standardLinkPreviews: %standardLinkPreviews,
|
||||||
|
statusLinkPreviews: %statusLinkPreviews,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.threadpool.start(arg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error sending message", msg = e.msg
|
error "Error sending message", msg = e.msg
|
||||||
|
self.events.emit(SIGNAL_SENDING_FAILED, MessageSendingFailure(chatId: chatId, error: e.msg))
|
||||||
|
|
||||||
|
proc onAsyncSendMessageDone*(self: Service, rpcResponseJson: string) {.slot.} =
|
||||||
|
let rpcResponseObj = rpcResponseJson.parseJson
|
||||||
|
try:
|
||||||
|
|
||||||
|
let errorString = rpcResponseObj{"error"}.getStr()
|
||||||
|
if errorString != "":
|
||||||
|
raise newException(CatchableError, errorString)
|
||||||
|
|
||||||
|
let rpcResponse = Json.decode($rpcResponseObj["response"], RpcResponse[JsonNode])
|
||||||
|
|
||||||
|
let (chats, messages) = self.processMessengerResponse(rpcResponse)
|
||||||
|
if chats.len == 0 or messages.len == 0:
|
||||||
|
raise newException(CatchableError, "no chat or message returned")
|
||||||
|
except Exception as e:
|
||||||
|
error "Error sending message", msg = e.msg
|
||||||
|
self.events.emit(SIGNAL_SENDING_FAILED, MessageSendingFailure(chatId: rpcResponseObj["chatId"].getStr, error: e.msg))
|
||||||
|
|
||||||
proc requestAddressForTransaction*(self: Service, chatId: string, fromAddress: string, amount: string, tokenAddress: string) =
|
proc requestAddressForTransaction*(self: Service, chatId: string, fromAddress: string, amount: string, tokenAddress: string) =
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -93,3 +93,38 @@ proc installStickerPackTask(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
error "Error installing stickers", message = getCurrentExceptionMsg()
|
error "Error installing stickers", message = getCurrentExceptionMsg()
|
||||||
let tpl: tuple[packId: string, installed: bool] = (arg.packId, installed)
|
let tpl: tuple[packId: string, installed: bool] = (arg.packId, installed)
|
||||||
arg.finish(tpl)
|
arg.finish(tpl)
|
||||||
|
|
||||||
|
type
|
||||||
|
AsyncSendStickerTaskArg = ref object of QObjectTaskArg
|
||||||
|
chatId: string
|
||||||
|
replyTo: string
|
||||||
|
stickerHash: string
|
||||||
|
stickerPackId: string
|
||||||
|
preferredUsername: string
|
||||||
|
|
||||||
|
const asyncSendStickerTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
|
let arg = decode[AsyncSendStickerTaskArg](argEncoded)
|
||||||
|
try:
|
||||||
|
let response = status_chat.sendChatMessage(
|
||||||
|
arg.chatId,
|
||||||
|
"You can see a nice sticker here!",
|
||||||
|
arg.replyTo,
|
||||||
|
ContentType.Sticker.int,
|
||||||
|
arg.preferredUsername,
|
||||||
|
standardLinkPreviews = JsonNode(),
|
||||||
|
statusLinkPreviews = JsonNode(),
|
||||||
|
communityId = "", # communityId is not necessary when sending a sticker
|
||||||
|
arg.stickerHash,
|
||||||
|
arg.stickerPackId,
|
||||||
|
)
|
||||||
|
|
||||||
|
arg.finish(%* {
|
||||||
|
"response": response,
|
||||||
|
"chatId": arg.chatId,
|
||||||
|
"error": "",
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
arg.finish(%* {
|
||||||
|
"error": e.msg,
|
||||||
|
"chatId": arg.chatId,
|
||||||
|
})
|
||||||
|
|
|
@ -345,25 +345,39 @@ QtObject:
|
||||||
except RpcException:
|
except RpcException:
|
||||||
error "Error removing installed sticker", message = getCurrentExceptionMsg()
|
error "Error removing installed sticker", message = getCurrentExceptionMsg()
|
||||||
|
|
||||||
proc sendSticker*(
|
proc asyncSendSticker*(
|
||||||
self: Service,
|
self: Service,
|
||||||
chatId: string,
|
chatId: string,
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
sticker: StickerDto,
|
sticker: StickerDto,
|
||||||
preferredUsername: string) =
|
preferredUsername: string) =
|
||||||
let response = status_chat.sendChatMessage(
|
let arg = AsyncSendStickerTaskArg(
|
||||||
chatId,
|
tptr: asyncSendStickerTask,
|
||||||
"Update to latest version to see a nice sticker here!",
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
replyTo,
|
slot: "onAsyncSendStickerDone",
|
||||||
ContentType.Sticker.int,
|
chatId: chatId,
|
||||||
preferredUsername,
|
replyTo: replyTo,
|
||||||
linkPreviews = @[],
|
stickerHash: sticker.hash,
|
||||||
communityId = "", # communityId is not necessary when sending a sticker
|
stickerPackId: sticker.packId,
|
||||||
sticker.hash,
|
preferredUsername: preferredUsername,
|
||||||
sticker.packId)
|
)
|
||||||
discard self.chatService.processMessengerResponse(response)
|
|
||||||
|
self.threadpool.start(arg)
|
||||||
self.addStickerToRecent(sticker)
|
self.addStickerToRecent(sticker)
|
||||||
|
|
||||||
|
proc onAsyncSendStickerDone*(self: Service, rpcResponseJson: string) {.slot.} =
|
||||||
|
let rpcResponseObj = rpcResponseJson.parseJson
|
||||||
|
try:
|
||||||
|
let errorString = rpcResponseObj{"error"}.getStr()
|
||||||
|
if errorString != "":
|
||||||
|
raise newException(CatchableError, errorString)
|
||||||
|
|
||||||
|
let rpcResponse = Json.decode($rpcResponseObj["response"], RpcResponse[JsonNode])
|
||||||
|
discard self.chatService.processMessengerResponse(rpcResponse)
|
||||||
|
except Exception as e:
|
||||||
|
error "Error sending sticker", msg = e.msg
|
||||||
|
self.events.emit(SIGNAL_SENDING_FAILED, ChatArgs(chatId: rpcResponseObj["chatId"].getStr))
|
||||||
|
|
||||||
proc removeRecentStickers*(self: Service, packId: string) =
|
proc removeRecentStickers*(self: Service, packId: string) =
|
||||||
self.recentStickers.keepItIf(it.packId != packId)
|
self.recentStickers.keepItIf(it.packId != packId)
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@ import json, sequtils, sugar, strutils
|
||||||
import core, ../app_service/common/utils
|
import core, ../app_service/common/utils
|
||||||
import response_type
|
import response_type
|
||||||
import interpret/cropped_image
|
import interpret/cropped_image
|
||||||
import ../app_service/service/message/dto/link_preview
|
|
||||||
import ../app_service/service/message/dto/standard_link_preview
|
|
||||||
import ../app_service/service/message/dto/status_link_preview
|
|
||||||
|
|
||||||
export response_type
|
export response_type
|
||||||
|
|
||||||
|
@ -59,12 +56,12 @@ proc sendChatMessage*(
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
contentType: int,
|
contentType: int,
|
||||||
preferredUsername: string = "",
|
preferredUsername: string = "",
|
||||||
linkPreviews: seq[LinkPreview],
|
standardLinkPreviews: JsonNode,
|
||||||
|
statusLinkPreviews: JsonNode,
|
||||||
communityId: string = "",
|
communityId: string = "",
|
||||||
stickerHash: string = "",
|
stickerHash: string = "",
|
||||||
stickerPack: string = "0",
|
stickerPack: string = "0",
|
||||||
): RpcResponse[JsonNode] =
|
): RpcResponse[JsonNode] =
|
||||||
let (standardLinkPreviews, statusLinkPreviews) = extractLinkPreviewsLists(linkPreviews)
|
|
||||||
result = callPrivateRPC("sendChatMessage".prefix, %* [
|
result = callPrivateRPC("sendChatMessage".prefix, %* [
|
||||||
{
|
{
|
||||||
"chatId": chatId,
|
"chatId": chatId,
|
||||||
|
@ -87,7 +84,7 @@ proc sendImages*(chatId: string,
|
||||||
msg: string,
|
msg: string,
|
||||||
replyTo: string,
|
replyTo: string,
|
||||||
preferredUsername: string,
|
preferredUsername: string,
|
||||||
linkPreviews: seq[LinkPreview],
|
linkPreviews: JsonNode,
|
||||||
): RpcResponse[JsonNode] =
|
): RpcResponse[JsonNode] =
|
||||||
let imagesJson = %* images.map(image => %*
|
let imagesJson = %* images.map(image => %*
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,6 +80,8 @@ Item {
|
||||||
id: d
|
id: d
|
||||||
readonly property var activeChatContentModule: d.getChatContentModule(root.activeChatId)
|
readonly property var activeChatContentModule: d.getChatContentModule(root.activeChatId)
|
||||||
|
|
||||||
|
property bool sendingInProgress: !!d.activeChatContentModule? d.activeChatContentModule.inputAreaModule.sendingInProgress : false
|
||||||
|
|
||||||
readonly property var urlsList: {
|
readonly property var urlsList: {
|
||||||
if (!d.activeChatContentModule) {
|
if (!d.activeChatContentModule) {
|
||||||
return
|
return
|
||||||
|
@ -276,6 +278,7 @@ Item {
|
||||||
&& root.rootStore.sectionDetails.joined
|
&& root.rootStore.sectionDetails.joined
|
||||||
&& !root.rootStore.sectionDetails.amIBanned
|
&& !root.rootStore.sectionDetails.amIBanned
|
||||||
&& root.rootStore.isUserAllowedToSendMessage
|
&& root.rootStore.isUserAllowedToSendMessage
|
||||||
|
&& !d.sendingInProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
store: root.rootStore
|
store: root.rootStore
|
||||||
|
@ -298,6 +301,9 @@ Item {
|
||||||
if (!root.canPost) {
|
if (!root.canPost) {
|
||||||
return qsTr("Sorry, you don't have permissions to post in this channel.")
|
return qsTr("Sorry, you don't have permissions to post in this channel.")
|
||||||
}
|
}
|
||||||
|
if (d.sendingInProgress) {
|
||||||
|
return qsTr("Sending...")
|
||||||
|
}
|
||||||
return root.rootStore.chatInputPlaceHolderText
|
return root.rootStore.chatInputPlaceHolderText
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -86,7 +86,8 @@ Item {
|
||||||
chatLogView.positionViewAtBeginning()
|
chatLogView.positionViewAtBeginning()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSendingMessageFailed() {
|
function onSendingMessageFailed(error) {
|
||||||
|
sendingMsgFailedPopup.error = error
|
||||||
sendingMsgFailedPopup.open()
|
sendingMsgFailedPopup.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,9 +378,11 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageDialog {
|
MessageDialog {
|
||||||
|
property string error
|
||||||
|
|
||||||
id: sendingMsgFailedPopup
|
id: sendingMsgFailedPopup
|
||||||
standardButtons: StandardButton.Ok
|
standardButtons: StandardButton.Ok
|
||||||
text: qsTr("Failed to send message.")
|
text: qsTr("Failed to send message.\n" + error)
|
||||||
icon: StandardIcon.Critical
|
icon: StandardIcon.Critical
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue