diff --git a/src/app/chat/views/message_list.nim b/src/app/chat/views/message_list.nim index aa6b255e30..ec0dd7c59b 100644 --- a/src/app/chat/views/message_list.nim +++ b/src/app/chat/views/message_list.nim @@ -225,6 +225,7 @@ QtObject: of "timestamp": result = $(message.timestamp) of "image": result = $(message.image) of "contentType": result = $(message.contentType.int) + of "sticker": result = $(message.stickerHash.decodeContentHash()) else: result = ("") proc add*(self: ChatMessageList, message: Message) = diff --git a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml index a6b1bf99cb..9e1dbf786c 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/Message.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/Message.qml @@ -44,14 +44,18 @@ Item { property bool isMessage: isEmoji || isImage || isSticker || isText || isAudio || contentType === Constants.communityInviteType || contentType === Constants.transactionType - property bool isExpired: (outgoingStatus == "sending" && (Math.floor(timestamp) + 180000) < Date.now()) + property bool isExpired: (outgoingStatus === "sending" && (Math.floor(timestamp) + 180000) < Date.now()) property bool isStatusUpdate: false property int replyMessageIndex: chatsModel.messageList.getMessageIndex(responseTo); property string repliedMessageAuthor: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "userName") : ""; + property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "publicKey") : ""; + property bool repliedMessageAuthorIsCurrentUser: replyMessageIndex > -1 ? repliedMessageAuthorPubkey === profileModel.profile.pubKey : ""; property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "message") : ""; property int repliedMessageType: replyMessageIndex > -1 ? parseInt(chatsModel.messageList.getMessageData(replyMessageIndex, "contentType")) : 0; property string repliedMessageImage: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "image") : ""; + property string repliedMessageUserIdenticon: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "identicon") : ""; + property string repliedMessageUserImage: replyMessageIndex > -1 ? appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser , false) || "" : ""; property var imageClick: function () {} property var scrollToBottom: function () {} @@ -106,6 +110,11 @@ Item { if (img) { profileImageSource = img } + } else if (replyMessageIndex > -1 && pubkey === repliedMessageAuthorPubkey) { + const imgReply = appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser, false) + if (imgReply) { + repliedMessageUserImage = imgReply + } } } } diff --git a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatReply.qml b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatReply.qml index 8297b74826..a8c8edab56 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatReply.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatReply.qml @@ -1,4 +1,6 @@ import QtQuick 2.14 +import QtQuick.Shapes 1.13 +import QtGraphicalEffects 1.13 import "../../../../../shared" import "../../../../../imports" @@ -12,6 +14,8 @@ Loader { property var container property int chatHorizontalPadding + property int nameMargin: 6 + id: root active: responseTo != "" && replyMessageIndex > -1 @@ -22,7 +26,18 @@ Loader { id: chatReply // childrenRect.height shows a binding loop for some reason, so we use heights instead - height: lblReplyAuthor.height + ((repliedMessageType === Constants.imageType ? imgReplyImage.height : lblReplyMessage.height) + 5 + 8) + height: { + const h = userImage.height + 2 + if (repliedMessageType === Constants.imageType) { + return h + imgReplyImage.height + } + if (repliedMessageType === Constants.stickerType) { + return h + stickerLoader.height + } + return h + lblReplyMessage.height + } + width: parent.width + clip: true TextMetrics { id: txtAuthorMetrics @@ -30,35 +45,102 @@ Loader { text: lblReplyAuthor.text } + Shape { + id: replyCorner + anchors.left: parent.left + anchors.leftMargin: 20 - 1 + anchors.top: parent.top + anchors.topMargin: Style.current.smallPadding + width: 20 + height: parent.height - anchors.topMargin + asynchronous: true + antialiasing: true + + ShapePath { + id: capTest + + strokeColor: Utils.setColorAlpha(root.elementsColor, 0.4) + strokeWidth: 3 + fillColor: "transparent" + + capStyle: ShapePath.RoundCap + joinStyle: ShapePath.RoundJoin + + startX: 20 + startY: 0 + PathLine { x: 10; y: 0 } + PathArc { + x: 0; y: 10 + radiusX: 13 + radiusY: 13 + direction: PathArc.Counterclockwise + } + PathLine { x: 0; y: chatReply.height - replyCorner.anchors.topMargin } + } + } + + UserImage { + id: userImage + imageHeight: 20 + imageWidth: 20 + active: true + anchors.left: replyCorner.right + anchors.leftMargin: Style.current.halfPadding + identiconImageSource: repliedMessageUserIdenticon + isReplyImage: true + profileImage: repliedMessageUserImage + } + StyledTextEdit { id: lblReplyAuthor - text: "↳" + repliedMessageAuthor + text: repliedMessageAuthor color: root.elementsColor readOnly: true + font.pixelSize: Style.current.secondaryTextFontSize selectByMouse: true - wrapMode: Text.Wrap - anchors.left: parent.left - anchors.right: parent.right + font.weight: Font.Medium + anchors.verticalCenter: userImage.verticalCenter + anchors.left: userImage.right + anchors.leftMargin: 5 } ChatImage { id: imgReplyImage - visible: repliedMessageType == Constants.imageType + visible: repliedMessageType === Constants.imageType imageWidth: 50 imageSource: repliedMessageImage anchors.top: lblReplyAuthor.bottom - anchors.topMargin: 5 - anchors.left: parent.left + anchors.topMargin: nameMargin + anchors.left: userImage.left chatHorizontalPadding: 0 container: root.container + allCornersRounded: true + } + + Loader { + id: stickerLoader + active: repliedMessageType === Constants.stickerType + anchors.top: lblReplyAuthor.bottom + anchors.topMargin: nameMargin + anchors.left: userImage.left + sourceComponent: Component { + Sticker { + id: stickerId + imageHeight: 56 + imageWidth: 56 + stickerData: chatsModel.messageList.getMessageData(replyMessageIndex, "sticker") + contentType: repliedMessageType + container: root.container + } + } } StyledTextEdit { id: lblReplyMessage - visible: repliedMessageType != Constants.imageType + visible: repliedMessageType !== Constants.imageType && repliedMessageType !== Constants.stickerType Component.onCompleted: textFieldImplicitWidth = implicitWidth anchors.top: lblReplyAuthor.bottom - anchors.topMargin: 5 + anchors.topMargin: nameMargin text: `