feat(image-album): Display album of images in replies

Fixes: #9957
This commit is contained in:
Boris Melnik 2023-04-27 15:35:16 +03:00
parent cdbdae2d39
commit df88984b45
9 changed files with 117 additions and 81 deletions

View File

@ -297,59 +297,13 @@ Control {
Loader { Loader {
active: true active: true
sourceComponent: messageDetails.album.length > 1 ? albumComp : imageComp sourceComponent: StatusMessageImageAlbum {
} width: messageLayout.width
album: root.messageDetails.albumCount > 0 ? root.messageDetails.album : [root.messageDetails.messageContent]
} albumCount: root.messageDetails.albumCount > 0 ? root.messageDetails.albumCount : 1
imageWidth: Math.min(messageLayout.width / root.messageDetails.albumCount - 9 * (root.messageDetails.albumCount - 1), 144)
Component { shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
id: imageComp onImageClicked: root.imageClicked(image, mouse, imageSource)
StatusImageMessage {
source: root.messageDetails.messageContent
onClicked: root.imageClicked(image, mouse, imageSource)
shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
}
}
Component {
id: albumComp
RowLayout {
width: messageLayout.width
spacing: 9
Repeater {
model: root.messageDetails.albumCount
delegate: Loader {
active: true
readonly property bool imageLoaded: index < root.messageDetails.album.length
readonly property string imagePath: imageLoaded ? root.messageDetails.album[index] : ""
sourceComponent: imageLoaded ? imageComponent : imagePlaceholderComponent
}
}
Component {
id: imageComponent
StatusImageMessage {
Layout.alignment: Qt.AlignLeft
imageWidth: Math.min(messageLayout.width / root.messageDetails.albumCount - 9 * (root.messageDetails.albumCount - 1), 144)
source: imagePath
onClicked: root.imageClicked(image, mouse, imageSource)
shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
}
}
Component {
id: imagePlaceholderComponent
LoadingComponent {
radius: 4
height: 194
width: 144
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
} }
} }
} }

View File

@ -0,0 +1,4 @@
module StatusQ.Components.private
StatusImageMessage 0.1 statusMessage/StatusImageMessage.qml
StatusMessageImageAlbum 0.1 statusMessage/StatusMessageImageAlbum.qml

View File

@ -0,0 +1,57 @@
import QtQuick 2.15
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
RowLayout {
id: root
property var album: []
property int albumCount: 0
property real imageWidth: 144
property int shapeType: -1
property real loadingComponentHeight: 194
signal imageClicked(var image, var mouse, var imageSource)
spacing: 9
Repeater {
model: root.albumCount
delegate: Loader {
active: true
readonly property bool imageLoaded: index < root.album.length
readonly property string imagePath: imageLoaded ? root.album[index] : ""
sourceComponent: imageLoaded ? imageComponent : imagePlaceholderComponent
}
}
Component {
id: imageComponent
StatusImageMessage {
Layout.alignment: Qt.AlignLeft
imageWidth: root.imageWidth
source: imagePath
onClicked: root.imageClicked(image, mouse, imageSource)
shapeType: root.shapeType
}
}
Component {
id: imagePlaceholderComponent
LoadingComponent {
radius: 4
height: root.loadingComponentHeight
width: root.imageWidth
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}

View File

@ -106,19 +106,25 @@ Item {
messageDetails: root.replyDetails messageDetails: root.replyDetails
} }
} }
Loader { Loader {
Layout.fillWidth: true Layout.fillWidth: true
asynchronous: true asynchronous: true
active: replyDetails.contentType === StatusMessage.ContentType.Image active: replyDetails.contentType === StatusMessage.ContentType.Image
visible: active visible: active
sourceComponent: StatusImageMessage { sourceComponent: StatusMessageImageAlbum {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: imageAlias.paintedHeight Layout.preferredHeight: 56
album: replyDetails.albumCount > 0 ? replyDetails.album : [replyDetails.messageContent]
albumCount: replyDetails.albumCount > 0 ? replyDetails.albumCount : 1
imageWidth: 56 imageWidth: 56
source: replyDetails.messageContent loadingComponentHeight: 56
shapeType: StatusImageMessage.ShapeType.ROUNDED shapeType: StatusImageMessage.ShapeType.ROUNDED
} }
} }
StatusSticker { StatusSticker {
asynchronous: true asynchronous: true
active: replyDetails.contentType === StatusMessage.ContentType.Sticker active: replyDetails.contentType === StatusMessage.ContentType.Sticker

View File

@ -3,13 +3,16 @@
<file>StatusQ/Components/private/statusMessage/StatusAudioMessage.qml</file> <file>StatusQ/Components/private/statusMessage/StatusAudioMessage.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusEditMessage.qml</file> <file>StatusQ/Components/private/statusMessage/StatusEditMessage.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusImageMessage.qml</file> <file>StatusQ/Components/private/statusMessage/StatusImageMessage.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusMessageQuickActions.qml</file> <file>StatusQ/Components/private/statusMessage/StatusMessageImageAlbum.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusMessageQuickActions.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusMessageReply.qml</file> <file>StatusQ/Components/private/statusMessage/StatusMessageReply.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusPinMessageDetails.qml</file> <file>StatusQ/Components/private/statusMessage/StatusPinMessageDetails.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusSticker.qml</file> <file>StatusQ/Components/private/statusMessage/StatusSticker.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusTextMessage.qml</file> <file>StatusQ/Components/private/statusMessage/StatusTextMessage.qml</file>
<file>StatusQ/Components/private/statusMessage/StatusTimeStampLabel.qml</file> <file>StatusQ/Components/private/statusMessage/StatusTimeStampLabel.qml</file>
<file>StatusQ/Components/qmldir</file> <file>StatusQ/Components/qmldir</file>
<file>StatusQ/Components/private/qmldir</file>
<file>StatusQ/Components/StatusAddress.qml</file> <file>StatusQ/Components/StatusAddress.qml</file>
<file>StatusQ/Components/StatusAddressPanel.qml</file> <file>StatusQ/Components/StatusAddressPanel.qml</file>
<file>StatusQ/Components/StatusAnimatedImage.qml</file> <file>StatusQ/Components/StatusAnimatedImage.qml</file>

View File

@ -152,7 +152,7 @@ ColumnLayout {
return return
} }
if (inputAreaLoader.item) { if (inputAreaLoader.item) {
inputAreaLoader.item.chatInput.showReplyArea(messageId, obj.senderDisplayName, obj.messageText, obj.contentType, obj.messageImage, obj.sticker) inputAreaLoader.item.chatInput.showReplyArea(messageId, obj.senderDisplayName, obj.messageText, obj.contentType, obj.messageImage, obj.albumMessageImages, obj.albumImagesCount, obj.sticker)
} }
} }
} }
@ -187,7 +187,7 @@ ColumnLayout {
return return
} }
if (inputAreaLoader.item) { if (inputAreaLoader.item) {
inputAreaLoader.item.chatInput.showReplyArea(messageId, obj.senderDisplayName, obj.messageText, obj.contentType, obj.messageImage, obj.sticker) inputAreaLoader.item.chatInput.showReplyArea(messageId, obj.senderDisplayName, obj.messageText, obj.contentType, obj.messageImage, obj.albumMessageImages, obj.albumImagesCount, obj.sticker)
} }
} }
onOpenStickerPackPopup: { onOpenStickerPackPopup: {

View File

@ -930,7 +930,7 @@ Rectangle {
return false return false
} }
function showReplyArea(messageId, userName, message, contentType, image, sticker) { function showReplyArea(messageId, userName, message, contentType, image, album, albumCount, sticker) {
isReply = true isReply = true
replyArea.userName = userName replyArea.userName = userName
replyArea.message = message replyArea.message = message
@ -938,6 +938,8 @@ Rectangle {
replyArea.image = image replyArea.image = image
replyArea.stickerData = sticker replyArea.stickerData = sticker
replyArea.messageId = messageId replyArea.messageId = messageId
replyArea.album = album
replyArea.albumCount = albumCount
messageInputField.forceActiveFocus(); messageInputField.forceActiveFocus();
} }

View File

@ -7,6 +7,7 @@ import shared.panels 1.0
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils import StatusQ.Core.Utils 0.1 as StatusQUtils
import StatusQ.Components.private 0.1
Rectangle { Rectangle {
id: root id: root
@ -26,6 +27,8 @@ Rectangle {
property string stickerData: "" property string stickerData: ""
property string messageId: "" property string messageId: ""
property int contentType: -1 property int contentType: -1
property var album: []
property int albumCount: 0
signal closeButtonClicked() signal closeButtonClicked()
@ -73,16 +76,16 @@ Rectangle {
} }
} }
StatusChatImage { StatusMessageImageAlbum {
id: imageThumbnail id: imageThumbnail
anchors.left: replyToUsername.left anchors.left: replyToUsername.left
anchors.top: replyToUsername.bottom anchors.top: replyToUsername.bottom
anchors.topMargin: 2 anchors.topMargin: 2
imageWidth: 64 album: root.albumCount > 0 ? root.album : [root.image]
imageSource: root.image albumCount: root.albumCount > 0 ? root.albumCount : 1
chatHorizontalPadding: 0 imageWidth: 56
visible: root.contentType === Constants.messageContentType.imageType loadingComponentHeight: 56
playing: false shapeType: StatusImageMessage.ShapeType.ROUNDED
} }
StatusSticker { StatusSticker {

View File

@ -608,30 +608,37 @@ Loader {
} }
replyDetails: StatusMessageDetails { replyDetails: StatusMessageDetails {
readonly property var responseMessage: contentType === StatusMessage.ContentType.Sticker || contentType === StatusMessage.ContentType.Image
? root.messageStore.getMessageByIdAsJson(responseToMessageWithId)
: null
onResponseMessageChanged: {
if (!responseMessage)
return
switch (contentType) {
case StatusMessage.ContentType.Sticker:
messageContent = responseMessage.sticker;
return
case StatusMessage.ContentType.Image:
messageContent = responseMessage.messageImage;
albumCount = responseMessage.albumImagesCount
album = responseMessage.albumMessageImages
return
default:
messageContent = ""
}
}
messageText: { messageText: {
if (root.quotedMessageDeleted) { if (root.quotedMessageDeleted) {
return qsTr("Message deleted") return qsTr("Message deleted")
} }
if (!root.quotedMessageText) { if (!root.quotedMessageText && contentType !== StatusMessage.ContentType.Image) {
return qsTr("Unknown message. Try fetching more messages") return qsTr("Unknown message. Try fetching more messages")
} }
return root.quotedMessageText return root.quotedMessageText
} }
contentType: d.convertContentType(root.quotedMessageContentType) contentType: d.convertContentType(root.quotedMessageContentType)
messageContent: {
if (contentType !== StatusMessage.ContentType.Sticker && contentType !== StatusMessage.ContentType.Image) {
return ""
}
let message = root.messageStore.getMessageByIdAsJson(responseToMessageWithId)
switch (contentType) {
case StatusMessage.ContentType.Sticker:
return message.sticker;
case StatusMessage.ContentType.Image:
return message.messageImage;
}
return "";
}
amISender: root.quotedMessageFrom === userProfile.pubKey amISender: root.quotedMessageFrom === userProfile.pubKey
sender.id: root.quotedMessageFrom sender.id: root.quotedMessageFrom
sender.isContact: quotedMessageAuthorDetailsIsContact sender.isContact: quotedMessageAuthorDetailsIsContact