Rich replies also when replying via media

Change-Id: I3352fe0a6c4b0c08a7564337b02d1cc8e5e4bbc4
This commit is contained in:
SpiritCroc 2022-11-20 16:20:40 +01:00
parent d8ac4f53d7
commit 15d8a916b1
14 changed files with 142 additions and 52 deletions

View file

@ -65,4 +65,9 @@
<item name="closeIconTint">?vctr_content_secondary</item>
</style>
<style name="InReplyToViewParams">
<item name="android:layout_marginTop">4dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:visibility">gone</item>
</style>
</resources>

View file

@ -202,11 +202,11 @@ class MessageItemFactory @Inject constructor(
is MessageImageInfoContent -> buildImageMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessageFileContent -> buildFileMessageItem(messageContent, highlight, attributes)
is MessageAudioContent -> buildAudioContent(params, messageContent, informationData, highlight, attributes)
is MessageFileContent -> buildFileMessageItem(messageContent, highlight, callback, attributes)
is MessageAudioContent -> buildAudioContent(params, messageContent, informationData, highlight, callback, attributes)
is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes)
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, callback, attributes)
is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(params.event, highlight, attributes)
is MessageVoiceBroadcastInfoContent -> voiceBroadcastItemFactory.create(params, messageContent, highlight, attributes)
else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
@ -220,6 +220,7 @@ class MessageItemFactory @Inject constructor(
locationContent: MessageLocationContent,
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
): MessageLocationItem? {
val width = timelineMediaSizeProvider.getMaxSize().first
@ -240,6 +241,9 @@ class MessageItemFactory @Inject constructor(
.locationPinProvider(locationPinProvider)
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun buildPollItem(
@ -262,6 +266,9 @@ class MessageItemFactory @Inject constructor(
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.callback(callback)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun createPollQuestion(
@ -279,6 +286,7 @@ class MessageItemFactory @Inject constructor(
messageContent: MessageAudioContent,
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes
): MessageAudioItem {
val fileUrl = getAudioFileUrl(messageContent, informationData)
@ -300,6 +308,9 @@ class MessageItemFactory @Inject constructor(
.contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder)
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun getAudioFileUrl(
@ -328,6 +339,7 @@ class MessageItemFactory @Inject constructor(
messageContent: MessageAudioContent,
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes
): MessageVoiceItem? {
// Do not display voice broadcast messages
@ -361,6 +373,9 @@ class MessageItemFactory @Inject constructor(
.contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder)
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun buildVerificationRequestMessageItem(
@ -409,6 +424,7 @@ class MessageItemFactory @Inject constructor(
private fun buildFileMessageItem(
messageContent: MessageFileContent,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
): MessageFileItem {
val mxcUrl = messageContent.getFileUrl() ?: ""
@ -424,6 +440,9 @@ class MessageItemFactory @Inject constructor(
.filename(messageContent.getFileName())
.caption(messageContent.getCaption())
.iconRes(R.drawable.ic_paperclip)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun buildAudioContent(
@ -431,11 +450,12 @@ class MessageItemFactory @Inject constructor(
messageContent: MessageAudioContent,
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
) = if (messageContent.voiceMessageIndicator != null) {
buildVoiceMessageItem(params, messageContent, informationData, highlight, attributes)
buildVoiceMessageItem(params, messageContent, informationData, highlight, callback, attributes)
} else {
buildAudioMessageItem(params, messageContent, informationData, highlight, attributes)
buildAudioMessageItem(params, messageContent, informationData, highlight, callback, attributes)
}
private fun buildNotHandledMessageItem(
@ -481,6 +501,9 @@ class MessageItemFactory @Inject constructor(
.contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
.playable(playable)
.highlighted(highlight)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
.mediaData(data)
.apply {
if (messageContent.msgType == MessageType.MSGTYPE_STICKER_LOCAL) {
@ -543,6 +566,9 @@ class MessageItemFactory @Inject constructor(
.contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
.playable(true)
.highlighted(highlight)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
.mediaData(thumbnailData)
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view.findViewById(R.id.messageThumbnailView)) }
}
@ -604,14 +630,14 @@ class MessageItemFactory @Inject constructor(
.markwonPlugins(htmlRenderer.get().plugins)
.searchForPills(isFormatted)
.previewUrlRetriever(callback?.getPreviewUrlRetriever())
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
.imageContentRenderer(imageContentRenderer)
.previewUrlCallback(callback)
.leftGuideline(avatarSizeProvider.leftGuideline)
.attributes(attributes)
.highlighted(highlight)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun annotateWithEdited(
@ -705,8 +731,6 @@ class MessageItemFactory @Inject constructor(
return MessageTextItem_()
.leftGuideline(avatarSizeProvider.leftGuideline)
.previewUrlRetriever(callback?.getPreviewUrlRetriever())
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
.imageContentRenderer(imageContentRenderer)
.previewUrlCallback(callback)
.attributes(attributes)
@ -714,6 +738,8 @@ class MessageItemFactory @Inject constructor(
.bindingOptions(bindingOptions)
.highlighted(highlight)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun buildEmoteMessageItem(
@ -740,13 +766,13 @@ class MessageItemFactory @Inject constructor(
.bindingOptions(bindingOptions)
.leftGuideline(avatarSizeProvider.leftGuideline)
.previewUrlRetriever(callback?.getPreviewUrlRetriever())
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
.imageContentRenderer(imageContentRenderer)
.previewUrlCallback(callback)
.attributes(attributes)
.highlighted(highlight)
.movementMethod(createLinkMovementMethod(callback))
.replyPreviewRetriever(callback?.getReplyPreviewRetriever())
.inReplyToClickCallback(callback)
}
private fun MessageContentWithFormattedBody.getHtmlBody(): CharSequence {

View file

@ -49,6 +49,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVerification
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.hasBeenEdited
import org.matrix.android.sdk.api.session.room.timeline.isReply
import timber.log.Timber
import javax.inject.Inject
@ -169,6 +170,7 @@ class MessageInformationDataFactory @Inject constructor(
senderPowerLevel = senderPowerLevel,
isDirect = isEffectivelyDirect,
isPublic = roomSummary?.isPublic ?: false,
isReply = event.isReply(),
dmChatPartnerId = dmOtherMemberId,
isFirstFromThisSender = isFirstFromThisSender,
isLastFromThisSender = isLastFromThisSender,

View file

@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail.timeline.item
import android.content.Context
import android.graphics.Typeface
import android.text.method.MovementMethod
import android.view.View
import android.widget.ImageView
import android.widget.ProgressBar
@ -37,6 +38,9 @@ import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
import im.vector.app.features.home.room.detail.timeline.reply.PreviewReplyUiState
import im.vector.app.features.home.room.detail.timeline.reply.ReplyPreviewRetriever
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.home.room.detail.timeline.view.ScMessageBubbleWrapView
import im.vector.app.features.home.room.detail.timeline.view.TimelineMessageLayoutRenderer
@ -55,6 +59,8 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
@LayoutRes layoutId: Int = R.layout.item_timeline_event_base
) : AbsBaseMessageItem<H>(layoutId) {
private val replyViewUpdater = ReplyViewUpdater()
override val baseAttributes: AbsBaseMessageItem.Attributes
get() = attributes
@ -65,6 +71,15 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
@EpoxyAttribute
lateinit var attributes: Attributes
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var movementMethod: MovementMethod? = null
@EpoxyAttribute
var replyPreviewRetriever: ReplyPreviewRetriever? = null
@EpoxyAttribute
var inReplyToClickCallback: TimelineEventController.InReplyToClickCallback? = null
private val _avatarClickListener = object : ClickListener {
override fun invoke(p1: View) {
attributes.avatarCallback?.onAvatarClicked(attributes.informationData)
@ -140,6 +155,18 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
updateHighlightedMessageHeight(holder, false)
}
}
// Replies
if (holder.replyToView != null) {
replyViewUpdater.replyView = holder.replyToView
val safeReplyPreviewRetriever = replyPreviewRetriever
if (safeReplyPreviewRetriever == null) {
holder.replyToView?.isVisible = false
} else {
safeReplyPreviewRetriever.addListener(attributes.informationData.eventId, replyViewUpdater)
}
holder.replyToView?.delegate = inReplyToClickCallback
}
}
private fun updateHighlightedMessageHeight(holder: Holder, isExpanded: Boolean) {
@ -160,6 +187,8 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
holder.memberNameView.setOnLongClickListener(null)
attributes.avatarRenderer.clear(holder.threadSummaryAvatarImageView)
holder.threadSummaryConstraintLayout.setOnClickListener(null)
replyPreviewRetriever?.removeListener(attributes.informationData.eventId, replyViewUpdater)
replyViewUpdater.replyView = null
super.unbind(holder)
}
@ -172,6 +201,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
val timeView by bind<TextView>(R.id.messageTimeView)
val sendStateImageView by bind<SendStateImageView>(R.id.messageSendStateImageView)
val eventSendingIndicator by bind<ProgressBar>(R.id.eventSendingIndicator)
val replyToView: InReplyToView? by lazy { view.findViewById(R.id.inReplyToContainer) }
val threadSummaryConstraintLayout by bind<ConstraintLayout>(R.id.messageThreadSummaryConstraintLayout)
val threadSummaryCounterTextView by bind<TextView>(R.id.messageThreadSummaryCounterTextView)
val threadSummaryAvatarImageView by bind<ImageView>(R.id.messageThreadSummaryAvatarImageView)
@ -237,6 +267,16 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder>(
)
}
inner class ReplyViewUpdater : ReplyPreviewRetriever.PreviewReplyRetrieverListener {
var replyView: InReplyToView? = null
override fun onStateUpdated(state: PreviewReplyUiState) {
replyPreviewRetriever?.let {
replyView?.render(state, it, attributes.informationData, movementMethod, coroutineScope)
}
}
}
override fun ignoreMessageGuideline(context: Context): Boolean {
val messageLayout = attributes.informationData.messageLayout as? TimelineMessageLayout.ScBubble ?: return false
return infoInBubbles(messageLayout) && canHideAvatars(attributes)

View file

@ -145,6 +145,8 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
private fun hasCaption() = !mediaData.caption.isNullOrBlank()
private fun needsRealBubble() = hasCaption() || attributes.informationData.isReply
override fun unbind(holder: Holder) {
GlideApp.with(holder.view.context.applicationContext).clear(holder.imageView)
imageContentRenderer.clear(holder.imageView)
@ -211,7 +213,7 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
}
override fun getScBubbleMargin(resources: Resources): Int {
if (hasCaption()) {
if (needsRealBubble()) {
return super.getScBubbleMargin(resources)
}
return 0
@ -238,7 +240,7 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
when {
// Don't show it for non-bubble layouts, don't show for Stickers, ...
// Also only supported for default corner radius
!(messageLayout.isRealBubble || messageLayout.isPseudoBubble) || hasCaption() || mode != ImageContentRenderer.Mode.THUMBNAIL -> {
!(messageLayout.isRealBubble || messageLayout.isPseudoBubble) || needsRealBubble() || mode != ImageContentRenderer.Mode.THUMBNAIL -> {
holder.mediaContentView.background = null
}
attributes.informationData.sentByMe -> {

View file

@ -42,6 +42,7 @@ data class MessageInformationData(
val readReceiptAnonymous: AnonymousReadReceipt,
val isDirect: Boolean,
val isPublic: Boolean,
val isReply: Boolean,
val senderPowerLevel: Int?,
val dmChatPartnerId: String?,
val e2eDecoration: E2EDecoration = E2EDecoration.NONE,

View file

@ -60,12 +60,6 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
@EpoxyAttribute
var useBigFont: Boolean = false
@EpoxyAttribute
var replyPreviewRetriever: ReplyPreviewRetriever? = null
@EpoxyAttribute
var inReplyToClickCallback: TimelineEventController.InReplyToClickCallback? = null
@EpoxyAttribute
var previewUrlRetriever: PreviewUrlRetriever? = null
@ -75,14 +69,14 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
@EpoxyAttribute
var imageContentRenderer: ImageContentRenderer? = null
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var movementMethod: MovementMethod? = null
// SC: moved to super
//@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
//var movementMethod: MovementMethod? = null
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var markwonPlugins: (List<MarkwonPlugin>)? = null
private val previewUrlViewUpdater = PreviewUrlViewUpdater()
private val replyViewUpdater = ReplyViewUpdater()
// Remember footer measures for URL updates
private var footerWidth: Int = 0
@ -107,15 +101,6 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
holder.previewUrlView.delegate = previewUrlCallback
holder.previewUrlView.renderMessageLayout(attributes.informationData.messageLayout)
replyViewUpdater.replyView = holder.replyToView
val safeReplyPreviewRetriever = replyPreviewRetriever
if (safeReplyPreviewRetriever == null) {
holder.replyToView.isVisible = false
} else {
safeReplyPreviewRetriever.addListener(attributes.informationData.eventId, replyViewUpdater)
}
holder.replyToView.delegate = inReplyToClickCallback
if (useBigFont) {
holder.messageView.textSize = 44F
} else {
@ -155,7 +140,6 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
previewUrlViewUpdater.previewUrlView = null
previewUrlViewUpdater.imageContentRenderer = null
previewUrlRetriever?.removeListener(attributes.informationData.eventId, previewUrlViewUpdater)
replyPreviewRetriever?.removeListener(attributes.informationData.eventId, replyViewUpdater)
}
override fun getViewStubId() = STUB_ID
@ -164,7 +148,6 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
val messageView by bind<FooteredTextView>(R.id.messageTextView)
val previewUrlViewElement by bind<PreviewUrlView>(R.id.messageUrlPreviewElement)
val previewUrlViewSc by bind<PreviewUrlViewSc>(R.id.messageUrlPreviewSc)
val replyToView by bind<InReplyToView>(R.id.inReplyToContainer)
lateinit var previewUrlView: AbstractPreviewUrlView // set to either previewUrlViewElement or previewUrlViewSc by layout
}
@ -197,17 +180,6 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
}
}
inner class ReplyViewUpdater : ReplyPreviewRetriever.PreviewReplyRetrieverListener {
var replyView: InReplyToView? = null
override fun onStateUpdated(state: PreviewReplyUiState) {
timber.log.Timber.i("REPLY STATE UPDATE $replyPreviewRetriever $replyView")
replyPreviewRetriever?.let {
replyView?.render(state, it, attributes.informationData, movementMethod, coroutineScope)
}
}
}
override fun allowFooterOverlay(holder: Holder, bubbleWrapView: ScMessageBubbleWrapView): Boolean {
return true

View file

@ -28,6 +28,7 @@ import im.vector.app.features.themes.BubbleThemeUtils
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageNoticeContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent
@ -36,6 +37,7 @@ import org.matrix.android.sdk.api.session.room.model.message.getCaption
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
import org.matrix.android.sdk.api.session.room.timeline.isEdition
import org.matrix.android.sdk.api.session.room.timeline.isReply
import org.matrix.android.sdk.api.session.room.timeline.isRootThread
import javax.inject.Inject
@ -208,9 +210,10 @@ class TimelineMessageLayoutFactory @Inject constructor(
}
}
private fun MessageContent?.isPseudoBubble(event: TimelineEvent): Boolean {
private fun MessageContent?.isPseudoBubble(event: TimelineEvent, ignoreReply: Boolean = false): Boolean {
if (this == null) return false
if (event.root.isRedacted()) return false
if (!ignoreReply && event.isReply()) return false
if (this is MessageWithAttachmentContent && !getCaption().isNullOrBlank()) return false
return this.msgType in MSG_TYPES_WITH_PSEUDO_BUBBLE_LAYOUT
}
@ -242,6 +245,7 @@ class TimelineMessageLayoutFactory @Inject constructor(
val type = root.getClearType()
if (type in EVENT_TYPES_WITH_BUBBLE_LAYOUT) {
val messageContent = getVectorLastMessageContent()
if (messageContent.isPseudoBubble(this, true)) return true
return messageContent?.msgType !in MSG_TYPES_WITHOUT_BUBBLE_LAYOUT
}
return false

View file

@ -604,7 +604,7 @@ fun setFlatRtl(layout: ViewGroup, direction: Int, childDirection: Int, depth: In
}
// Static to use from classes that use simplified/non-sc layouts, e.g. item_timeline_event_base_noinfo
fun renderStubMessageLayout(messageLayout: TimelineMessageLayout, viewStubContainer: FrameLayout) {
fun renderStubMessageLayout(messageLayout: TimelineMessageLayout, viewStubContainer: View) {
if (messageLayout !is TimelineMessageLayout.ScBubble) {
return
}

View file

@ -9,6 +9,13 @@
android:minWidth="@dimen/chat_bubble_fixed_size"
tools:viewBindingIgnore="true">
<im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
android:id="@+id/inReplyToContainer"
style="@style/InReplyToViewParams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:visibility="visible" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/messageMainInnerLayout"
style="@style/TimelineContentMediaPillStyle"

View file

@ -9,6 +9,13 @@
android:orientation="vertical"
tools:viewBindingIgnore="true">
<im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
android:id="@+id/inReplyToContainer"
style="@style/InReplyToViewParams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:visibility="visible" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/messageFileMainLayout"
style="@style/TimelineContentMediaPillStyle"

View file

@ -5,15 +5,28 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
android:id="@+id/inReplyToContainer"
style="@style/InReplyToViewParams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<!-- Size will be overrode -->
<ImageView
android:id="@+id/staticMapImageView"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_marginTop="8dp"
app:layout_goneMarginTop="0dp"
android:contentDescription="@string/a11y_static_map_image"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@id/inReplyToContainer"
tools:src="@tools:sample/backgrounds/scenic" />
<ImageView

View file

@ -6,15 +6,28 @@
android:layout_height="wrap_content"
tools:viewBindingIgnore="true">
<im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
android:id="@+id/inReplyToContainer"
style="@style/InReplyToViewParams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<ImageView
android:id="@+id/messageThumbnailView"
android:layout_width="375dp"
android:layout_height="0dp"
android:contentDescription="@string/a11y_image"
android:layout_marginTop="8dp"
app:layout_goneMarginTop="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@id/inReplyToContainer"
tools:layout_height="300dp"
tools:src="@tools:sample/backgrounds/scenic" />
@ -57,6 +70,6 @@
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/messageTextView"
app:layout_constraintTop_toBottomOf="@id/messageCaptionView"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -10,11 +10,9 @@
<im.vector.app.features.home.room.detail.timeline.reply.InReplyToView
android:id="@+id/inReplyToContainer"
style="@style/InReplyToViewParams"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:visibility="gone"
tools:visibility="visible" />
<!-- Layout gravity left: fixes long display name pills moving text out: