From ceb5873272c00c2be93910a16a84d487e49a8838 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Sat, 11 Jul 2020 21:03:39 -0400 Subject: [PATCH] show date headers, and fix sending replies only when they are enabled --- src/app/chat/views/message_list.nim | 20 +++-- .../Chat/ChatColumn/ChatButtons.qml | 2 +- .../AppLayouts/Chat/ChatColumn/ChatInput.qml | 2 +- .../Chat/ChatColumn/ChatMessages.qml | 10 ++- ui/app/AppLayouts/Chat/ChatColumn/Message.qml | 74 ++++++++++++++++--- .../AppLayouts/Chat/ChatColumn/ReplyArea.qml | 6 +- vendor/edn.nim | 1 + 7 files changed, 90 insertions(+), 25 deletions(-) create mode 160000 vendor/edn.nim diff --git a/src/app/chat/views/message_list.nim b/src/app/chat/views/message_list.nim index a7e94b87d1..9559e08cf2 100644 --- a/src/app/chat/views/message_list.nim +++ b/src/app/chat/views/message_list.nim @@ -24,6 +24,7 @@ type OutgoingStatus = UserRole + 13 ResponseTo = UserRole + 14 PlainText = UserRole + 15 + Index = UserRole + 16 QtObject: type @@ -80,6 +81,7 @@ QtObject: of ChatMessageRoles.Id: result = newQVariant(message.id) of ChatMessageRoles.OutgoingStatus: result = newQVariant(message.outgoingStatus) of ChatMessageRoles.ResponseTo: result = newQVariant(message.responseTo) + of ChatMessageRoles.Index: result = newQVariant(index.row) method roleNames(self: ChatMessageList): Table[int, string] = { @@ -97,20 +99,25 @@ QtObject: ChatMessageRoles.SectionIdentifier.int: "sectionIdentifier", ChatMessageRoles.Id.int: "messageId", ChatMessageRoles.OutgoingStatus.int: "outgoingStatus", - ChatMessageRoles.ResponseTo.int: "responseTo" + ChatMessageRoles.ResponseTo.int: "responseTo", + ChatMessageRoles.Index.int: "index" }.toTable proc getMessageIndex(self: ChatMessageList, messageId: string): int {.slot.} = if not self.messageIndex.hasKey(messageId): return -1 result = self.messageIndex[messageId] - proc getReplyData(self: ChatMessageList, index: int, data: string): string {.slot.} = + # TODO: see how to use data() instead of this function + proc getMessageData(self: ChatMessageList, index: int, data: string): string {.slot.} = + if index < 0 or index >= self.messages.len: return ("") + let message = self.messages[index] case data: - of "userName": result = message.alias - of "message": result = message.text - of "identicon": result = message.identicon - else: result = "" + of "userName": result = (message.alias) + of "message": result = (message.text) + of "identicon": result = (message.identicon) + of "timestamp": result = $(message.timestamp) + else: result = ("") proc add*(self: ChatMessageList, message: Message) = if self.messageIndex.hasKey(message.id): return # duplicated msg @@ -141,7 +148,6 @@ QtObject: m.outgoingStatus = "sent" self.dataChanged(topLeft, bottomRight, @[ChatMessageRoles.OutgoingStatus.int]) - proc updateUsernames*(self: ChatMessageList, contacts: seq[Profile]) = let topLeft = self.createIndex(0, 0, nil) let bottomRight = self.createIndex(self.messages.len, 0, nil) diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatButtons.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatButtons.qml index 5d08b6256f..c444ea320a 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatButtons.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ChatButtons.qml @@ -23,7 +23,7 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right onClicked: { - chatsModel.sendMessage(txtData.text, SelectedMessage.messageId) + chatsModel.sendMessage(txtData.text, chatColumn.isReply ? SelectedMessage.messageId : "") txtData.text = "" } background: Rectangle { diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatInput.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatInput.qml index 758b5ba410..2e27ae6a42 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatInput.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ChatInput.qml @@ -34,7 +34,7 @@ Rectangle { if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { if(txtData.text.trim().length > 0){ let msg = interpretMessage(txtData.text.trim()) - chatsModel.sendMessage(msg, SelectedMessage.messageId); + chatsModel.sendMessage(msg, chatColumn.isReply ? SelectedMessage.messageId : ""); txtData.text = ""; event.accepted = true; sendMessageSound.stop() diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml index f818d08895..7e34fe57a9 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml @@ -111,7 +111,7 @@ ScrollView { } model: messageList - Message { + delegate: Message { id: msgDelegate fromAuthor: model.fromAuthor chatId: model.chatId @@ -129,6 +129,14 @@ ScrollView { authorPrevMsg: msgDelegate.ListView.previousSection profileClick: profilePopup.setPopupData.bind(profilePopup) messageId: model.messageId + prevMessageIndex: { + // This is used in order to have access to the previous message and determine the timestamp + // we can't rely on the index because the sequence of messages is not ordered on the nim side + if(msgDelegate.DelegateModel.itemsIndex > 0){ + return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index + } + return -1; + } } } diff --git a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml index 9d89076e82..e5af8f2009 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml @@ -22,6 +22,7 @@ Item { property string outgoingStatus: "" property string responseTo: "" property string messageId: "" + property int prevMessageIndex: -1 property string authorCurrentMsg: "authorCurrentMsg" property string authorPrevMsg: "authorPrevMsg" @@ -32,8 +33,8 @@ Item { property bool isSticker: contentType === Constants.stickerType property int replyMessageIndex: chatsModel.messageList.getMessageIndex(responseTo); - property string repliedMessageAuthor: replyMessageIndex > -1 ? chatsModel.messageList.getReplyData(replyMessageIndex, "userName") : ""; - property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageList.getReplyData(replyMessageIndex, "message") : ""; + property string repliedMessageAuthor: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "userName") : ""; + property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "message") : ""; property var profileClick: function () {} @@ -43,9 +44,9 @@ Item { case Constants.chatIdentifier: return parent.parent.height - 100 case Constants.stickerType: - return stickerId.height + 50 + return stickerId.height + 50 + (dateGroupLbl.visible ? 50 : 0) default: - return (isCurrentUser || (!isCurrentUser && authorCurrentMsg == authorPrevMsg) ? chatBox.height : 24 + chatBox.height) + 20 + return childrenRect.height } } @@ -186,15 +187,64 @@ Item { textFormat: Text.RichText } + StyledText { + id: dateGroupLbl + font.pixelSize: 13 + color: Style.current.darkGrey + horizontalAlignment: Text.AlignHCenter + anchors.horizontalCenter: parent.horizontalCenter + text: { + if (prevMessageIndex == -1) return ""; // identifier + + let now = new Date() + let yesterday = new Date() + yesterday.setDate(now.getDate()-1) + + let prevMsgTimestamp = chatsModel.messageList.getMessageData(prevMessageIndex, "timestamp") + var currentMsgDate = new Date(parseInt(timestamp, 10)); + var prevMsgDate = prevMsgTimestamp === "" ? new Date(0) : new Date(parseInt(prevMsgTimestamp, 10)); + if(currentMsgDate.getDay() !== prevMsgDate.getDay()){ + if (now.toDateString() === currentMsgDate.toDateString()) { + return qsTr("Today") + } else if (yesterday.toDateString() === currentMsgDate.toDateString()) { + //% "Yesterday" + return qsTrId("yesterday") + } else { + const monthNames = [ + qsTr("January"), + qsTr("February"), + qsTr("March"), + qsTr("April"), + qsTr("May"), + qsTr("June"), + qsTr("July"), + qsTr("August"), + qsTr("September"), + qsTr("October"), + qsTr("November"), + qsTr("December") + ]; + return monthNames[currentMsgDate.getMonth()] + ", " + currentMsgDate.getDay() + } + } else { + return ""; + } + + } + anchors.top: parent.top + anchors.topMargin: 20 + visible: text !== "" + } + // Messages Image { id: chatImage width: 36 height: 36 - anchors.topMargin: 20 anchors.left: parent.left anchors.leftMargin: Style.current.padding - anchors.top: parent.top + anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top + anchors.topMargin: 20 fillMode: Image.PreserveAspectFit source: identicon visible: (isMessage || isEmoji) && authorCurrentMsg != authorPrevMsg && !isCurrentUser @@ -217,7 +267,7 @@ Item { id: chatName text: userName anchors.leftMargin: 20 - anchors.top: parent.top + anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top anchors.topMargin: 0 anchors.left: chatImage.right font.bold: true @@ -260,7 +310,7 @@ Item { anchors.leftMargin: !isCurrentUser ? 8 : 0 anchors.right: !isCurrentUser ? undefined : parent.right anchors.rightMargin: !isCurrentUser ? 0 : Style.current.padding - anchors.top: authorCurrentMsg != authorPrevMsg && !isCurrentUser ? chatImage.top : parent.top + anchors.top: authorCurrentMsg != authorPrevMsg && !isCurrentUser ? chatImage.top : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top) anchors.topMargin: 0 visible: isMessage || isEmoji @@ -397,7 +447,7 @@ Item { font.pixelSize: 10 readOnly: true selectByMouse: true - visible: true + visible: (isEmoji || isMessage || isSticker) } @@ -415,13 +465,13 @@ Item { anchors.rightMargin: 5 font.pixelSize: 10 readOnly: true - visible: isCurrentUser + visible: isCurrentUser && (isEmoji || isMessage || isSticker) } - + // This rectangle's only job is to mask the corner to make it less rounded... yep Rectangle { // TODO find a way to show the corner for stickers since they have a border - visible: !isSticker + visible: isMessage || isEmoji color: chatBox.color width: 18 height: 18 diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ReplyArea.qml b/ui/app/AppLayouts/Chat/ChatColumn/ReplyArea.qml index cef2f25f61..cef39079e8 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ReplyArea.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ReplyArea.qml @@ -21,9 +21,9 @@ Rectangle { let replyMessageIndex = chatsModel.messageList.getMessageIndex(SelectedMessage.messageId); if (replyMessageIndex == -1) return; - userName = chatsModel.messageList.getReplyData(replyMessageIndex, "userName") - message = chatsModel.messageList.getReplyData(replyMessageIndex, "message") - identicon = chatsModel.messageList.getReplyData(replyMessageIndex, "identicon") + userName = chatsModel.messageList.getMessageData(replyMessageIndex, "userName") + message = chatsModel.messageList.getMessageData(replyMessageIndex, "message") + identicon = chatsModel.messageList.getMessageData(replyMessageIndex, "identicon") } function reset(){ diff --git a/vendor/edn.nim b/vendor/edn.nim new file mode 160000 index 0000000000..4cda60880e --- /dev/null +++ b/vendor/edn.nim @@ -0,0 +1 @@ +Subproject commit 4cda60880e108f0cb7efe1c209308f2db03267d9