From 7b8ede03bc9ffde664589ad03a7e596c2b4c42d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Mar 2021 20:09:53 +0100 Subject: [PATCH 1/2] Picture preview when replying. Also add the image preview in the message detail bottomsheet (#2916) --- CHANGES.md | 1 + .../BottomSheetMessagePreviewItem.kt | 13 ++++ .../home/room/detail/RoomDetailFragment.kt | 13 ++++ .../action/MessageActionsEpoxyController.kt | 7 +++ .../image/ImageContentRendererFactory.kt | 63 +++++++++++++++++++ .../src/main/res/layout/composer_layout.xml | 7 +++ ...composer_layout_constraint_set_compact.xml | 9 +++ ...omposer_layout_constraint_set_expanded.xml | 21 +++++-- .../item_bottom_sheet_message_preview.xml | 16 ++++- 9 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt diff --git a/CHANGES.md b/CHANGES.md index d2ba5babec..9bfc5a59a4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Improvements 🙌: - Crypto improvement | Bulk send NO_OLM withheld code - Display the room shield in all room setting screens - Improve message with Emoji only detection (#3017) + - Picture preview when replying. Also add the image preview in the message detail bottomsheet (#2916) Bugfix 🐛: - Fix bad theme change for the MainActivity diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index a323ce995b..2f7c22e4b4 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -19,6 +19,7 @@ package im.vector.app.core.epoxy.bottomsheet import android.text.method.MovementMethod import android.widget.ImageView import android.widget.TextView +import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R @@ -27,6 +28,7 @@ import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess +import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.util.MatrixItem /** @@ -44,6 +46,12 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel(R.id.bottom_sheet_message_preview_sender) val body by bind(R.id.bottom_sheet_message_preview_body) val timestamp by bind(R.id.bottom_sheet_message_preview_timestamp) + val imagePreview by bind(R.id.bottom_sheet_message_preview_image) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index a80aeb65b0..64bffcb49c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -98,6 +98,7 @@ import im.vector.app.core.ui.views.FailedMessagesWarningView import im.vector.app.core.ui.views.JumpToReadMarkerView import im.vector.app.core.ui.views.NotificationAreaView import im.vector.app.core.utils.Debouncer +import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.KeyboardStateUtils import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES import im.vector.app.core.utils.TextUtils @@ -137,6 +138,7 @@ import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBot import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider +import im.vector.app.features.home.room.detail.timeline.image.buildImageContentRendererData import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem @@ -223,6 +225,7 @@ class RoomDetailFragment @Inject constructor( private val eventHtmlRenderer: EventHtmlRenderer, private val vectorPreferences: VectorPreferences, private val colorProvider: ColorProvider, + private val dimensionConverter: DimensionConverter, private val notificationUtils: NotificationUtils, private val matrixItemColorProvider: MatrixItemColorProvider, private val imageContentRenderer: ImageContentRenderer, @@ -873,6 +876,15 @@ class RoomDetailFragment @Inject constructor( } views.composerLayout.views.composerRelatedMessageContent.text = (formattedBody ?: nonFormattedBody) + // Image Event + val data = event.buildImageContentRendererData(dimensionConverter.dpToPx(66)) + val isImageVisible = if (data != null) { + imageContentRenderer.render(data, ImageContentRenderer.Mode.THUMBNAIL, views.composerLayout.views.composerRelatedMessageImage) + true + } else { + false + } + updateComposerText(defaultContent) views.composerLayout.views.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), iconRes)) @@ -884,6 +896,7 @@ class RoomDetailFragment @Inject constructor( if (isAdded) { // need to do it here also when not using quick reply focusComposerAndShowKeyboard() + views.composerLayout.views.composerRelatedMessageImage.isVisible = isImageVisible } } focusComposerAndShowKeyboard() diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 4e1492aaba..30587e6659 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -29,11 +29,14 @@ import im.vector.app.core.epoxy.bottomsheet.bottomSheetQuickReactionsItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetSendStateItem import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.resources.StringProvider +import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.TimelineEventController +import im.vector.app.features.home.room.detail.timeline.image.buildImageContentRendererData import im.vector.app.features.home.room.detail.timeline.item.E2EDecoration import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod import im.vector.app.features.home.room.detail.timeline.tools.linkify +import im.vector.app.features.media.ImageContentRenderer import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.send.SendState import javax.inject.Inject @@ -45,6 +48,8 @@ class MessageActionsEpoxyController @Inject constructor( private val stringProvider: StringProvider, private val avatarRenderer: AvatarRenderer, private val fontProvider: EmojiCompatFontProvider, + private val imageContentRenderer: ImageContentRenderer, + private val dimensionConverter: DimensionConverter, private val dateFormatter: VectorDateFormatter ) : TypedEpoxyController() { @@ -59,6 +64,8 @@ class MessageActionsEpoxyController @Inject constructor( avatarRenderer(avatarRenderer) matrixItem(state.informationData.matrixItem) movementMethod(createLinkMovementMethod(listener)) + imageContentRenderer(imageContentRenderer) + data(state.timelineEvent()?.buildImageContentRendererData(dimensionConverter.dpToPx(66))) userClicked { listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) } body(state.messageBody.linkify(listener)) time(formattedDate) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt new file mode 100644 index 0000000000..7ff184f664 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.detail.timeline.image + +import im.vector.app.features.media.ImageContentRenderer +import org.matrix.android.sdk.api.session.events.model.isImageMessage +import org.matrix.android.sdk.api.session.events.model.isVideoMessage +import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent +import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent +import org.matrix.android.sdk.api.session.room.model.message.getFileUrl +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent +import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt + +fun TimelineEvent.buildImageContentRendererData(maxHeight: Int): ImageContentRenderer.Data? { + return when { + root.isImageMessage() -> root.getClearContent().toModel() + ?.let { messageImageContent -> + ImageContentRenderer.Data( + eventId = eventId, + filename = messageImageContent.body, + mimeType = messageImageContent.mimeType, + url = messageImageContent.getFileUrl(), + elementToDecrypt = messageImageContent.encryptedFileInfo?.toElementToDecrypt(), + height = messageImageContent.info?.height, + maxHeight = maxHeight, + width = messageImageContent.info?.width, + maxWidth = maxHeight * 2, + allowNonMxcUrls = false + ) + } + root.isVideoMessage() -> root.getClearContent().toModel() + ?.let { messageVideoContent -> + ImageContentRenderer.Data( + eventId = eventId, + filename = messageVideoContent.body, + mimeType = messageVideoContent.mimeType, + url = messageVideoContent.getFileUrl(), + elementToDecrypt = messageVideoContent.encryptedFileInfo?.toElementToDecrypt(), + height = messageVideoContent.videoInfo?.height, + maxHeight = maxHeight, + width = messageVideoContent.videoInfo?.width, + maxWidth = maxHeight * 2, + allowNonMxcUrls = false + ) + } + else -> null + } +} diff --git a/vector/src/main/res/layout/composer_layout.xml b/vector/src/main/res/layout/composer_layout.xml index 0db905d015..e837d2d80b 100644 --- a/vector/src/main/res/layout/composer_layout.xml +++ b/vector/src/main/res/layout/composer_layout.xml @@ -68,6 +68,13 @@ app:tint="?riotx_text_primary" tools:ignore="MissingConstraints,MissingPrefix" /> + + + + + - diff --git a/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml b/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml index 5fbed68955..afd96d5690 100644 --- a/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml +++ b/vector/src/main/res/layout/item_bottom_sheet_message_preview.xml @@ -50,6 +50,20 @@ app:layout_constraintEnd_toEndOf="parent" tools:text="Friday 8pm" /> + + From 5136979352ef32f4c22c600fb09cfed036477024 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Mar 2021 18:33:06 +0100 Subject: [PATCH 2/2] Cleanup on unbinding Valere's review --- .../core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index 2f7c22e4b4..5ff7a07e3c 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -77,6 +77,11 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel(R.id.bottom_sheet_message_preview_avatar) val sender by bind(R.id.bottom_sheet_message_preview_sender)