From 55466416d6b7fa51af38eb87764aa888e7e22b25 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Tue, 19 Jan 2021 13:06:06 -0400 Subject: [PATCH] fix: initial load of messages and reactions done on a separate thread --- src/app/chat/event_handling.nim | 3 +-- src/app/chat/view.nim | 17 +++++++++++++++++ src/status/chat.nim | 32 ++++++++++++++++++++++++++++++++ src/status/libstatus/chat.nim | 30 ++++++++++++++++-------------- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/app/chat/event_handling.nim b/src/app/chat/event_handling.nim index 7b0ccc3e9b..dcfce697b9 100644 --- a/src/app/chat/event_handling.nim +++ b/src/app/chat/event_handling.nim @@ -48,8 +48,7 @@ proc handleChatEvents(self: ChatController) = # Do not add community chats to the normal chat list elif channel.chat.chatType != ChatType.Profile and channel.chat.chatType != status_chat.ChatType.CommunityChat: discard self.view.chats.addChatItemToList(channel.chat) - self.status.chat.chatMessages(channel.chat.id) - self.status.chat.chatReactions(channel.chat.id) + self.view.asyncMessageLoad(channel.chat.id) self.status.events.on("chatsLoaded") do(e:Args): self.view.calculateUnreadMessages() diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index 9b96590511..667f1b8ceb 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -5,6 +5,8 @@ import ../../status/libstatus/chat as libstatus_chat import ../../status/libstatus/accounts/constants import ../../status/libstatus/mailservers as status_mailservers import ../../status/libstatus/types +import ../../status/libstatus/core +import ../../status/libstatus/chat as core_chat import ../../status/libstatus/utils as status_utils import ../../status/accounts as status_accounts import ../../status/chat as status_chat @@ -447,6 +449,21 @@ QtObject: proc loadingMessagesChanged*(self: ChatsView, value: bool) {.signal.} + proc asyncMessageLoad*(self: ChatsView, chatId: string) {.slot.} = + spawnAndSend(self, "asyncMessageLoaded") do: # Call self.ensResolved(string) when ens is resolved + $(%*{ + "chatId": chatId, + "messages": callPrivateRPC("chatMessages".prefix, %* [chatId, "", 20]).parseJson()["result"], + "reactions": callPrivateRPC("emojiReactionsByChatID".prefix, %* [chatId, "", 20]).parseJson()["result"] + }) + + proc asyncMessageLoaded*(self: ChatsView, rpcResponse: string) {.slot.} = + let rpcResponseObj = rpcResponse.parseJson + let chatMessages = parseChatMessagesResponse(rpcResponseObj["chatId"].getStr, rpcResponseObj["messages"]) + let reactions = parseReactionsResponse(rpcResponseObj["chatId"].getStr, rpcResponseObj["reactions"]) + self.status.chat.chatMessages(rpcResponseObj["chatId"].getStr, true, chatMessages[0], chatMessages[1]) + self.status.chat.chatReactions(rpcResponseObj["chatId"].getStr, true, reactions[0], reactions[1]) + proc hideLoadingIndicator*(self: ChatsView) {.slot.} = self.loadingMessages = false self.loadingMessagesChanged(false) diff --git a/src/status/chat.nim b/src/status/chat.nim index 89fb05d085..636fbbd01a 100644 --- a/src/status/chat.nim +++ b/src/status/chat.nim @@ -266,6 +266,38 @@ proc chatMessages*(self: ChatModel, chatId: string, initialLoad:bool = true) = self.events.emit("messagesLoaded", MsgsLoadedArgs(messages: messageTuple[1])) + +proc chatMessages*(self: ChatModel, chatId: string, initialLoad:bool = true, cursor: string = "", messages: seq[Message]) = + if not self.msgCursor.hasKey(chatId): + self.msgCursor[chatId] = ""; + + # Messages were already loaded, since cursor will + # be nil/empty if there are no more messages + if(not initialLoad and self.msgCursor[chatId] == ""): return + + self.msgCursor[chatId] = cursor + + if messages.len > 0: + let lastMsgIndex = messages.len - 1 + let ts = times.convert(Milliseconds, Seconds, messages[lastMsgIndex].whisperTimestamp.parseInt()) + self.lastMessageTimestamps[chatId] = ts + + self.events.emit("messagesLoaded", MsgsLoadedArgs(messages: messages)) + +proc chatReactions*(self: ChatModel, chatId: string, initialLoad:bool = true, cursor: string = "", reactions: seq[Reaction]) = + try: + if not self.emojiCursor.hasKey(chatId): + self.emojiCursor[chatId] = ""; + + # Messages were already loaded, since cursor will + # be nil/empty if there are no more messages + if(not initialLoad and self.emojiCursor[chatId] == ""): return + + self.emojiCursor[chatId] = cursor; + self.events.emit("reactionsLoaded", ReactionsLoadedArgs(reactions: reactions)) + except Exception as e: + error "Error reactions", msg = e.msg + proc chatReactions*(self: ChatModel, chatId: string, initialLoad:bool = true) = try: if not self.emojiCursor.hasKey(chatId): diff --git a/src/status/libstatus/chat.nim b/src/status/libstatus/chat.nim index ca246e7df5..2e7baf78f5 100644 --- a/src/status/libstatus/chat.nim +++ b/src/status/libstatus/chat.nim @@ -55,8 +55,14 @@ proc loadChats*(): seq[Chat] = result.add(chat) result.sort(sortChats) -proc chatMessages*(chatId: string, cursor: string = ""): (string, seq[Message]) = +proc parseChatMessagesResponse*(chatId: string, rpcResult: JsonNode): (string, seq[Message]) = var messages: seq[Message] = @[] + if rpcResult["messages"].kind != JNull: + for jsonMsg in rpcResult["messages"]: + messages.add(jsonMsg.toMessage) + return (rpcResult{"cursor"}.getStr, messages) + +proc chatMessages*(chatId: string, cursor: string = ""): (string, seq[Message]) = var cursorVal: JsonNode if cursor == "": @@ -64,16 +70,17 @@ proc chatMessages*(chatId: string, cursor: string = ""): (string, seq[Message]) else: cursorVal = newJString(cursor) - let rpcResult = parseJson(callPrivateRPC("chatMessages".prefix, %* [chatId, cursorVal, 20]))["result"] - if rpcResult["messages"].kind != JNull: - for jsonMsg in rpcResult["messages"]: - messages.add(jsonMsg.toMessage) - - return (rpcResult{"cursor"}.getStr, messages) + let callRPCResult = parseJson(callPrivateRPC("chatMessages".prefix, %* [chatId, cursorVal, 20]))["result"] + return parseChatMessagesResponse(chatId, callRPCResult) +proc parseReactionsResponse*(chatId: string, rpcResult: JsonNode): (string, seq[Reaction]) = + var reactions: seq[Reaction] = @[] + if rpcResult != nil and rpcResult.kind != JNull and rpcResult.len != 0: + for jsonMsg in rpcResult: + reactions.add(jsonMsg.toReaction) + return (rpcResult{"cursor"}.getStr, reactions) proc getEmojiReactionsByChatId*(chatId: string, cursor: string = ""): (string, seq[Reaction]) = - var reactions: seq[Reaction] = @[] var cursorVal: JsonNode if cursor == "": @@ -82,12 +89,7 @@ proc getEmojiReactionsByChatId*(chatId: string, cursor: string = ""): (string, s cursorVal = newJString(cursor) let rpcResult = parseJson(callPrivateRPC("emojiReactionsByChatID".prefix, %* [chatId, cursorVal, 20]))["result"] - - if rpcResult != nil and rpcResult.len != 0: - for jsonMsg in rpcResult: - reactions.add(jsonMsg.toReaction) - - return (rpcResult{"cursor"}.getStr, reactions) + return parseReactionsResponse(chatId, rpcResult) proc addEmojiReaction*(chatId: string, messageId: string, emojiId: int): seq[Reaction] = let rpcResult = parseJson(callPrivateRPC("sendEmojiReaction".prefix, %* [chatId, messageId, emojiId]))["result"]