Copy permalink

<!-- Please read [CONTRIBUTING.md](https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md) before submitting your pull request -->

## Type of change

- [ ] Feature
- [ ] Bugfix
- [ ] Technical
- [ ] Other :

## Content

<!-- Describe shortly what has been changed -->
Add action on message bottom sheet to copy permalink on some Event.

## Motivation and context

<!-- Provide link to the corresponding issue if applicable or explain the context -->
Closes #2650

## Screenshots / GIFs

<!--
We have screenshot tests in the project, so attaching screenshots to a PR is not mandatory, as far as there
is a Composable Preview covering the changes. In this case, the change will appear in the file diff.
Note that all the UI composables should be covered by a Composable Preview.

Providing a video of the change is still very useful for the reviewer and for the history of the project.

You can use a table like this to show screenshots comparison.
Uncomment this markdown table below and edit the last line `|||`:
|copy screenshot of before here|copy screenshot of after here|

|Before|After|
|-|-|
|||
 -->
See recorded one

## Tests

<!-- Explain how you tested your development -->

- Long click on a message and observe that there is a new action to copy the permalink.

## Tested devices

- [ ] Physical
- [x] Emulator
- OS version(s):

## Checklist

<!-- Depending on the Pull Request content, it can be acceptable if some of the following checkboxes stay unchecked. -->

- [ ] Changes have been tested on an Android device or Android emulator with API 23
- [ ] UI change has been tested on both light and dark themes
- [ ] Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
- [ ] Pull request is based on the develop branch
- [ ] Pull request includes a new file under ./changelog.d. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#changelog
- [ ] Pull request includes screenshots or videos if containing UI changes
- [ ] Pull request includes a [sign off](https://matrix-org.github.io/synapse/latest/development/contributing_guide.html#sign-off)
- [ ] You've made a self review of your PR

[Task] Copy permalink for Event

[Task] Copy permalink for Event
Please see and discuss the details in the meta issue.

diff --git a/changelog.d/2650.feature b/changelog.d/2650.feature
new file mode 100644
index 00000000000..4287d42ac79
--- /dev/null
+++ b/changelog.d/2650.feature
@@ -0,0 +1,1 @@
+Add action to copy permalink
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
index 4c92585b0db..4edc943a730 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
@@ -89,6 +89,7 @@ import io.element.android.libraries.matrix.ui.room.canRedactOtherAsState
 import io.element.android.libraries.matrix.ui.room.canRedactOwnAsState
 import io.element.android.libraries.matrix.ui.room.canSendMessageAsState
 import io.element.android.libraries.textcomposer.model.MessageComposerMode
+import io.element.android.libraries.ui.strings.CommonStrings
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -273,6 +274,7 @@ class MessagesPresenter @AssistedInject constructor(
     ) = launch {
         when (action) {
             TimelineItemAction.Copy -> handleCopyContents(targetEvent)
+            TimelineItemAction.CopyLink -> handleCopyLink(targetEvent)
             TimelineItemAction.Redact -> handleActionRedact(targetEvent)
             TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState, enableTextFormatting)
             TimelineItemAction.Reply,
@@ -435,6 +437,20 @@ class MessagesPresenter @AssistedInject constructor(
         event.eventId?.let { timelineState.eventSink(TimelineEvents.PollEndClicked(it)) }
     }

+    private suspend fun handleCopyLink(event: TimelineItem.Event) {
+        event.eventId ?: return
+        room.getPermalinkFor(event.eventId).fold(
+            onSuccess = { permalink ->
+                clipboardHelper.copyPlainText(permalink)
+                snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_link_copied_to_clipboard))
+            },
+            onFailure = {
+                Timber.e(it, "Failed to get permalink for event ${event.eventId}")
+                snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_error))
+            }
+        )
+    }
+
     private suspend fun handleCopyContents(event: TimelineItem.Event) {
         val content = when (event.content) {
             is TimelineItemTextBasedContent -> event.content.body
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt
index f836e2f8a05..5ebedeb06f5 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt
@@ -96,6 +96,7 @@ class ActionListPresenter @Inject constructor(
                 is TimelineItemStateContent -> {
                     buildList {
                         add(TimelineItemAction.Copy)
+                        add(TimelineItemAction.CopyLink)
                         if (isDeveloperModeEnabled) {
                             add(TimelineItemAction.ViewSource)
                         }
@@ -119,6 +120,7 @@ class ActionListPresenter @Inject constructor(
                         if (timelineItem.content.canBeCopied()) {
                             add(TimelineItemAction.Copy)
                         }
+                        add(TimelineItemAction.CopyLink)
                         if (isDeveloperModeEnabled) {
                             add(TimelineItemAction.ViewSource)
                         }
@@ -136,6 +138,7 @@ class ActionListPresenter @Inject constructor(
                             add(TimelineItemAction.Reply)
                             add(TimelineItemAction.Forward)
                         }
+                        add(TimelineItemAction.CopyLink)
                         if (isDeveloperModeEnabled) {
                             add(TimelineItemAction.ViewSource)
                         }
@@ -176,6 +179,7 @@ class ActionListPresenter @Inject constructor(
                     if (timelineItem.content.canBeCopied()) {
                         add(TimelineItemAction.Copy)
                     }
+                    add(TimelineItemAction.CopyLink)
                     if (isDeveloperModeEnabled) {
                         add(TimelineItemAction.ViewSource)
                     }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt
index 10952058b50..be78037d761 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt
@@ -135,6 +135,7 @@ fun aTimelineItemActionList(): ImmutableList<TimelineItemAction> {
         TimelineItemAction.Reply,
         TimelineItemAction.Forward,
         TimelineItemAction.Copy,
+        TimelineItemAction.CopyLink,
         TimelineItemAction.Edit,
         TimelineItemAction.Redact,
         TimelineItemAction.ReportContent,
@@ -146,6 +147,7 @@ fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> {
         TimelineItemAction.EndPoll,
         TimelineItemAction.Reply,
         TimelineItemAction.Copy,
+        TimelineItemAction.CopyLink,
         TimelineItemAction.ViewSource,
         TimelineItemAction.ReportContent,
         TimelineItemAction.Redact,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt
index f244f515f36..f61e6197c21 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt
@@ -31,6 +31,7 @@ sealed class TimelineItemAction(
 ) {
     data object Forward : TimelineItemAction(CommonStrings.action_forward, CompoundDrawables.ic_compound_forward)
     data object Copy : TimelineItemAction(CommonStrings.action_copy, CompoundDrawables.ic_compound_copy)
+    data object CopyLink : TimelineItemAction(CommonStrings.action_copy_link_to_message, CompoundDrawables.ic_compound_link)
     data object Redact : TimelineItemAction(CommonStrings.action_remove, CompoundDrawables.ic_compound_delete, destructive = true)
     data object Reply : TimelineItemAction(CommonStrings.action_reply, CompoundDrawables.ic_compound_reply)
     data object ReplyInThread : TimelineItemAction(CommonStrings.action_reply_in_thread, CompoundDrawables.ic_compound_reply)
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt
index 3e01155a86b..aa1f3fa0254 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt
@@ -328,5 +328,12 @@ interface MatrixRoom : Closeable {
      */
     fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver>

+    /**
+     * Get the permalink for the provided [eventId].
+     * @param eventId The event id to get the permalink for.
+     * @return The permalink, or a failure.
+     */
+    suspend fun getPermalinkFor(eventId: EventId): Result<String>
+
     override fun close() = destroy()
 }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt
index 7ab6e3640b6..be61b063103 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt
@@ -16,6 +16,7 @@

 package io.element.android.libraries.matrix.impl.room

+import io.element.android.appconfig.MatrixConfiguration
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.core.coroutine.childScope
 import io.element.android.libraries.matrix.api.core.EventId
@@ -711,6 +712,19 @@ class RustMatrixRoom(
         )
     }

+    override suspend fun getPermalinkFor(eventId: EventId): Result<String> {
+        // FIXME Use the SDK API once https://github.com/matrix-org/matrix-rust-sdk/issues/3259 has been done
+        // Now use a simple builder
+        return runCatching {
+            buildString {
+                append(MatrixConfiguration.MATRIX_TO_PERMALINK_BASE_URL)
+                append(roomId.value)
+                append("/")
+                append(eventId.value)
+            }
+        }
+    }
+
     private fun sendAttachment(files: List<File>, handle: () -> SendAttachmentJoinHandle): Result<MediaUploadHandler> {
         return runCatching {
             MediaUploadHandlerImpl(files, handle())

diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt
index 6cceb6b5b54..bce97f4a6ee 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt
@@ -233,6 +233,27 @@ class MessagesPresenterTest {
         }
     }

+    @Test
+    fun `present - handle action copy link`() = runTest {
+        val clipboardHelper = FakeClipboardHelper()
+        val event = aMessageEvent()
+        val matrixRoom = FakeMatrixRoom(
+            permalinkResult = { Result.success("a link") },
+        )
+        val presenter = createMessagesPresenter(
+            clipboardHelper = clipboardHelper,
+            matrixRoom = matrixRoom,
+        )
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitFirstItem()
+            initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.CopyLink, event))
+            assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
+            assertThat(clipboardHelper.clipboardContents).isEqualTo("a link")
+        }
+    }
+
     @Test
     fun `present - handle action reply`() = runTest {
         val presenter = createMessagesPresenter()
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt
index 981e8fc8ac0..c1062625f7d 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt
@@ -153,6 +153,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Reply,
                         TimelineItemAction.Forward,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                         TimelineItemAction.ReportContent,
                     )
@@ -193,6 +194,7 @@ class ActionListPresenterTest {
                     actions = persistentListOf(
                         TimelineItemAction.Forward,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                         TimelineItemAction.ReportContent,
                     )
@@ -232,6 +234,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Reply,
                         TimelineItemAction.Forward,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                         TimelineItemAction.ReportContent,
                         TimelineItemAction.Redact,
@@ -272,6 +275,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Reply,
                         TimelineItemAction.Forward,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                         TimelineItemAction.ReportContent,
                         TimelineItemAction.Redact,
@@ -315,6 +319,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Forward,
                         TimelineItemAction.Edit,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                         TimelineItemAction.Redact,
                     )
@@ -357,6 +362,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Forward,
                         TimelineItemAction.Edit,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                     )
                 )
@@ -396,6 +402,7 @@ class ActionListPresenterTest {
                     actions = persistentListOf(
                         TimelineItemAction.Reply,
                         TimelineItemAction.Forward,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                         TimelineItemAction.Redact,
                     )
@@ -435,6 +442,7 @@ class ActionListPresenterTest {
                     displayEmojiReactions = false,
                     actions = persistentListOf(
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.ViewSource,
                     )
                 )
@@ -473,6 +481,7 @@ class ActionListPresenterTest {
                     displayEmojiReactions = false,
                     actions = persistentListOf(
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                     )
                 )
             )
@@ -513,6 +522,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Forward,
                         TimelineItemAction.Edit,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.Redact,
                     )
                 )
@@ -595,6 +605,7 @@ class ActionListPresenterTest {
                     actions = persistentListOf(
                         TimelineItemAction.Edit,
                         TimelineItemAction.Copy,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.Redact,
                     )
                 )
@@ -632,6 +643,7 @@ class ActionListPresenterTest {
                         TimelineItemAction.Reply,
                         TimelineItemAction.Edit,
                         TimelineItemAction.EndPoll,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.Redact,
                     )
                 )
@@ -668,6 +680,7 @@ class ActionListPresenterTest {
                     actions = persistentListOf(
                         TimelineItemAction.Reply,
                         TimelineItemAction.EndPoll,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.Redact,
                     )
                 )
@@ -703,6 +716,7 @@ class ActionListPresenterTest {
                     displayEmojiReactions = true,
                     actions = persistentListOf(
                         TimelineItemAction.Reply,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.Redact,
                     )
                 )
@@ -738,6 +752,7 @@ class ActionListPresenterTest {
                     actions = persistentListOf(
                         TimelineItemAction.Reply,
                         TimelineItemAction.Forward,
+                        TimelineItemAction.CopyLink,
                         TimelineItemAction.Redact,
                     )
                 )
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt
index 32575e59245..f2395241b5c 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt
@@ -84,6 +84,7 @@ class FakeMatrixRoom(
     override val activeMemberCount: Long = 234L,
     val notificationSettingsService: NotificationSettingsService = FakeNotificationSettingsService(),
     private val matrixTimeline: MatrixTimeline = FakeMatrixTimeline(),
+    private var permalinkResult: () -> Result<String> = { Result.success("link") },
     canRedactOwn: Boolean = false,
     canRedactOther: Boolean = false,
 ) : MatrixRoom {
@@ -273,6 +274,10 @@ class FakeMatrixRoom(
         return cancelSendResult
     }

+    override suspend fun getPermalinkFor(eventId: EventId): Result<String> {
+        return permalinkResult()
+    }
+
     override suspend fun editMessage(
         originalEventId: EventId?,
         transactionId: TransactionId?,
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_10,NEXUS_5,1.0,en].png
index a2fa0ff4c9d..758bb383113 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_10,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_10,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:654d73d145ba000b0a58e1974206bd9c7970a5a384186336469504cd35b19890
-size 29036
+oid sha256:f5aa4c9aab5727c56ee6efcf8c136cca8276d54695d28a4f548af9d51f3df4b9
+size 34264
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_2,NEXUS_5,1.0,en].png
index 0cf654af986..8ac22522d01 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:32c2a61124bd68fc1921439f834744c1a40fa615de1270b8d97dd5c4365bbd25
-size 39317
+oid sha256:0d31d3549643b37a21f043f9ec9a33fa93e25f4004b077af713097855235effe
+size 44276
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_3,NEXUS_5,1.0,en].png
index 942a986658b..f5be0071937 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:17c00b93a8073bdc2741f0492623ffef80d37e3f3fc8744650233d489b6efc82
-size 39866
+oid sha256:dfe460e8bab0a27a31984ce8c85ed98aef2a994584f724375cd436d5c1c7c6ca
+size 44758
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_4,NEXUS_5,1.0,en].png
index ca3fc4b9e22..8f629512ea7 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2bcd9a9db22a88210afa8ba3700abc1895d040c044ec11aa324d720651a3bc0b
-size 40404
+oid sha256:e287869aa819ff569ab187f8995260410c47c32817caba61ba7639d6b0a2fe44
+size 45245
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_5,NEXUS_5,1.0,en].png
index 8a6fc8596a4..e5b5b23b085 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:00804549fdbada3e48531ffab2bd5e013cd592d11c56e65eb2385b07910bc6e3
-size 39998
+oid sha256:1f6602e1e19e1c5b545522ff7444b294cc926d02b1910f196461a9770f64af4a
+size 44882
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_6,NEXUS_5,1.0,en].png
index 8f3fe73e50b..9f81bd59e2b 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4f71497d55a8cb048b3249221e8b24c883e3015533f4e543650b742542b5daac
-size 40645
+oid sha256:4c321a39333a03b5eadf287e2a37e809da3620205d97caa1ae63f9ab99dc4f82
+size 45464
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_7,NEXUS_5,1.0,en].png
index c044d8db01b..a9ba8ca80e6 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0d4ad5e2fb1b518495f23b70fde606d791536adbea3ffac76c5fbb54e4c22138
-size 41343
+oid sha256:135f36df3ade2a4e210fc5560b8a00593e842153424da5efcd25b5c64036f59c
+size 46240
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_8,NEXUS_5,1.0,en].png
index 870e1cd2c6c..2d2bf39bf1d 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:675bbd412179ad4960c6cf78f973c67fd11809340e414f7ebf3eef5e41434e0e
-size 41201
+oid sha256:ea154dca2cde0829bb70dbcf9e032e63d052c35194b159dd72db8c72a58863b0
+size 46082
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_9,NEXUS_5,1.0,en].png
index d8fffdef9a5..97c322b6a95 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_9,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Day-1_1_null_9,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:33e82110711be0bdff074df90c93c3911e77bf53672df336c5fa6bf74f28d86f
-size 28191
+oid sha256:f2124f3afde9e0fc4e42733d3624f69a74b898a035e47e4369acfad2834d0e02
+size 33378
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_10,NEXUS_5,1.0,en].png
index 683a9a47550..0ce605591d5 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_10,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_10,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7220aa1b48506d58f800d71c0aa1b3ea1650fa2153246d1572213e5ff0170b04
-size 27759
+oid sha256:61da843a4fd576317ce1dab5a95cba47f269c96096157f880da5c6f3f8a944c7
+size 32148
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_2,NEXUS_5,1.0,en].png
index 04e465574f8..7e260976f90 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:36262a1ed8e2029519eb519e64dd973a5170269c04ad509464596b87bcbd9247
-size 37891
+oid sha256:0345399ddbe34e4fb13468571921fb2de8db1b7db01cb6a7439970b15046d37e
+size 42361
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_3,NEXUS_5,1.0,en].png
index c36ec3d9994..0cbbb24fd4b 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3c75a4422846ab1e4d12c48916a5f306b506cd1c082f1709104560634106a8ba
-size 38420
+oid sha256:63b40ee6d9b4fa6f049dedbfc628380069360e67129b8e53b94e04d25b5897bf
+size 42898
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_4,NEXUS_5,1.0,en].png
index 08bc6aed16e..02acc78564d 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e28f6654d3fd5fb6e332a999fda8393bdff4988a87039e683cd94a251f4b9b07
-size 38926
+oid sha256:a5d9f66ab910df80652ef7658869ee05f570af134f1e05e8fc5b19d9a05a453e
+size 43388
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_5,NEXUS_5,1.0,en].png
index e5917eb1ae0..38a46d54121 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9a2cd0f46f405978dda374ce865bc5f409280716830fcd2d29e290c11b36f118
-size 38538
+oid sha256:e37056a6b4d6416a77af752d04b040d1fc8dbd65bdaaae8d50c05e7a11309d05
+size 43013
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_6,NEXUS_5,1.0,en].png
index 490bfe9f87e..0dd6058fd1e 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:eac8803bd70cc677841f124eeb19e70f50a257cf89360410618db2c2f601c27a
-size 39178
+oid sha256:995e4bfb172bbc09177d1427f63063f86348cedd5e497a5341eb0e8374e80cc9
+size 43634
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_7,NEXUS_5,1.0,en].png
index 6bd5bbeda89..139f2d887a1 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:96c95a7ca59ed0d8bba59e735a2248d2cee3d0a8d4c045a0491fe1731c8c9574
-size 39848
+oid sha256:1d086a8c7b3f9e6dbbf30495ba1d209b8436a8ef5d31dc9a3605a0b2cd9ce72e
+size 44276
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_8,NEXUS_5,1.0,en].png
index 3c897184fae..0058b2ffd35 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a395ca5f5dbf4647ad1b5dea90f3c7a1cada2e934c4053f5ecc1e793e4efa879
-size 39718
+oid sha256:013dce6e34f67c62a514b958b502a511c9975551eb745b4e502c5794584e730a
+size 44150
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_9,NEXUS_5,1.0,en].png
index 1afb6e95320..6505ba7ac70 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_9,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_SheetContent_null_SheetContent-Night-1_2_null_9,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4bf2d4ecc1c9e67cd833ca5cd61b4f77e5da9381e4425f332b91e7fbf8d9d0f4
-size 26781
+oid sha256:cda82238c49b88bf0da5f462bcb05dee7fe2e659345c03997456be635ff4bae2
+size 31287