From cbdc3e61b570862c599d3a274ba78b46db4f5039 Mon Sep 17 00:00:00 2001 From: Boris Melnik Date: Wed, 5 Apr 2023 19:13:41 +0300 Subject: [PATCH] fix(images): Display image placeholder when image from album not loaded Fixes: #9990 --- .../modules/main/activity_center/module.nim | 1 + .../chat_content/messages/module.nim | 4 +++ .../main/chat_section/chat_content/module.nim | 1 + .../modules/shared_models/message_item.nim | 8 ++++++ .../modules/shared_models/message_model.nim | 4 +++ .../service/message/dto/message.nim | 2 ++ test/nim/message_model_test.nim | 1 + .../src/StatusQ/Components/StatusMessage.qml | 27 ++++++++++++++++--- .../Components/StatusMessageDetails.qml | 1 + .../Chat/views/ChatMessagesView.qml | 1 + ui/imports/shared/views/chat/MessageView.qml | 2 ++ 11 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/app/modules/main/activity_center/module.nim b/src/app/modules/main/activity_center/module.nim index 9552796ad3b..9eafc68ead5 100644 --- a/src/app/modules/main/activity_center/module.nim +++ b/src/app/modules/main/activity_center/module.nim @@ -134,6 +134,7 @@ proc createMessageItemFromDto(self: Module, message: MessageDto, communityId: st message.albumId, if (len(message.albumId) == 0): @[] else: @[message.image], if (len(message.albumId) == 0): @[] else: @[message.id], + message.albumImagesCount, )) method convertToItems*( diff --git a/src/app/modules/main/chat_section/chat_content/messages/module.nim b/src/app/modules/main/chat_section/chat_content/messages/module.nim index f926c07c96e..591f2f87b44 100644 --- a/src/app/modules/main/chat_section/chat_content/messages/module.nim +++ b/src/app/modules/main/chat_section/chat_content/messages/module.nim @@ -122,6 +122,7 @@ proc createFetchMoreMessagesItem(self: Module): Item = albumId = "", albumMessageImages = @[], albumMessageIds = @[], + albumImagesCount = 0, ) proc createChatIdentifierItem(self: Module): Item = @@ -180,6 +181,7 @@ proc createChatIdentifierItem(self: Module): Item = albumId = "", albumMessageImages = @[], albumMessageIds = @[], + albumImagesCount = 0, ) proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module) = @@ -296,6 +298,7 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se message.albumId, if (len(message.albumId) == 0): @[] else: @[message.image], if (len(message.albumId) == 0): @[] else: @[message.id], + message.albumImagesCount, ) for r in reactions: @@ -429,6 +432,7 @@ method messagesAdded*(self: Module, messages: seq[MessageDto]) = message.albumId, if (len(message.albumId) == 0): @[] else: @[message.image], if (len(message.albumId) == 0): @[] else: @[message.id], + message.albumImagesCount, ) items.add(item) diff --git a/src/app/modules/main/chat_section/chat_content/module.nim b/src/app/modules/main/chat_section/chat_content/module.nim index 9f8ec787b44..d790fb0c166 100644 --- a/src/app/modules/main/chat_section/chat_content/module.nim +++ b/src/app/modules/main/chat_section/chat_content/module.nim @@ -223,6 +223,7 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy: message.albumId, if (len(message.albumId) == 0): @[] else: @[message.image], if (len(message.albumId) == 0): @[] else: @[message.id], + message.albumImagesCount, ) item.pinned = true item.pinnedBy = actionInitiatedBy diff --git a/src/app/modules/shared_models/message_item.nim b/src/app/modules/shared_models/message_item.nim index 59770c78b2c..97f895b3ff0 100644 --- a/src/app/modules/shared_models/message_item.nim +++ b/src/app/modules/shared_models/message_item.nim @@ -59,6 +59,7 @@ type albumId: string albumMessageImages: seq[string] albumMessageIds: seq[string] + albumImagesCount: int proc initItem*( id, @@ -103,6 +104,7 @@ proc initItem*( albumId: string, albumMessageImages: seq[string], albumMessageIds: seq[string], + albumImagesCount: int, ): Item = result = Item() result.id = id @@ -152,6 +154,7 @@ proc initItem*( result.albumId = albumId result.albumMessageImages = albumMessageImages result.albumMessageIds = albumMessageIds + result.albumImagesCount = albumImagesCount if quotedMessageContentType == ContentType.DiscordMessage.int: result.quotedMessageAuthorDisplayName = quotedMessageDiscordMessage.author.name @@ -226,6 +229,7 @@ proc initNewMessagesMarkerItem*(clock, timestamp: int64): Item = albumId = "", albumMessageImages = @[], albumMessageIds = @[], + albumImagesCount = 0, ) proc `$`*(self: Item): string = @@ -366,6 +370,9 @@ proc albumMessageIds*(self: Item): seq[string] {.inline.} = proc `albumMessageIds=`*(self: Item, value: seq[string]) {.inline.} = self.albumMessageIds = value +proc albumImagesCount*(self: Item): int {.inline.} = + self.albumImagesCount + proc messageContainsMentions*(self: Item): bool {.inline.} = self.messageContainsMentions @@ -491,6 +498,7 @@ proc toJsonNode*(self: Item): JsonNode = "albumId": self.albumId, "albumMessageImages": self.albumMessageImages, "albumMessageIds": self.albumMessageIds, + "albumImagesCount": self.albumImagesCount, } proc editMode*(self: Item): bool {.inline.} = diff --git a/src/app/modules/shared_models/message_model.nim b/src/app/modules/shared_models/message_model.nim index b028f979d32..b3ec9a06859 100644 --- a/src/app/modules/shared_models/message_model.nim +++ b/src/app/modules/shared_models/message_model.nim @@ -62,6 +62,7 @@ type QuotedMessageAuthorIsContact QuotedMessageAuthorColorHash AlbumMessageImages + AlbumImagesCount QtObject: type @@ -163,6 +164,7 @@ QtObject: ModelRole.QuotedMessageAuthorIsContact.int: "quotedMessageAuthorIsContact", ModelRole.QuotedMessageAuthorColorHash.int: "quotedMessageAuthorColorHash", ModelRole.AlbumMessageImages.int: "albumMessageImages", + ModelRole.AlbumImagesCount.int: "albumImagesCount", }.toTable method data(self: Model, index: QModelIndex, role: int): QVariant = @@ -309,6 +311,8 @@ QtObject: result = newQVariant(item.messageAttachments.join(" ")) of ModelRole.AlbumMessageImages: result = newQVariant(item.albumMessageImages.join(" ")) + of ModelRole.AlbumImagesCount: + result = newQVariant(item.albumImagesCount) proc updateItemAtIndex(self: Model, index: int) = let ind = self.createIndex(index, 0, nil) diff --git a/src/app_service/service/message/dto/message.nim b/src/app_service/service/message/dto/message.nim index d388d5b6f20..35783d64a87 100644 --- a/src/app_service/service/message/dto/message.nim +++ b/src/app_service/service/message/dto/message.nim @@ -104,6 +104,7 @@ type MessageDto* = object sticker*: Sticker image*: string albumId*: string + albumImagesCount*: int gapParameters*: GapParameters timestamp*: int64 contentType*: int @@ -224,6 +225,7 @@ proc toMessageDto*(jsonObj: JsonNode): MessageDto = discard jsonObj.getProp("contactRequestState", result.contactRequestState) discard jsonObj.getProp("image", result.image) discard jsonObj.getProp("albumId", result.albumId) + discard jsonObj.getProp("albumImagesCount", result.albumImagesCount) discard jsonObj.getProp("editedAt", result.editedAt) discard jsonObj.getProp("deleted", result.deleted) discard jsonObj.getProp("deletedForMe", result.deletedForMe) diff --git a/test/nim/message_model_test.nim b/test/nim/message_model_test.nim index 9f490198d33..c68d567a6b8 100644 --- a/test/nim/message_model_test.nim +++ b/test/nim/message_model_test.nim @@ -52,6 +52,7 @@ proc createTestMessageItem(id: string, clock: int64): Item = albumId = "", albumMessageImages = @[], albumMessageIds = @[], + albumImagesCount = 0, ) let message0_chatIdentifier = createTestMessageItem("chat-identifier", -2) diff --git a/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml b/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml index 894e7c9b289..37479da6fda 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml @@ -317,14 +317,33 @@ Control { width: messageLayout.width spacing: 9 Repeater { - model: root.messageDetails.album - StatusImageMessage { + model: root.messageDetails.albumCount + Loader { + active: true + property bool imageLoaded: index < root.messageDetails.album.length + property string imagePath: imageLoaded ? root.messageDetails.album[index] : "" + sourceComponent: imageLoaded ? imageComponent : imagePlaceholderComponent + } + + Component { + id: imageComponent + StatusImageMessage { Layout.alignment: Qt.AlignLeft - imageWidth: Math.min(parent.width / root.messageDetails.album.length - 9 * (root.messageDetails.album.length - 1), 144) - source: modelData + imageWidth: Math.min(parent.width / root.messageDetails.albumCount - 9 * (root.messageDetails.albumCount - 1), 144) + source: root.messageDetails.album[index] 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 { diff --git a/ui/StatusQ/src/StatusQ/Components/StatusMessageDetails.qml b/ui/StatusQ/src/StatusQ/Components/StatusMessageDetails.qml index ee6fbc9c787..2a55acf571c 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusMessageDetails.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusMessageDetails.qml @@ -13,4 +13,5 @@ QtObject { property string messageContent: "" property string messageOriginInfo: "" property var album: [] + property int albumCount: 0 } diff --git a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml index 47047b1b9ad..32f3e59e5f7 100644 --- a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml @@ -293,6 +293,7 @@ Item { unparsedText: model.unparsedText messageImage: model.messageImage album: model.albumMessageImages.split(" ") + albumCount: model.albumImagesCount messageTimestamp: model.timestamp messageOutgoingStatus: model.outgoingStatus resendError: model.resendError diff --git a/ui/imports/shared/views/chat/MessageView.qml b/ui/imports/shared/views/chat/MessageView.qml index 05217e192cd..29bde34a0ce 100644 --- a/ui/imports/shared/views/chat/MessageView.qml +++ b/ui/imports/shared/views/chat/MessageView.qml @@ -77,6 +77,7 @@ Loader { property var quotedMessageAuthorDetailsColorHash property var album: [] + property int albumCount: 0 // External behavior changers property bool isInPinnedPopup: false // The pinned popup limits the number of buttons shown @@ -586,6 +587,7 @@ Loader { return ""; } album: root.album + albumCount: root.albumCount amISender: root.amISender sender.id: root.senderIsEnsVerified ? "" : Utils.getCompressedPk(root.senderId)