Iterate on extra padding solution.
This commit is contained in:
parent
659d719456
commit
884aea1c80
10 changed files with 148 additions and 17 deletions
|
|
@ -33,6 +33,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventSendStat
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
|
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
fun aTimelineState(timelineItems: ImmutableList<TimelineItem> = persistentListOf()) = TimelineState(
|
fun aTimelineState(timelineItems: ImmutableList<TimelineItem> = persistentListOf()) = TimelineState(
|
||||||
|
|
@ -102,6 +103,7 @@ internal fun aTimelineItemEvent(
|
||||||
sendState: EventSendState = EventSendState.Sent(eventId),
|
sendState: EventSendState = EventSendState.Sent(eventId),
|
||||||
inReplyTo: InReplyTo? = null,
|
inReplyTo: InReplyTo? = null,
|
||||||
debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(),
|
debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(),
|
||||||
|
timelineItemReactions: TimelineItemReactions = aTimelineItemReactions(isMine = isMine),
|
||||||
): TimelineItem.Event {
|
): TimelineItem.Event {
|
||||||
return TimelineItem.Event(
|
return TimelineItem.Event(
|
||||||
id = eventId.value,
|
id = eventId.value,
|
||||||
|
|
@ -110,11 +112,7 @@ internal fun aTimelineItemEvent(
|
||||||
senderId = UserId("@senderId:domain"),
|
senderId = UserId("@senderId:domain"),
|
||||||
senderAvatar = AvatarData("@senderId:domain", "sender", size = AvatarSize.TimelineSender),
|
senderAvatar = AvatarData("@senderId:domain", "sender", size = AvatarSize.TimelineSender),
|
||||||
content = content,
|
content = content,
|
||||||
reactionsState = TimelineItemReactions(
|
reactionsState = timelineItemReactions,
|
||||||
persistentListOf(
|
|
||||||
AggregatedReaction("👍", "1", isOnMyMessage = isMine)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
sentTime = "12:34",
|
sentTime = "12:34",
|
||||||
isMine = isMine,
|
isMine = isMine,
|
||||||
senderDisplayName = "Sender",
|
senderDisplayName = "Sender",
|
||||||
|
|
@ -125,6 +123,19 @@ internal fun aTimelineItemEvent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun aTimelineItemReactions(
|
||||||
|
count: Int = 1,
|
||||||
|
isMine: Boolean = true,
|
||||||
|
): TimelineItemReactions {
|
||||||
|
return TimelineItemReactions(
|
||||||
|
reactions = buildList {
|
||||||
|
repeat(count) {
|
||||||
|
add(AggregatedReaction(key = "👍", count = (it + 1).toString(), isOnMyMessage = isMine))
|
||||||
|
}
|
||||||
|
}.toPersistentList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun aTimelineItemDebugInfo(
|
internal fun aTimelineItemDebugInfo(
|
||||||
model: String = "Rust(Model())",
|
model: String = "Rust(Model())",
|
||||||
originalJson: String? = null,
|
originalJson: String? = null,
|
||||||
|
|
|
||||||
|
|
@ -46,13 +46,17 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
|
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
|
||||||
|
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
|
||||||
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
|
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.event.toExtraPadding
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||||
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
|
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
|
||||||
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
|
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
|
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
|
||||||
|
|
@ -73,6 +77,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageT
|
||||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
|
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
|
||||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
|
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
|
||||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
|
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemEventRow(
|
fun TimelineItemEventRow(
|
||||||
|
|
@ -228,6 +233,7 @@ private fun MessageEventBubbleContent(
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
onClick = onMessageClick,
|
onClick = onMessageClick,
|
||||||
onLongClick = onMessageLongClick,
|
onLongClick = onMessageLongClick,
|
||||||
|
extraPadding = event.toExtraPadding(),
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -437,3 +443,44 @@ private fun ContentToPreview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
internal fun TimelineItemEventRowTimestampLightPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) =
|
||||||
|
ElementPreviewLight { ContentTimestampToPreview(event) }
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
internal fun TimelineItemEventRowTimestampDarkPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) =
|
||||||
|
ElementPreviewDark { ContentTimestampToPreview(event) }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ContentTimestampToPreview(event: TimelineItem.Event) {
|
||||||
|
Column {
|
||||||
|
val oldContent = event.content as TimelineItemTextContent
|
||||||
|
listOf(
|
||||||
|
"Text",
|
||||||
|
"Text longer but displayed on 1 line",
|
||||||
|
"Text which should be rendered on several lines",
|
||||||
|
).forEach { str ->
|
||||||
|
listOf(false, true).forEach { useDocument ->
|
||||||
|
TimelineItemEventRow(
|
||||||
|
event = event.copy(
|
||||||
|
content = oldContent.copy(
|
||||||
|
body = str,
|
||||||
|
htmlDocument = if (useDocument) Jsoup.parse(str) else null,
|
||||||
|
),
|
||||||
|
reactionsState = aTimelineItemReactions(count = 0),
|
||||||
|
senderDisplayName = if (useDocument) "Document case" else "Text case",
|
||||||
|
),
|
||||||
|
isHighlighted = false,
|
||||||
|
onClick = {},
|
||||||
|
onLongClick = {},
|
||||||
|
onUserDataClick = {},
|
||||||
|
inReplyToClick = {},
|
||||||
|
onTimestampClicked = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
|
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
|
||||||
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
|
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.event.noExtraPadding
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
|
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
|
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
|
||||||
|
|
@ -66,6 +67,7 @@ fun TimelineItemStateEventRow(
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
onLongClick = onLongClick,
|
onLongClick = onLongClick,
|
||||||
|
extraPadding = noExtraPadding,
|
||||||
modifier = Modifier.defaultTimelineContentPadding()
|
modifier = Modifier.defaultTimelineContentPadding()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,8 @@
|
||||||
package io.element.android.features.messages.impl.timeline.components.event
|
package io.element.android.features.messages.impl.timeline.components.event
|
||||||
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
|
||||||
|
|
@ -35,6 +33,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
||||||
fun TimelineItemEventContentView(
|
fun TimelineItemEventContentView(
|
||||||
content: TimelineItemEventContent,
|
content: TimelineItemEventContent,
|
||||||
interactionSource: MutableInteractionSource,
|
interactionSource: MutableInteractionSource,
|
||||||
|
extraPadding: ExtraPadding,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onLongClick: () -> Unit,
|
onLongClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
|
|
@ -42,14 +41,17 @@ fun TimelineItemEventContentView(
|
||||||
when (content) {
|
when (content) {
|
||||||
is TimelineItemEncryptedContent -> TimelineItemEncryptedView(
|
is TimelineItemEncryptedContent -> TimelineItemEncryptedView(
|
||||||
content = content,
|
content = content,
|
||||||
|
extraPadding = extraPadding,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
is TimelineItemRedactedContent -> TimelineItemRedactedView(
|
is TimelineItemRedactedContent -> TimelineItemRedactedView(
|
||||||
content = content,
|
content = content,
|
||||||
|
extraPadding = extraPadding,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
is TimelineItemTextBasedContent -> TimelineItemTextView(
|
is TimelineItemTextBasedContent -> TimelineItemTextView(
|
||||||
content = content,
|
content = content,
|
||||||
|
extraPadding = extraPadding,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onTextClicked = onClick,
|
onTextClicked = onClick,
|
||||||
|
|
@ -57,6 +59,7 @@ fun TimelineItemEventContentView(
|
||||||
)
|
)
|
||||||
is TimelineItemUnknownContent -> TimelineItemUnknownView(
|
is TimelineItemUnknownContent -> TimelineItemUnknownView(
|
||||||
content = content,
|
content = content,
|
||||||
|
extraPadding = extraPadding,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
is TimelineItemImageContent -> TimelineItemImageView(
|
is TimelineItemImageContent -> TimelineItemImageView(
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,14 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemEncryptedView(
|
fun TimelineItemEncryptedView(
|
||||||
content: TimelineItemEncryptedContent,
|
content: TimelineItemEncryptedContent,
|
||||||
|
extraPadding: ExtraPadding,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = stringResource(id = CommonStrings.common_decryption_error),
|
text = stringResource(id = CommonStrings.common_decryption_error),
|
||||||
iconDescription = stringResource(id = CommonStrings.dialog_title_warning),
|
iconDescription = stringResource(id = CommonStrings.dialog_title_warning),
|
||||||
icon = Icons.Default.Warning,
|
icon = Icons.Default.Warning,
|
||||||
|
extraPadding = extraPadding,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +58,7 @@ private fun ContentToPreview() {
|
||||||
TimelineItemEncryptedView(
|
TimelineItemEncryptedView(
|
||||||
content = TimelineItemEncryptedContent(
|
content = TimelineItemEncryptedContent(
|
||||||
data = UnableToDecryptContent.Data.Unknown
|
data = UnableToDecryptContent.Data.Unknown
|
||||||
)
|
),
|
||||||
|
extraPadding = noExtraPadding
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ fun TimelineItemInformativeView(
|
||||||
text: String,
|
text: String,
|
||||||
iconDescription: String,
|
iconDescription: String,
|
||||||
icon: ImageVector,
|
icon: ImageVector,
|
||||||
|
extraPadding: ExtraPadding,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -58,7 +59,7 @@ fun TimelineItemInformativeView(
|
||||||
fontStyle = FontStyle.Italic,
|
fontStyle = FontStyle.Italic,
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
text = text + extraPaddingTrick
|
text = text + extraPadding.str
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,6 +77,7 @@ private fun ContentToPreview() {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = "Info",
|
text = "Info",
|
||||||
iconDescription = "",
|
iconDescription = "",
|
||||||
icon = Icons.Default.Delete
|
icon = Icons.Default.Delete,
|
||||||
|
extraPadding = noExtraPadding,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,14 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemRedactedView(
|
fun TimelineItemRedactedView(
|
||||||
content: TimelineItemRedactedContent,
|
content: TimelineItemRedactedContent,
|
||||||
|
extraPadding: ExtraPadding,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = stringResource(id = CommonStrings.common_message_removed) + extraPaddingTrick,
|
text = stringResource(id = CommonStrings.common_message_removed),
|
||||||
iconDescription = stringResource(id = CommonStrings.common_message_removed),
|
iconDescription = stringResource(id = CommonStrings.common_message_removed),
|
||||||
icon = Icons.Default.Delete,
|
icon = Icons.Default.Delete,
|
||||||
|
extraPadding = extraPadding,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -52,5 +54,8 @@ internal fun TimelineItemRedactedViewDarkPreview() =
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContentToPreview() {
|
private fun ContentToPreview() {
|
||||||
TimelineItemRedactedView(TimelineItemRedactedContent)
|
TimelineItemRedactedView(
|
||||||
|
TimelineItemRedactedContent,
|
||||||
|
extraPadding = noExtraPadding
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ import android.text.util.Linkify.PHONE_NUMBERS
|
||||||
import android.text.util.Linkify.WEB_URLS
|
import android.text.util.Linkify.WEB_URLS
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -29,6 +32,7 @@ import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.text.util.LinkifyCompat
|
import androidx.core.text.util.LinkifyCompat
|
||||||
import io.element.android.features.messages.impl.timeline.components.html.HtmlDocument
|
import io.element.android.features.messages.impl.timeline.components.html.HtmlDocument
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
|
||||||
|
|
@ -43,12 +47,25 @@ import io.element.android.libraries.designsystem.text.toAnnotatedString
|
||||||
fun TimelineItemTextView(
|
fun TimelineItemTextView(
|
||||||
content: TimelineItemTextBasedContent,
|
content: TimelineItemTextBasedContent,
|
||||||
interactionSource: MutableInteractionSource,
|
interactionSource: MutableInteractionSource,
|
||||||
|
extraPadding: ExtraPadding,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onTextClicked: () -> Unit = {},
|
onTextClicked: () -> Unit = {},
|
||||||
onTextLongClicked: () -> Unit = {},
|
onTextLongClicked: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val htmlDocument = content.htmlDocument
|
val htmlDocument = content.htmlDocument
|
||||||
if (htmlDocument != null) {
|
if (htmlDocument != null) {
|
||||||
|
// For now we ignore the extra padding for html content, so add some spacing
|
||||||
|
// below the content (as previous behavior)
|
||||||
|
Column(modifier = modifier) {
|
||||||
|
HtmlDocument(
|
||||||
|
document = htmlDocument,
|
||||||
|
modifier = Modifier,
|
||||||
|
onTextClicked = onTextClicked,
|
||||||
|
onTextLongClicked = onTextLongClicked,
|
||||||
|
interactionSource = interactionSource
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
}
|
||||||
HtmlDocument(
|
HtmlDocument(
|
||||||
document = htmlDocument,
|
document = htmlDocument,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
@ -61,7 +78,7 @@ fun TimelineItemTextView(
|
||||||
val linkStyle = SpanStyle(
|
val linkStyle = SpanStyle(
|
||||||
color = LinkColor,
|
color = LinkColor,
|
||||||
)
|
)
|
||||||
val styledText = remember(content.body) { content.body.linkify(linkStyle) + extraPaddingTrick.toAnnotatedString() }
|
val styledText = remember(content.body) { content.body.linkify(linkStyle) + extraPadding.str.toAnnotatedString() }
|
||||||
ClickableLinkText(
|
ClickableLinkText(
|
||||||
text = styledText,
|
text = styledText,
|
||||||
linkAnnotationTag = "URL",
|
linkAnnotationTag = "URL",
|
||||||
|
|
@ -110,6 +127,10 @@ internal fun TimelineItemTextViewDarkPreview(@PreviewParameter(TimelineItemTextB
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ContentToPreview(content: TimelineItemTextBasedContent) {
|
fun ContentToPreview(content: TimelineItemTextBasedContent) {
|
||||||
TimelineItemTextView(content, MutableInteractionSource())
|
TimelineItemTextView(
|
||||||
|
content = content,
|
||||||
|
interactionSource = MutableInteractionSource(),
|
||||||
|
extraPadding = ExtraPadding("xxxxxxx"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,14 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemUnknownView(
|
fun TimelineItemUnknownView(
|
||||||
content: TimelineItemUnknownContent,
|
content: TimelineItemUnknownContent,
|
||||||
|
extraPadding: ExtraPadding,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = stringResource(id = CommonStrings.common_unsupported_event) + extraPaddingTrick,
|
text = stringResource(id = CommonStrings.common_unsupported_event),
|
||||||
iconDescription = stringResource(id = CommonStrings.dialog_title_warning),
|
iconDescription = stringResource(id = CommonStrings.dialog_title_warning),
|
||||||
icon = Icons.Default.Info,
|
icon = Icons.Default.Info,
|
||||||
|
extraPadding = extraPadding,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -52,5 +54,8 @@ internal fun TimelineItemUnknownViewDarkPreview() =
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContentToPreview() {
|
private fun ContentToPreview() {
|
||||||
TimelineItemUnknownView(TimelineItemUnknownContent)
|
TimelineItemUnknownView(
|
||||||
|
content = TimelineItemUnknownContent,
|
||||||
|
extraPadding = noExtraPadding
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,38 @@
|
||||||
|
|
||||||
package io.element.android.features.messages.impl.timeline.components.event
|
package io.element.android.features.messages.impl.timeline.components.event
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||||
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
|
||||||
|
import io.element.android.libraries.core.bool.orFalse
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.EventSendState
|
||||||
|
import io.element.android.libraries.ui.strings.R
|
||||||
|
|
||||||
// Allow to not overlap the timestamp with the text, in the message bubble.
|
// Allow to not overlap the timestamp with the text, in the message bubble.
|
||||||
// Compute the size of the worst case.
|
// Compute the size of the worst case.
|
||||||
val extraPaddingTrick: String = " ".repeat(" (edited) 88:88 X ".length)
|
data class ExtraPadding(val str: String)
|
||||||
|
|
||||||
|
val noExtraPadding = ExtraPadding("")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See [io.element.android.features.messages.impl.timeline.components.TimelineEventTimestampView] for the related View.
|
||||||
|
* And https://www.figma.com/file/0MMNu7cTOzLOlWb7ctTkv3/Element-X?node-id=1819%253A99506 for the design.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun TimelineItem.Event.toExtraPadding(): ExtraPadding {
|
||||||
|
val formattedTime = sentTime
|
||||||
|
val hasMessageSendingFailed = sendState is EventSendState.SendingFailed
|
||||||
|
val isMessageEdited = (content as? TimelineItemTextBasedContent)?.isEdited.orFalse()
|
||||||
|
|
||||||
|
var strLen = 2
|
||||||
|
if (isMessageEdited) {
|
||||||
|
strLen += stringResource(id = R.string.common_edited_suffix).length + 2
|
||||||
|
}
|
||||||
|
strLen += formattedTime.length
|
||||||
|
if (hasMessageSendingFailed) {
|
||||||
|
strLen += 3
|
||||||
|
}
|
||||||
|
// A space and a few unbreakable spaces
|
||||||
|
return ExtraPadding(" " + "\u00A0".repeat(strLen))
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue