Use section identifiers as a way to identify if messages have been sent by the current user (no need to modify the model with `repeatMessageInfo`)

This commit is contained in:
Richard Ramos 2020-06-05 18:20:45 -04:00 committed by Iuri Matias
parent 4fe6d9b767
commit 9d75f6f552
7 changed files with 68 additions and 45 deletions

View File

@ -31,15 +31,14 @@ proc delete*(self: ChatController) =
proc handleChatEvents(self: ChatController) =
# Display already saved messages
self.status.events.on("messagesLoaded") do(e:Args):
for message in MsgsLoadedArgs(e).messages:
self.view.pushMessage(message.chatId, message.toChatMessage())
self.view.pushMessages(MsgsLoadedArgs(e).messages)
self.status.events.on("messageSent") do(e: Args):
var sentMessage = MsgArgs(e)
var chatMessage = sentMessage.payload.toChatMessage()
chatMessage.message = sentMessage.message
chatMessage.isCurrentUser = true
self.view.pushMessage(sentMessage.chatId, chatMessage)
self.view.pushMessage(chatMessage)
self.status.events.on("channelJoined") do(e: Args):
var channelMessage = ChannelArgs(e)
@ -69,13 +68,10 @@ proc init*(self: ChatController) =
self.status.mailservers.init()
self.status.chat.init()
proc handleMessage(self: ChatController, data: MessageSignal) =
for c in data.chats:
self.view.updateChat(c.toChatItem())
for message in data.messages:
self.view.pushMessage(message.localChatId, message.toChatMessage())
self.view.pushMessages(data.messages)
proc handleDiscoverySummary(self: ChatController, data: DiscoverySummarySignal) =
## Handle mailserver peers being added and removed

View File

@ -50,6 +50,7 @@ QtObject:
let selectedChannel = self.chats.getChannel(index)
if self.activeChannel.id == selectedChannel.id: return
self.activeChannel.setChatItem(selectedChannel)
self.status.chat.setActiveChannel(selectedChannel.id)
self.activeChannelChanged()
proc getActiveChannelIdx(self: ChatsView): QVariant {.slot.} =
@ -77,9 +78,14 @@ QtObject:
if not self.messageList.hasKey(channel):
self.messageList[channel] = newChatMessageList()
proc pushMessage*(self:ChatsView, channel: string, message: ChatMessage) =
self.upsertChannel(channel)
self.messageList[channel].add(message)
proc pushMessage*(self:ChatsView, message: ChatMessage) =
self.upsertChannel(message.chatId)
self.messageList[message.chatId].add(message)
proc pushMessages*(self:ChatsView, messages: seq[Message]) =
for msg in messages:
self.upsertChannel(msg.chatId)
self.messageList[msg.chatId].add(msg.toChatMessage())
proc getMessageList(self: ChatsView): QVariant {.slot.} =
self.upsertChannel(self.activeChannel.id)

View File

@ -8,11 +8,10 @@ type
Timestamp = UserRole + 3
Identicon = UserRole + 4
IsCurrentUser = UserRole + 5
RepeatMessageInfo = UserRole + 6
ContentType = UserRole + 7
Sticker = UserRole + 8
FromAuthor = UserRole + 9
Clock = UserRole + 10
ContentType = UserRole + 6
Sticker = UserRole + 7
FromAuthor = UserRole + 8
Clock = UserRole + 9
QtObject:
type
ChatMessageList* = ref object of QAbstractListModel
@ -41,7 +40,6 @@ QtObject:
if index.row < 0 or index.row >= self.messages.len:
return
let message = self.messages[index.row]
let repeatMessageInfo = (index.row == 0) or message.fromAuthor != self.messages[index.row - 1].fromAuthor
let chatMessageRole = role.ChatMessageRoles
case chatMessageRole:
of ChatMessageRoles.UserName: result = newQVariant(message.userName)
@ -50,7 +48,6 @@ QtObject:
of ChatMessageRoles.Clock: result = newQVariant($message.clock)
of ChatMessageRoles.Identicon: result = newQVariant(message.identicon)
of ChatMessageRoles.IsCurrentUser: result = newQVariant(message.isCurrentUser)
of ChatMessageRoles.RepeatMessageInfo: result = newQVariant(repeatMessageInfo)
of ChatMessageRoles.ContentType: result = newQVariant(message.contentType)
of ChatMessageRoles.Sticker: result = newQVariant(message.sticker)
of ChatMessageRoles.FromAuthor: result = newQVariant(message.fromAuthor)
@ -63,7 +60,6 @@ QtObject:
ChatMessageRoles.Clock.int:"clock",
ChatMessageRoles.Identicon.int:"identicon",
ChatMessageRoles.IsCurrentUser.int:"isCurrentUser",
ChatMessageRoles.RepeatMessageInfo.int:"repeatMessageInfo",
ChatMessageRoles.ContentType.int:"contentType",
ChatMessageRoles.Sticker.int:"sticker",
ChatMessageRoles.FromAuthor.int:"fromAuthor"
@ -73,3 +69,10 @@ QtObject:
self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len)
self.messages.add(message)
self.endInsertRows()
proc add*(self: ChatMessageList, messages: seq[ChatMessage]) =
self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len)
for message in messages:
self.messages.add(message)
self.endInsertRows()

View File

@ -108,6 +108,9 @@ proc leave*(self: ChatModel, chatId: string) =
self.events.emit("channelLeft", ChannelArgs(channel: chatId))
self.events.emit("activeChannelChanged", ChannelArgs(channel: self.getActiveChannel()))
proc setActiveChannel*(self: ChatModel, chatId: string) =
self.events.emit("activeChannelChanged", ChannelArgs(channel: chatId))
proc sendMessage*(self: ChatModel, chatId: string, msg: string): string =
var sentMessage = status_chat.sendChatMessage(chatId, msg)
var parsedMessage = parseJson(sentMessage)["result"]["chats"][0]["lastMessage"]

View File

@ -12,6 +12,7 @@ type ChatMessage* = ref object
isCurrentUser*: bool
contentType*: int
sticker*: string
chatId*: string
proc delete*(self: ChatMessage) =
discard
@ -27,9 +28,11 @@ proc newChatMessage*(): ChatMessage =
result.isCurrentUser = false
result.contentType = 1
result.sticker = ""
result.chatId = ""
proc toChatMessage*(payload: JsonNode): ChatMessage =
result = ChatMessage(
chatId: payload["chatId"].str,
userName: payload["alias"].str,
message: payload["text"].str,
timestamp: $payload["timestamp"],
@ -42,6 +45,7 @@ proc toChatMessage*(payload: JsonNode): ChatMessage =
proc toChatMessage*(message: Message): ChatMessage =
result = ChatMessage(
chatId: message.chatId,
userName: message.alias,
clock: message.clock,
fromAuthor: message.fromAuthor,

View File

@ -22,10 +22,6 @@ ScrollView {
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
function scrollToBottom(goToBottom) {
chatLogView.positionViewAtEnd();
}
ListView {
anchors.fill: parent
spacing: 4
@ -33,26 +29,26 @@ ScrollView {
Layout.fillWidth: true
Layout.fillHeight: true
onCountChanged: {
scrollToBottom();
if (!this.atYEnd) {
// User has scrolled up, we don't want to scroll back
return
}
Qt.callLater( chatLogView.positionViewAtEnd )
}
model: messageListDelegate
section.property: "userName"
section.criteria: ViewSection.FullString
}
DelegateModel {
id: messageListDelegate
model: messageList
delegate: Message {
userName: model.userName
message: model.message
identicon: model.identicon
isCurrentUser: model.isCurrentUser
repeatMessageInfo: model.repeatMessageInfo
timestamp: model.timestamp
sticker: model.sticker
contentType: model.contentType
}
property var lessThan: [
function(left, right) { return left.clock < right.clock }
]
property var lessThan: function(left, right) { return left.clock < right.clock }
property int sortOrder: 0
onSortOrderChanged: items.setGroups(0, items.count, "unsorted")
function insertPosition(lessThan, item) {
var lower = 0
@ -73,23 +69,37 @@ ScrollView {
while (unsortedItems.count > 0) {
var item = unsortedItems.get(0)
var index = insertPosition(lessThan, item)
item.groups = "items"
items.move(item.itemsIndex, index)
}
}
items.includeByDefault: false
groups: DelegateModelGroup {
id: unsortedItems
name: "unsorted"
includeByDefault: true
onChanged: {
messageListDelegate.sort(messageListDelegate.lessThan)
scrollToBottom();
if (messageListDelegate.sortOrder == messageListDelegate.lessThan.length)
setGroups(0, count, "items")
else {
messageListDelegate.sort(messageListDelegate.lessThan[messageListDelegate.sortOrder])
}
}
}
model: messageList
delegate: Message {
id: msgDelegate
userName: model.userName
message: model.message
identicon: model.identicon
isCurrentUser: model.isCurrentUser
timestamp: model.timestamp
sticker: model.sticker
contentType: model.contentType
authorCurrentMsg: msgDelegate.ListView.section
authorPrevMsg: msgDelegate.ListView.previousSection
}
}
}

View File

@ -12,14 +12,15 @@ Item {
property string message: "That's right. We're friends... Of justice, that is."
property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
property bool isCurrentUser: false
property bool repeatMessageInfo: true
property int timestamp: 1234567
property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v"
property int contentType: 1 // constants don't work in default props
width: parent.width
height: contentType == Constants.stickerType ? stickerId.height : (isCurrentUser || (!isCurrentUser && !repeatMessageInfo) ? chatBox.height : 24 + chatBox.height)
property string authorCurrentMsg: "authorCurrentMsg"
property string authorPrevMsg: "authorPrevMsg"
width: parent.width
height: contentType == Constants.stickerType ? stickerId.height + 50 : (isCurrentUser || (!isCurrentUser && authorCurrentMsg == authorPrevMsg) ? chatBox.height : 24 + chatBox.height)
ProfilePopup {
id: profilePopup
}
@ -34,7 +35,7 @@ Item {
anchors.top: parent.top
fillMode: Image.PreserveAspectFit
source: identicon
visible: repeatMessageInfo && !isCurrentUser
visible: authorCurrentMsg != authorPrevMsg && !isCurrentUser
MouseArea {
cursorShape: Qt.PointingHandCursor
@ -57,7 +58,7 @@ Item {
readOnly: true
wrapMode: Text.WordWrap
selectByMouse: true
visible: repeatMessageInfo && !isCurrentUser
visible: authorCurrentMsg != authorPrevMsg && !isCurrentUser
}
Rectangle {
@ -74,7 +75,7 @@ Item {
anchors.leftMargin: !isCurrentUser ? 8 : 0
anchors.right: !isCurrentUser ? undefined : parent.right
anchors.rightMargin: !isCurrentUser ? 0 : Theme.padding
anchors.top: repeatMessageInfo && !isCurrentUser ? chatImage.top : parent.top
anchors.top: authorCurrentMsg != authorPrevMsg && !isCurrentUser ? chatImage.top : parent.top
anchors.topMargin: 0
// Thi`s rectangle's only job is to mask the corner to make it less rounded... yep