diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml
index fd825db3f0..abe4b190df 100644
--- a/.idea/dictionaries/shared.xml
+++ b/.idea/dictionaries/shared.xml
@@ -9,6 +9,7 @@
placeables
showkase
snackbar
+ swipeable
textfields
diff --git a/build.gradle.kts b/build.gradle.kts
index 40f0b8706c..b5d082b8ce 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -247,6 +247,7 @@ koverMerged {
excludes += "io.element.android.features.messages.impl.media.local.LocalMediaViewState"
excludes += "io.element.android.features.location.impl.map.MapState"
excludes += "io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState*"
+ excludes += "io.element.android.libraries.designsystem.swipe.SwipeableActionsState*"
}
bound {
minValue = 90
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
index d4b0f80e3e..7f18ad2fdf 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalMaterial3Api::class)
-
package io.element.android.features.messages.impl.timeline.components
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -28,6 +28,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.absoluteOffset
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -35,26 +36,25 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.DismissDirection
-import androidx.compose.material3.DismissState
-import androidx.compose.material3.DismissValue
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.SwipeToDismiss
-import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.platform.ViewConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
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.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
@@ -66,6 +66,7 @@ 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.toExtraPadding
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.bubble.BubbleState
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
@@ -78,6 +79,9 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.swipe.SwipeableActionsState
+import io.element.android.libraries.designsystem.swipe.rememberSwipeableActionsState
+import io.element.android.libraries.designsystem.text.toPx
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
@@ -93,7 +97,10 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
+import kotlinx.coroutines.launch
import org.jsoup.Jsoup
+import kotlin.math.abs
+import kotlin.math.roundToInt
@Composable
fun TimelineItemEventRow(
@@ -110,6 +117,7 @@ fun TimelineItemEventRow(
onSwipeToReply: () -> Unit,
modifier: Modifier = Modifier
) {
+ val coroutineScope = rememberCoroutineScope()
val interactionSource = remember { MutableInteractionSource() }
fun onUserDataClicked() {
@@ -121,56 +129,88 @@ fun TimelineItemEventRow(
inReplyToClick(inReplyToEventId)
}
- if (canReply) {
- val dismissState = rememberDismissState(
- confirmValueChange = {
- if (it == DismissValue.DismissedToEnd) {
- onSwipeToReply()
+ Column(modifier = modifier.fillMaxWidth()) {
+ if (event.groupPosition.isNew()) {
+ Spacer(modifier = Modifier.height(16.dp))
+ } else {
+ Spacer(modifier = Modifier.height(2.dp))
+ }
+ if (canReply) {
+ val state: SwipeableActionsState = rememberSwipeableActionsState()
+ val offset = state.offset.value
+ val swipeThresholdPx = 40.dp.toPx()
+ val thresholdCrossed = abs(offset) > swipeThresholdPx
+ SwipeSensitivity(3f) {
+ Box(Modifier.fillMaxWidth()) {
+ Row(modifier = Modifier.matchParentSize()) {
+ ReplySwipeIndicator({ offset / 120 })
+ }
+ TimelineItemEventRowContent(
+ modifier = Modifier
+ .absoluteOffset { IntOffset(x = offset.roundToInt(), y = 0) }
+ .draggable(
+ orientation = Orientation.Horizontal,
+ enabled = !state.isResettingOnRelease,
+ onDragStopped = {
+ coroutineScope.launch {
+ if (thresholdCrossed) {
+ onSwipeToReply()
+ }
+ state.resetOffset()
+ }
+ },
+ state = state.draggableState,
+ ),
+ event = event,
+ isHighlighted = isHighlighted,
+ interactionSource = interactionSource,
+ onClick = onClick,
+ onLongClick = onLongClick,
+ onTimestampClicked = onTimestampClicked,
+ inReplyToClicked = ::inReplyToClicked,
+ onUserDataClicked = ::onUserDataClicked,
+ onReactionClicked = { emoji -> onReactionClick(emoji, event) },
+ onMoreReactionsClicked = { onMoreReactionsClick(event) },
+ )
}
- // Do not dismiss the message, return false!
- false
}
- )
- SwipeToDismiss(
- state = dismissState,
- background = {
- ReplySwipeIndicator({ dismissState.toSwipeProgress() })
- },
- directions = setOf(DismissDirection.StartToEnd),
- dismissContent = {
- TimelineItemEventRowContent(
- event = event,
- isHighlighted = isHighlighted,
- interactionSource = interactionSource,
- onClick = onClick,
- onLongClick = onLongClick,
- onTimestampClicked = onTimestampClicked,
- inReplyToClicked = ::inReplyToClicked,
- onUserDataClicked = ::onUserDataClicked,
- onReactionClicked = { emoji -> onReactionClick(emoji, event) },
- onMoreReactionsClicked = { onMoreReactionsClick(event) },
- )
- }
- )
- } else {
- TimelineItemEventRowContent(
- event = event,
- isHighlighted = isHighlighted,
- interactionSource = interactionSource,
- onClick = onClick,
- onLongClick = onLongClick,
- onTimestampClicked = onTimestampClicked,
- inReplyToClicked = ::inReplyToClicked,
- onUserDataClicked = ::onUserDataClicked,
- onReactionClicked = { emoji -> onReactionClick(emoji, event) },
- onMoreReactionsClicked = { onMoreReactionsClick(event) },
- )
+ } else {
+ TimelineItemEventRowContent(
+ event = event,
+ isHighlighted = isHighlighted,
+ interactionSource = interactionSource,
+ onClick = onClick,
+ onLongClick = onLongClick,
+ onTimestampClicked = onTimestampClicked,
+ inReplyToClicked = ::inReplyToClicked,
+ onUserDataClicked = ::onUserDataClicked,
+ onReactionClicked = { emoji -> onReactionClick(emoji, event) },
+ onMoreReactionsClicked = { onMoreReactionsClick(event) },
+ )
+ }
}
- // This is assuming that we are in a ColumnScope, but this is OK, for both Preview and real usage.
- if (event.groupPosition.isNew()) {
- Spacer(modifier = modifier.height(16.dp))
- } else {
- Spacer(modifier = modifier.height(2.dp))
+}
+
+/**
+ * Impact ViewConfiguration.touchSlop by [sensitivityFactor].
+ * Inspired from https://issuetracker.google.com/u/1/issues/269627294.
+ * @param sensitivityFactor the factor to multiply the touchSlop by. The highest value, the more the user will
+ * have to drag to start the drag.
+ * @param content the content to display.
+ */
+@Composable
+fun SwipeSensitivity(
+ sensitivityFactor: Float,
+ content: @Composable () -> Unit,
+) {
+ val current = LocalViewConfiguration.current
+ CompositionLocalProvider(
+ LocalViewConfiguration provides object : ViewConfiguration by current {
+ override val touchSlop: Float
+ get() = current.touchSlop * sensitivityFactor
+ }
+ ) {
+ content()
}
}
@@ -266,14 +306,6 @@ private fun TimelineItemEventRowContent(
}
}
-private fun DismissState.toSwipeProgress(): Float {
- return when (targetValue) {
- DismissValue.Default -> 0f
- DismissValue.DismissedToEnd -> progress * 3
- DismissValue.DismissedToStart -> progress * 3
- }
-}
-
@Composable
private fun MessageSenderInformation(
sender: String,
@@ -544,6 +576,7 @@ private fun ContentToPreview() {
body = "A long text which will be displayed on several lines and" +
" hopefully can be manually adjusted to test different behaviors."
),
+ groupPosition = TimelineItemGroupPosition.First,
),
isHighlighted = false,
canReply = true,
@@ -562,6 +595,7 @@ private fun ContentToPreview() {
content = aTimelineItemImageContent().copy(
aspectRatio = 5f
),
+ groupPosition = TimelineItemGroupPosition.Last,
),
isHighlighted = false,
canReply = true,
@@ -606,7 +640,8 @@ private fun ContentToPreviewWithReply() {
body = "A long text which will be displayed on several lines and" +
" hopefully can be manually adjusted to test different behaviors."
),
- inReplyTo = aInReplyToReady(replyContent)
+ inReplyTo = aInReplyToReady(replyContent),
+ groupPosition = TimelineItemGroupPosition.First,
),
isHighlighted = false,
canReply = true,
@@ -625,7 +660,8 @@ private fun ContentToPreviewWithReply() {
content = aTimelineItemImageContent().copy(
aspectRatio = 5f
),
- inReplyTo = aInReplyToReady(replyContent)
+ inReplyTo = aInReplyToReady(replyContent),
+ groupPosition = TimelineItemGroupPosition.Last,
),
isHighlighted = false,
canReply = true,
@@ -699,7 +735,6 @@ private fun ContentTimestampToPreview(event: TimelineItem.Event) {
}
}
-
@Preview
@Composable
internal fun TimelineItemEventRowWithManyReactionsLightPreview() =
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/swipe/SwipeableActionsState.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/swipe/SwipeableActionsState.kt
new file mode 100644
index 0000000000..77d80cdde5
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/swipe/SwipeableActionsState.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2023 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 io.element.android.libraries.designsystem.swipe
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.MutatePriority
+import androidx.compose.foundation.gestures.DraggableState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+
+/**
+ * Inspired from https://github.com/bmarty/swipe/blob/trunk/swipe/src/main/kotlin/me/saket/swipe/SwipeableActionsState.kt
+ */
+@Composable
+fun rememberSwipeableActionsState(): SwipeableActionsState {
+ return remember { SwipeableActionsState() }
+}
+
+@Stable
+class SwipeableActionsState {
+ /**
+ * The current position (in pixels) of the content.
+ */
+ val offset: State get() = offsetState
+ private var offsetState = mutableStateOf(0f)
+
+ /**
+ * Whether the content is currently animating to reset its offset after it was swiped.
+ */
+ var isResettingOnRelease: Boolean by mutableStateOf(false)
+ private set
+
+ val draggableState = DraggableState { delta ->
+ val targetOffset = offsetState.value + delta
+ val isAllowed = isResettingOnRelease || targetOffset > 0f
+
+ offsetState.value += if (isAllowed) delta else 0f
+ }
+
+ suspend fun resetOffset() {
+ draggableState.drag(MutatePriority.PreventUserInput) {
+ isResettingOnRelease = true
+ try {
+ Animatable(offsetState.value).animateTo(
+ targetValue = 0f,
+ animationSpec = tween(durationMillis = 300),
+ ) {
+ dragBy(value - offsetState.value)
+ }
+ } finally {
+ isResettingOnRelease = false
+ }
+ }
+ }
+}
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png
index 2eb0d560be..b5b12ec81d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b8ca3e1c8ce3c9476cdc7db46aebc8b6970486ff01e05b82c162256373c8957f
-size 141055
+oid sha256:323b80f3b2fcee42ffe50f333ff9d3952da05138f413f15882bf8ff7079347d8
+size 138598
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png
index bcda87bb06..9664edfe08 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2bf89d0228a9771360eaad8a0bc514731153a351551df427cf7f7e44b886edfe
-size 145398
+oid sha256:21c3a584e3d47d030e45aac8d2162bd9b1d03f0ef43c3b8681f69eadd2d6fcc2
+size 142344
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 02fef0faa0..82fefe69c1 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:043097099dd08f0e192debd0ef650e8effe76c71f29dd3a993bf756d8e933d25
-size 62314
+oid sha256:7d62f35da442eba33e6913f6704de1e80918e50cef6237c00678ec9de5a23759
+size 62310
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 4f80e82b44..633ab693fd 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4fe9d9d0ff870ccbb095c53b37900c00feb8153e76965ba432bad9d37387e512
-size 64523
+oid sha256:8d488277351ea1f53f11cabef46ff46768a42d61dc913b903b670635b9e44816
+size 64503
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index aaae1b427f..b27bf20e06 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e78c43cdaa5532d854087567fb8deef13fe89b1e896450428186df6b6cd83443
-size 68731
+oid sha256:e6b3750046ba185168395f20c75451524754b003a293cfcb0ed5a45be8f3335b
+size 68707
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index a18580d94f..f9b8fdd599 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:960e7c05075107db3a2b57f630f114927d4d019ffc5d38f5d501d44107753ea5
-size 70789
+oid sha256:963bf003585c82dddbb2efe1f6cf2f0564db88ea5de69e2b4322a6d256639de8
+size 70761
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 6f7db0fa68..43da505724 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f39fd269e68edb95e0b7c49bbf21a51c6c4233bfbfc173fdbc0e80eec2cf8d83
+oid sha256:b75482695c36693390a1100ff2758ed8910f65da42ddb270cbc07252c25ae439
size 64252
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_1,NEXUS_5,1.0,en].png
index dd02e31b94..0dfb072ab2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:eeb7f709da25c8864e712ab1532fd7803ab1d692c7baea970283a4702640840c
-size 66900
+oid sha256:401cbd6022543957388ec5fe81181604495238e80c95c1baa036c67bd62460d6
+size 66869
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_2,NEXUS_5,1.0,en].png
index ff1cdcee31..ed1bb381da 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:79493cad80934a053f300864189dd47bf6c1d9aabac780a5c5ea1ca497fc7a47
-size 71250
+oid sha256:ac20d25de28ae59dd2e9ea2743480792c3c10644128219966af1eee1e2034ac0
+size 71215
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 00d73a45bb..b0b268e568 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowTimestampLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c2b4ed0df17a6f96dd0031b820585346ec6ccac419a2f1237e0decdfb50dddb7
-size 73644
+oid sha256:5ca3befc8d4142f5be8252ffffef5ac82a25786085b0552b348d4f0a412bc9ae
+size 73743
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png
index 599ea51395..579d5884e4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:82b4fb72cd3517b4eedeba3172cc428ba67199df816c686d998027ed021c1bb0
-size 84164
+oid sha256:1963827d549b8144bd1c71f85da6208307b8939f621b57c705a2ca61309f2e0d
+size 84239
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png
index e4cd1354cc..1aa0b25463 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:7c95c7df9616dca071528f4185e63485e7e738e51e595d828f94b08205c6e33d
-size 87695
+oid sha256:6e4ae356384002a19f779236ed6f2a3722c8f7bda91357dee3cacbb95d6aa61e
+size 87794
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png
index 40a5b155d3..c306c70ed3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:02f2eb6e37f1022aa13cbcdfc34e7955b99ee4c3d6b35668b548afc94d33ae31
-size 119137
+oid sha256:dcd2fb7256950a8a31267d6be90c342ae8774e945b04d954a7cc3d83878cb25a
+size 119550
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png
index 09c6f7efe7..1749f4f823 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d50e5ac4433e4a44091623f1813373884007506002cc0c657ca7231a6e309462
-size 123938
+oid sha256:5628adde34216d1888481918628c82655252acfc15296c4fddd3220d0b72eaa4
+size 124893