feature(@desktop/chat): support jumping to search result message that is not currently loaded in memory

Crash adding public chat which is caused by changes applied to this feature is fixed.

Fixes: #3005
This commit is contained in:
Sale Djenic 2021-07-29 15:56:01 +02:00 committed by Iuri Matias
parent 5d8b02e057
commit 83d6817f70
9 changed files with 98 additions and 60 deletions

View File

@ -13,6 +13,7 @@ proc handleChatEvents(self: ChatController) =
self.status.events.on("messagesLoaded") do(e:Args):
let evArgs = MsgsLoadedArgs(e)
self.view.onMessagesLoaded(evArgs.messages)
self.view.onMessagesLoaded(msgArgs.chatId, msgArgs.messages)
for statusUpdate in evArgs.statusUpdates:
self.view.communities.updateMemberVisibility(statusUpdate)

View File

@ -438,8 +438,8 @@ QtObject:
let task = RequestMessagesTaskArg( `method`: "requestMoreMessages", chatId: self.channelView.activeChannel.id)
mailserverWorker.start(task)
proc onMessagesLoaded*(self: ChatsView, messages: var seq[Message]) =
self.messageView.onMessagesLoaded(messages)
proc onMessagesLoaded*(self: ChatsView, chatId: string, messages: var seq[Message]) =
self.messageView.onMessagesLoaded(chatId, messages)
proc onSearchMessagesLoaded*(self: ChatsView, messages: seq[Message]) =
self.messageView.onSearchMessagesLoaded(messages)

View File

@ -57,6 +57,8 @@ QtObject:
messageReactions*: Table[string, string]
timedoutMessages: HashSet[string]
userList: UserListView
loadingHistoryMessages: bool
initialMessagesLoaded: bool
proc delete*(self: ChatMessageList) =
self.messages = @[]
@ -81,6 +83,8 @@ QtObject:
proc setup*(self: ChatMessageList, chatId: string, status: Status, addFakeMessages: bool) =
self.messages = @[]
self.id = chatId
self.loadingHistoryMessages = false
self.initialMessagesLoaded = false
if addFakeMessages:
self.addFakeMessages()
@ -97,6 +101,41 @@ QtObject:
new(result, delete)
result.setup(chatId, status, addFakeMessages)
#################################################
# Properties
#################################################
proc loadingHistoryMessagesChanged*(self: ChatMessageList) {.signal.}
proc setLoadingHistoryMessages*(self: ChatMessageList, value: bool) =
if (value == self.loadingHistoryMessages):
return
self.loadingHistoryMessages = value
self.loadingHistoryMessagesChanged()
proc getLoadingHistoryMessages*(self: ChatMessageList): QVariant {.slot.} =
return newQVariant(self.loadingHistoryMessages)
QtProperty[QVariant] loadingHistoryMessages:
read = getLoadingHistoryMessages
notify = loadingHistoryMessagesChanged
proc initialMessagesLoadedChanged*(self: ChatMessageList) {.signal.}
proc setInitialMessagesLoaded*(self: ChatMessageList, value: bool) =
if (value == self.initialMessagesLoaded):
return
self.initialMessagesLoaded = value
self.initialMessagesLoadedChanged()
proc getInitialMessagesLoaded*(self: ChatMessageList): QVariant {.slot.} =
return newQVariant(self.initialMessagesLoaded)
QtProperty[QVariant] initialMessagesLoaded:
read = getInitialMessagesLoaded
notify = initialMessagesLoadedChanged
proc countChanged*(self: ChatMessageList) {.signal.}
proc count*(self: ChatMessageList): int {.slot.} =

View File

@ -18,6 +18,7 @@ logScope:
type
ChatViewRoles {.pure.} = enum
MessageList = UserRole + 1
ChatId
QtObject:
type MessageView* = ref object of QAbstractListModel
@ -33,7 +34,6 @@ QtObject:
unreadDirectMessagesAndMentionsCount: int
channelOpenTime*: Table[string, int64]
searchedMessageId: string
loadingHistoryMessages: bool
proc setup(self: MessageView) = self.QAbstractListModel.setup
proc delete*(self: MessageView) =
@ -59,32 +59,14 @@ QtObject:
result.unreadMessageCnt = 0
result.searchResultMessageModel = newMessageListProxyModel(status)
result.unreadDirectMessagesAndMentionsCount = 0
result.loadingHistoryMessages = false
result.setup
#################################################
# Forward declaration section
#################################################
proc checkIfSearchedMessageIsLoaded(self: MessageView)
#################################################
# Properties
#################################################
proc loadingHistoryMessagesChanged*(self: MessageView) {.signal.}
proc setLoadingHistoryMessages*(self: MessageView, value: bool) =
if (value == self.loadingHistoryMessages):
return
self.loadingHistoryMessages = value
self.loadingHistoryMessagesChanged()
proc getLoadingHistoryMessages*(self: MessageView): QVariant {.slot.} =
return newQVariant(self.loadingHistoryMessages)
QtProperty[QVariant] loadingHistoryMessages:
read = getLoadingHistoryMessages
notify = loadingHistoryMessagesChanged
proc checkIfSearchedMessageIsLoaded(self: MessageView, chatId: string)
proc setLoadingHistoryMessages*(self: MessageView, chatId: string, value: bool)
proc setInitialMessagesLoaded*(self: MessageView, chatId: string, value: bool)
proc replaceMentionsWithPubKeys(self: MessageView, mentions: seq[string], contacts: seq[Profile], message: string, predicate: proc (contact: Profile): string): string =
var updatedMessage = message
@ -286,18 +268,17 @@ QtObject:
proc messagesLoaded*(self: MessageView) {.signal.}
proc loadMoreMessages*(self: MessageView) {.slot.} =
let channelId = self.channelView.activeChannel.id
self.setLoadingHistoryMessages(true)
proc loadMoreMessages*(self: MessageView, channelId: string) {.slot.} =
self.setLoadingHistoryMessages(channelId, true)
self.status.chat.loadMoreMessagesForChannel(channelId)
proc onMessagesLoaded*(self: MessageView, messages: var seq[Message]) =
proc onMessagesLoaded*(self: MessageView, chatId: string, messages: var seq[Message]) =
self.pushMessages(messages)
self.messagesLoaded();
self.setLoadingHistoryMessages(false)
self.messagesLoaded()
self.checkIfSearchedMessageIsLoaded()
self.setInitialMessagesLoaded(chatId, true)
self.setLoadingHistoryMessages(chatId, false)
self.checkIfSearchedMessageIsLoaded(chatId)
proc loadingMessagesChanged*(self: MessageView, value: bool) {.signal.}
@ -432,10 +413,15 @@ QtObject:
return
if index.row < 0 or index.row >= self.messageList.len:
return
return newQVariant(toSeq(self.messageList.values)[index.row])
let chatViewRole = role.ChatViewRoles
case chatViewRole:
of ChatViewRoles.ChatId: result = newQVariant(toSeq(self.messageList.keys)[index.row])
of ChatViewRoles.MessageList: result = newQVariant(toSeq(self.messageList.values)[index.row])
method roleNames(self: MessageView): Table[int, string] =
{
ChatViewRoles.ChatId.int:"chatId",
ChatViewRoles.MessageList.int:"messages"
}.toTable
@ -472,13 +458,15 @@ QtObject:
return message.id != ""
proc loadMessagesTillMessageWithIdIsLoaded*(self: MessageView, messageId: string) {.slot.} =
proc loadMessagesUntillMessageWithIdIsLoaded*(self: MessageView, messageId: string) {.slot.} =
self.searchedMessageId = messageId
self.loadMoreMessages()
let chatId = self.channelView.activeChannel.id
self.loadMoreMessages(chatId)
proc searchedMessageLoaded*(self: MessageView, messageId: string) {.signal.}
proc checkIfSearchedMessageIsLoaded(self: MessageView) =
proc checkIfSearchedMessageIsLoaded(self: MessageView, chatId: string) =
if (self.searchedMessageId.len == 0):
return
@ -486,4 +474,13 @@ QtObject:
self.searchedMessageLoaded(self.searchedMessageId)
self.searchedMessageId = ""
else:
self.loadMoreMessages()
self.loadMoreMessages(chatId)
proc setLoadingHistoryMessages*(self: MessageView, chatId: string, value: bool) =
if self.messageList.hasKey(chatId):
self.messageList[chatId].setLoadingHistoryMessages(value)
proc setInitialMessagesLoaded*(self: MessageView, chatId: string, value: bool) =
if self.messageList.hasKey(chatId):
self.messageList[chatId].setInitialMessagesLoaded(value)

View File

@ -46,6 +46,7 @@ type
active*: bool
MsgsLoadedArgs* = ref object of Args
chatId*: string
messages*: seq[Message]
statusUpdates*: seq[StatusUpdate]
@ -76,10 +77,10 @@ QtObject:
mailserverReady*: bool
contacts*: Table[string, Profile]
channels*: Table[string, Chat]
msgCursor*: Table[string, string]
pinnedMsgCursor*: Table[string, string]
msgCursor: Table[string, string]
pinnedMsgCursor: Table[string, string]
activityCenterCursor*: string
emojiCursor*: Table[string, string]
emojiCursor: Table[string, string]
lastMessageTimestamps*: Table[string, int64]
proc setup(self: ChatModel) =
@ -665,13 +666,22 @@ QtObject:
for jsonMsg in messagesArray:
messages.add(jsonMsg.toMessage())
self.events.emit("searchMessagesLoaded", MsgsLoadedArgs(messages: messages))
self.events.emit("searchMessagesLoaded", MsgsLoadedArgs(chatId: chatId, messages: messages))
proc loadMoreMessagesForChannel*(self: ChatModel, channelId: string) =
if (channelId.len == 0):
info "empty channel id set for fetching more messages"
return
if(not self.msgCursor.hasKey(channelId)):
self.msgCursor[channelId] = ""
if(not self.emojiCursor.hasKey(channelId)):
self.emojiCursor[channelId] = ""
if(not self.pinnedMsgCursor.hasKey(channelId)):
self.pinnedMsgCursor[channelId] = ""
let arg = AsyncFetchChatMessagesTaskArg(
tptr: cast[ByteAddress](asyncFetchChatMessagesTask),
vptr: cast[ByteAddress](self.vptr),
@ -690,19 +700,13 @@ QtObject:
info "empty channel id set for loading initial messages"
return
if(not self.msgCursor.hasKey(channelId)):
self.msgCursor[channelId] = ""
else:
if(self.msgCursor.hasKey(channelId)):
return
if(not self.emojiCursor.hasKey(channelId)):
self.emojiCursor[channelId] = ""
else:
if(self.emojiCursor.hasKey(channelId)):
return
if(not self.pinnedMsgCursor.hasKey(channelId)):
self.pinnedMsgCursor[channelId] = ""
else:
if(self.pinnedMsgCursor.hasKey(channelId)):
return
self.loadMoreMessagesForChannel(channelId)
@ -771,6 +775,6 @@ QtObject:
pinnedMessages.add(msg)
# notify view
self.events.emit("messagesLoaded", MsgsLoadedArgs(messages: messages))
self.events.emit("messagesLoaded", MsgsLoadedArgs(chatId: chatId, messages: messages))
self.events.emit("reactionsLoaded", ReactionsLoadedArgs(reactions: reactions))
self.events.emit("pinnedMessagesLoaded", MsgsLoadedArgs(messages: pinnedMessages))
self.events.emit("pinnedMessagesLoaded", MsgsLoadedArgs(chatId: chatId, messages: pinnedMessages))

View File

@ -308,7 +308,7 @@ Item {
active: stackLayoutChatMessages.currentIndex === index
sourceComponent: ChatMessages {
id: chatMessages
messageList: model.messages
messageList: messages
messageContextMenuInst: MessageContextMenu {
reactionModel: EmojiReactions { }
}

View File

@ -22,7 +22,6 @@ Item {
property alias scrollToMessage: chatLogView.scrollToMessage
property var messageContextMenuInst
property var messageList: MessagesData {}
property real scrollY: chatLogView.visibleArea.yPosition * chatLogView.contentHeight
property int newMessages: 0
property int countOnStartUp: 0
@ -223,10 +222,10 @@ Item {
}
property var loadMsgs : Backpressure.oneInTime(chatLogView, 500, function() {
if(chatsModel.messageView.loadingHistoryMessages)
if(!messages.initialMessagesLoaded || messages.loadingHistoryMessages)
return
chatsModel.messageView.loadMoreMessages();
chatsModel.messageView.loadMoreMessages(chatId);
});
onContentYChanged: {
@ -263,7 +262,7 @@ Item {
function(left, right) { return left.clock > right.clock }
]
model: messageList
model: messages
delegate: Message {
id: msgDelegate

View File

@ -215,7 +215,7 @@ Popup {
if(chatsModel.messageView.isMessageDisplayed(model.messageId))
positionAtMessage(model.messageId)
else
chatsModel.messageView.loadMessagesTillMessageWithIdIsLoaded(model.messageId)
chatsModel.messageView.loadMessagesUntillMessageWithIdIsLoaded(model.messageId)
}
prevMessageIndex: -1

View File

@ -4,7 +4,6 @@ import "../../../../shared"
Rectangle {
property string channel: "status"
property var onJoin: function() {}
border.width: 1
radius: 8
@ -30,7 +29,6 @@ Rectangle {
anchors.fill: parent
onClicked: {
chatsModel.channelView.joinPublicChat(channel);
onJoin()
}
cursorShape: Qt.PointingHandCursor
}