Fix oversize padding on captioned images/videos (#3732)

* Fix oversize padding on captioned images/videos

Use consistent padding with the InReplyToView for the media, and
consistent caption padding with other textual messages.

Signed-off-by: Joe Groocock <me@frebib.net>

* Update screenshots

---------

Signed-off-by: Joe Groocock <me@frebib.net>
Co-authored-by: Jorge Martín <jorgem@element.io>
Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Joe Groocock
2024-10-29 16:34:09 +00:00
committed by GitHub
parent 0e4ef9fc0a
commit b4ccd5801d
44 changed files with 127 additions and 99 deletions

View File

@@ -0,0 +1,14 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.features.messages.impl.timeline.components
enum class ContentPadding {
Textual,
Media,
CaptionedMedia
}

View File

@@ -522,32 +522,33 @@ private fun MessageEventBubbleContent(
fun CommonLayout(
timestampPosition: TimestampPosition,
showThreadDecoration: Boolean,
paddingBehaviour: ContentPadding,
inReplyToDetails: InReplyToDetails?,
modifier: Modifier = Modifier,
canShrinkContent: Boolean = false,
) {
val timestampLayoutModifier: Modifier
val contentModifier: Modifier
when {
inReplyToDetails != null -> {
if (timestampPosition == TimestampPosition.Overlay) {
timestampLayoutModifier = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp)
contentModifier = Modifier.clip(RoundedCornerShape(12.dp))
val timestampLayoutModifier =
if (inReplyToDetails != null && timestampPosition == TimestampPosition.Overlay) {
Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp)
} else {
Modifier
}
val topPadding = if (inReplyToDetails != null) 0.dp else 8.dp
val contentModifier = when (paddingBehaviour) {
ContentPadding.Textual ->
Modifier.padding(start = 12.dp, end = 12.dp, top = topPadding, bottom = 8.dp)
ContentPadding.Media -> {
if (inReplyToDetails == null) {
Modifier
} else {
contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp)
timestampLayoutModifier = Modifier
Modifier.clip(RoundedCornerShape(10.dp))
}
}
timestampPosition != TimestampPosition.Overlay -> {
timestampLayoutModifier = Modifier
contentModifier = Modifier
.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp)
}
else -> {
timestampLayoutModifier = Modifier
contentModifier = Modifier
}
ContentPadding.CaptionedMedia ->
Modifier.padding(start = 8.dp, end = 8.dp, top = topPadding, bottom = 8.dp)
}
val threadDecoration = @Composable {
if (showThreadDecoration) {
ThreadDecoration(modifier = Modifier.padding(top = 8.dp, start = 12.dp, end = 12.dp))
@@ -601,9 +602,17 @@ private fun MessageEventBubbleContent(
is TimelineItemPollContent -> TimestampPosition.Below
else -> TimestampPosition.Default
}
val paddingBehaviour = when (event.content) {
is TimelineItemImageContent -> if (event.content.showCaption) ContentPadding.CaptionedMedia else ContentPadding.Media
is TimelineItemVideoContent -> if (event.content.showCaption) ContentPadding.CaptionedMedia else ContentPadding.Media
is TimelineItemStickerContent,
is TimelineItemLocationContent -> ContentPadding.Media
else -> ContentPadding.Textual
}
CommonLayout(
showThreadDecoration = event.isThreaded,
timestampPosition = timestampPosition,
paddingBehaviour = paddingBehaviour,
inReplyToDetails = event.inReplyTo,
canShrinkContent = event.content is TimelineItemVoiceContent,
modifier = bubbleModifier.semantics(mergeDescendants = true) {

View File

@@ -50,7 +50,9 @@ internal fun TimelineItemEventRowWithReplyContentToPreview(
isMine = it,
timelineItemReactions = aTimelineItemReactions(count = 0),
content = aTimelineItemImageContent(
aspectRatio = 2.5f
aspectRatio = 2.5f,
filename = "image.jpg",
caption = "A reply with an image.",
),
inReplyTo = inReplyToDetails,
displayNameAmbiguous = displayNameAmbiguous,

View File

@@ -69,9 +69,7 @@ fun TimelineItemImageView(
modifier = modifier.semantics { contentDescription = description },
) {
val containerModifier = if (content.showCaption) {
Modifier
.padding(top = 6.dp)
.clip(RoundedCornerShape(6.dp))
Modifier.clip(RoundedCornerShape(10.dp))
} else {
Modifier
}
@@ -119,6 +117,7 @@ fun TimelineItemImageView(
val aspectRatio = content.aspectRatio ?: DEFAULT_ASPECT_RATIO
EditorStyledText(
modifier = Modifier
.padding(horizontal = 4.dp) // This is (12.dp - 8.dp) contentPadding from CommonLayout
.widthIn(min = MIN_HEIGHT_IN_DP.dp * aspectRatio, max = MAX_HEIGHT_IN_DP.dp * aspectRatio),
text = caption,
style = ElementRichTextEditorStyle.textStyle(),

View File

@@ -137,6 +137,7 @@ fun TimelineItemVideoView(
val aspectRatio = content.aspectRatio ?: DEFAULT_ASPECT_RATIO
EditorStyledText(
modifier = Modifier
.padding(horizontal = 4.dp) // This is (12.dp - 8.dp) contentPadding from CommonLayout
.widthIn(min = MIN_HEIGHT_IN_DP.dp * aspectRatio, max = MAX_HEIGHT_IN_DP.dp * aspectRatio),
text = caption,
style = ElementRichTextEditorStyle.textStyle(),

View File

@@ -12,6 +12,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.collections.immutable.toImmutableList
import java.text.DateFormat
import java.util.Date
import java.util.TimeZone
open class AggregatedReactionProvider : PreviewParameterProvider<AggregatedReaction> {
override val values: Sequence<AggregatedReaction>
@@ -29,7 +30,9 @@ fun anAggregatedReaction(
count: Int = 1,
isHighlighted: Boolean = false,
): AggregatedReaction {
val timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, java.util.Locale.US)
val timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, java.util.Locale.US).apply {
timeZone = TimeZone.getTimeZone("UTC")
}
val date = Date(1_689_061_264L)
val senders = buildList {
repeat(count) { index ->