diff --git a/.github/workflows/maestro.yml b/.github/workflows/maestro.yml
index 136dfb1f20..74696c9a22 100644
--- a/.github/workflows/maestro.yml
+++ b/.github/workflows/maestro.yml
@@ -79,7 +79,7 @@ jobs:
uses: actions/download-artifact@v4
with:
name: elementx-apk-maestro
- - uses: mobile-dev-inc/action-maestro-cloud@v1.9.6
+ - uses: mobile-dev-inc/action-maestro-cloud@v1.9.7
if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch'
with:
api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/ElementCallConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/ElementCallConfig.kt
index d7cad2f9e1..390ba5a532 100644
--- a/appconfig/src/main/kotlin/io/element/android/appconfig/ElementCallConfig.kt
+++ b/appconfig/src/main/kotlin/io/element/android/appconfig/ElementCallConfig.kt
@@ -16,5 +16,5 @@ object ElementCallConfig {
/**
* The default duration of a ringing call in seconds before it's automatically dismissed.
*/
- const val RINGING_CALL_DURATION_SECONDS = 15
+ const val RINGING_CALL_DURATION_SECONDS = 90
}
diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt
index c5f605e5fe..83ea9e3b77 100644
--- a/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt
+++ b/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt
@@ -11,14 +11,20 @@ import android.graphics.Color
import androidx.annotation.ColorInt
object NotificationConfig {
- // TODO EAx Implement and set to true at some point
- const val SUPPORT_MARK_AS_READ_ACTION = false
+ /**
+ * If set to true, the notification will have a "Mark as read" action.
+ */
+ const val SHOW_MARK_AS_READ_ACTION = true
- // TODO EAx Implement and set to true at some point
- const val SUPPORT_JOIN_DECLINE_INVITE = false
+ /**
+ * If set to true, the notification for invitation will have two actions to accept or decline the invite.
+ */
+ const val SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS = true
- // TODO EAx Implement and set to true at some point
- const val SUPPORT_QUICK_REPLY_ACTION = false
+ /**
+ * If set to true, the notification will have a "Quick reply" action, allow to compose and send a message to the room.
+ */
+ const val SHOW_QUICK_REPLY_ACTION = true
@ColorInt
val NOTIFICATION_ACCENT_COLOR: Int = Color.parseColor("#FF0DBD8B")
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
index 5677d3834d..940e576a30 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
@@ -20,11 +20,20 @@ import androidx.lifecycle.repeatOnLifecycle
import com.bumble.appyx.core.composable.PermanentChild
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
+import com.bumble.appyx.core.navigation.NavElements
+import com.bumble.appyx.core.navigation.NavKey
import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
+import com.bumble.appyx.navmodel.backstack.BackStack.State.ACTIVE
+import com.bumble.appyx.navmodel.backstack.BackStack.State.CREATED
+import com.bumble.appyx.navmodel.backstack.BackStack.State.STASHED
+import com.bumble.appyx.navmodel.backstack.BackStackElement
+import com.bumble.appyx.navmodel.backstack.BackStackElements
+import com.bumble.appyx.navmodel.backstack.operation.BackStackOperation
+import com.bumble.appyx.navmodel.backstack.operation.Push
import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import com.bumble.appyx.navmodel.backstack.operation.replace
@@ -312,7 +321,7 @@ class LoggedInFlowNode @AssistedInject constructor(
}
override fun onForwardedToSingleRoom(roomId: RoomId) {
- coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias()) }
+ coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias(), clearBackstack = false) }
}
override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) {
@@ -400,6 +409,11 @@ class LoggedInFlowNode @AssistedInject constructor(
is NavTarget.SecureBackup -> {
secureBackupEntryPoint.nodeBuilder(this, buildContext)
.params(SecureBackupEntryPoint.Params(initialElement = navTarget.initialElement))
+ .callback(object : SecureBackupEntryPoint.Callback {
+ override fun onDone() {
+ backstack.pop()
+ }
+ })
.build()
}
NavTarget.Ftue -> {
@@ -467,21 +481,21 @@ class LoggedInFlowNode @AssistedInject constructor(
serverNames: List = emptyList(),
trigger: JoinedRoom.Trigger? = null,
eventId: EventId? = null,
+ clearBackstack: Boolean,
) {
waitForNavTargetAttached { navTarget ->
navTarget is NavTarget.RoomList
}
attachChild {
- backstack.push(
- NavTarget.Room(
- roomIdOrAlias = roomIdOrAlias,
- serverNames = serverNames,
- trigger = trigger,
- initialElement = RoomNavigationTarget.Messages(
- focusedEventId = eventId
- )
+ val roomNavTarget = NavTarget.Room(
+ roomIdOrAlias = roomIdOrAlias,
+ serverNames = serverNames,
+ trigger = trigger,
+ initialElement = RoomNavigationTarget.Messages(
+ focusedEventId = eventId
)
)
+ backstack.accept(AttachRoomOperation(roomNavTarget, clearBackstack))
}
}
@@ -526,3 +540,31 @@ class LoggedInFlowNode @AssistedInject constructor(
@Assisted plugins: List,
) : Node(buildContext, plugins = plugins)
}
+
+@Parcelize
+private class AttachRoomOperation(
+ val roomTarget: LoggedInFlowNode.NavTarget.Room,
+ val clearBackstack: Boolean,
+) : BackStackOperation {
+ override fun isApplicable(elements: NavElements) = true
+
+ override fun invoke(elements: BackStackElements): BackStackElements {
+ return if (clearBackstack) {
+ // Makes sure the room list target is alone in the backstack and stashed
+ elements.mapNotNull { element ->
+ if (element.key.navTarget == LoggedInFlowNode.NavTarget.RoomList) {
+ element.transitionTo(STASHED, this)
+ } else {
+ null
+ }
+ } + BackStackElement(
+ key = NavKey(roomTarget),
+ fromState = CREATED,
+ targetState = ACTIVE,
+ operation = this
+ )
+ } else {
+ Push(roomTarget).invoke(elements)
+ }
+ }
+}
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
index 53f6de6032..143595d934 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
@@ -303,6 +303,7 @@ class RootFlowNode @AssistedInject constructor(
trigger = JoinedRoom.Trigger.MobilePermalink,
serverNames = permalinkData.viaParameters,
eventId = permalinkData.eventId,
+ clearBackstack = true
)
}
is PermalinkData.UserLink -> {
@@ -318,7 +319,7 @@ class RootFlowNode @AssistedInject constructor(
.apply {
when (deeplinkData) {
is DeeplinkData.Root -> Unit // The room list will always be shown, observing FtueState
- is DeeplinkData.Room -> attachRoom(deeplinkData.roomId.toRoomIdOrAlias())
+ is DeeplinkData.Room -> attachRoom(deeplinkData.roomId.toRoomIdOrAlias(), clearBackstack = true)
}
}
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 187b09de54..31edb5b08c 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -52,6 +52,10 @@ allprojects {
detektPlugins("io.nlopez.compose.rules:detekt:0.4.19")
}
+ tasks.withType().configureEach {
+ exclude("io/element/android/tests/konsist/failures/**")
+ }
+
// KtLint
apply {
plugin("org.jlleitschuh.gradle.ktlint")
@@ -75,6 +79,7 @@ allprojects {
val generatedPath = "${layout.buildDirectory.asFile.get()}/generated/"
filter {
exclude { element -> element.file.path.contains(generatedPath) }
+ exclude("io/element/android/tests/konsist/failures/**")
}
}
// Dependency check
diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt
index 609c04a0e6..588fd25ac0 100644
--- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt
+++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt
@@ -66,19 +66,34 @@ class WebViewWidgetMessageInterceptor(
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
// No network for instance, transmit the error
Timber.e("onReceivedError error: ${error?.errorCode} ${error?.description}")
- onError(error?.description?.toString())
+
+ // Only propagate the error if it happens while loading the current page
+ if (view?.url == request?.url.toString()) {
+ onError(error?.description.toString())
+ }
+
super.onReceivedError(view, request, error)
}
override fun onReceivedHttpError(view: WebView?, request: WebResourceRequest?, errorResponse: WebResourceResponse?) {
Timber.e("onReceivedHttpError error: ${errorResponse?.statusCode} ${errorResponse?.reasonPhrase}")
- onError(errorResponse?.statusCode.toString())
+
+ // Only propagate the error if it happens while loading the current page
+ if (view?.url == request?.url.toString()) {
+ onError(errorResponse?.statusCode.toString())
+ }
+
super.onReceivedHttpError(view, request, errorResponse)
}
override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
Timber.e("onReceivedSslError error: ${error?.primaryError}")
- onError(error?.primaryError?.toString())
+
+ // Only propagate the error if it happens while loading the current page
+ if (view?.url == error?.url.toString()) {
+ onError(error?.toString())
+ }
+
super.onReceivedSslError(view, handler, error)
}
}
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt
index 67e697e8e4..164a82af62 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt
@@ -102,7 +102,10 @@ class CreateRoomDataStore @Inject constructor(
createRoomConfigFlow.getAndUpdate { config ->
config.copy(
roomVisibility = when (config.roomVisibility) {
- is RoomVisibilityState.Public -> config.roomVisibility.copy(roomAddress = RoomAddress.Edited(address))
+ is RoomVisibilityState.Public -> {
+ val sanitizedAddress = address.lowercase()
+ config.roomVisibility.copy(roomAddress = RoomAddress.Edited(sanitizedAddress))
+ }
else -> config.roomVisibility
}
)
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
index e34bb27a8b..fabbe2aecc 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
@@ -240,9 +240,9 @@ private fun RoomTopic(
modifier = modifier,
label = stringResource(R.string.screen_create_room_topic_label),
value = topic,
- placeholder = stringResource(CommonStrings.common_topic_placeholder),
onValueChange = onTopicChange,
maxLines = 3,
+ supportingText = stringResource(CommonStrings.common_topic_placeholder),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Sentences,
),
diff --git a/features/createroom/impl/src/main/res/values-de/translations.xml b/features/createroom/impl/src/main/res/values-de/translations.xml
index 441f747e7e..09ad753211 100644
--- a/features/createroom/impl/src/main/res/values-de/translations.xml
+++ b/features/createroom/impl/src/main/res/values-de/translations.xml
@@ -3,11 +3,22 @@
"Neuer Raum"
"Personen einladen"
"Beim Erstellen des Chats ist ein Fehler aufgetreten"
- "Die Nachrichten in diesem Chat sind verschlüsselt. Die Verschlüsselung kann nicht nachträglich deaktiviert werden."
- "Privater Raum (nur auf Einladung)"
- "Die Nachrichten sind nicht verschlüsselt und können von jedem gelesen werden. Die Verschlüsselung kann zu einem späteren Zeitpunkt aktiviert werden."
- "Öffentlicher Raum (für alle)"
+ "Nur eingeladene Personen haben Zutritt zu diesem Chatroom. Alle Nachrichten sind durchgehend verschlüsselt."
+ "Privater Chatroom"
+ "Jeder kann diesen Chatroom finden.
+Sie können dies aber jederzeit in den Chatroomeinstellungen ändern."
+ "Öffentlicher Chatroom"
+ "Jeder kann diesem Chatroom beitreten"
+ "Jemand"
+ "Chatroom Zugang"
+ "Jeder kann darum bitten, dem Chatroom beizutreten, aber ein Administrator oder ein Moderator muss die Anfrage akzeptieren."
+ "Beitritt beantragen"
+ "Einige Zeichen sind nicht erlaubt. Es werden nur Buchstaben, Ziffern und die folgenden Symbole unterstützt: ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"
+ "Diese Chatroomadresse existiert bereits. Bitte versuchen Sie, das Adressenfeld des Chatrooms zu bearbeiten oder den Namen des Chatrooms zu ändern"
+ "Damit dieser Chatroom im öffentlichen Chatroomverzeichnis sichtbar ist, benötigen Sie eine Chatroomadresse."
+ "Chatroom Adresse"
"Raumname"
+ " Sichtbarkeit des Chatrooms"
"Raum erstellen"
"Thema (optional)"
"Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten"
diff --git a/features/createroom/impl/src/main/res/values/localazy.xml b/features/createroom/impl/src/main/res/values/localazy.xml
index 7900aef801..7a08c7af87 100644
--- a/features/createroom/impl/src/main/res/values/localazy.xml
+++ b/features/createroom/impl/src/main/res/values/localazy.xml
@@ -14,7 +14,7 @@ You can change this anytime in room settings."
"Anyone can ask to join the room but an administrator or a moderator will have to accept the request"
"Ask to join"
"Some characters are not allowed. Only letters, digits and the following symbols are supported ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"
- "This room address already exists, please try editing the room address field or change the room name"
+ "This room address already exists. Please try editing the room address field or change the room name"
"In order for this room to be visible in the public room directory, you will need a room address."
"Room address"
"Room name"
diff --git a/features/deactivation/impl/src/main/res/values-de/translations.xml b/features/deactivation/impl/src/main/res/values-de/translations.xml
new file mode 100644
index 0000000000..0830d6ba3f
--- /dev/null
+++ b/features/deactivation/impl/src/main/res/values-de/translations.xml
@@ -0,0 +1,14 @@
+
+
+ "Bitte bestätigen Sie, dass Sie Ihr Benutzerkonto deaktivieren möchten. Diese Aktion kann nicht rückgängig gemacht werden."
+ "Lösche alle meine Nachrichten"
+ "Warnung: Benutzern werden möglicherweise unvollständige Konversationen angezeigt."
+ "Wenn Sie Ihr Konto deaktivieren%1$s, wird es:"
+ "irreversibel"
+ "%1$s Ihr Konto (Sie können sich nicht erneut anmelden und Ihre ID kann nicht wiederverwendet werden)."
+ "Dauerhaft deaktivieren"
+ "Sie werden aus allen Chatrooms entfernt."
+ "Löschen Sie Ihre Kontoinformationen von unserem Identitätsserver."
+ "Gelöschte Nachrichten werden für bereits registrierte Benutzer weiterhin sichtbar sein, wenn sie auch neuen oder nicht registrierten Benutzern nicht mehr zur Verfügung stehen."
+ "Benutzerkonto deaktivieren"
+
diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/state/SharedPreferencesWelcomeScreenState.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/state/SharedPreferencesWelcomeScreenStore.kt
similarity index 94%
rename from features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/state/SharedPreferencesWelcomeScreenState.kt
rename to features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/state/SharedPreferencesWelcomeScreenStore.kt
index 551a00dd20..b03ccae482 100644
--- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/state/SharedPreferencesWelcomeScreenState.kt
+++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/state/SharedPreferencesWelcomeScreenStore.kt
@@ -16,7 +16,7 @@ import javax.inject.Inject
@ContributesBinding(AppScope::class)
@SingleIn(AppScope::class)
-class SharedPreferencesWelcomeScreenState @Inject constructor(
+class SharedPreferencesWelcomeScreenStore @Inject constructor(
private val sharedPreferences: SharedPreferences,
) : WelcomeScreenStore {
companion object {
diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/welcome/state/InMemoryWelcomeScreenState.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/welcome/state/InMemoryWelcomeScreenStore.kt
similarity index 90%
rename from features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/welcome/state/InMemoryWelcomeScreenState.kt
rename to features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/welcome/state/InMemoryWelcomeScreenStore.kt
index a310a43a7f..cf3a73f490 100644
--- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/welcome/state/InMemoryWelcomeScreenState.kt
+++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/welcome/state/InMemoryWelcomeScreenStore.kt
@@ -7,7 +7,7 @@
package io.element.android.features.ftue.impl.welcome.state
-class InMemoryWelcomeScreenState : WelcomeScreenStore {
+class InMemoryWelcomeScreenStore : WelcomeScreenStore {
private var isWelcomeScreenNeeded = true
override fun isWelcomeScreenNeeded(): Boolean {
diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt
index ba909a147b..1984c0c4b3 100644
--- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt
+++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt
@@ -48,8 +48,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.util.Optional
-private const val MAX_KNOCK_MESSAGE_LENGTH = 500
-
class JoinRoomPresenter @AssistedInject constructor(
@Assisted private val roomId: RoomId,
@Assisted private val roomIdOrAlias: RoomIdOrAlias,
diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt
index 6049e6cd5a..b53c1e0f7d 100644
--- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt
+++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt
@@ -18,6 +18,8 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.ui.model.InviteSender
+internal const val MAX_KNOCK_MESSAGE_LENGTH = 500
+
@Immutable
data class JoinRoomState(
val contentState: ContentState,
diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt
index 33dcf786e5..d3bbc59c0c 100644
--- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt
+++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt
@@ -40,17 +40,6 @@ open class JoinRoomStateProvider : PreviewParameterProvider {
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin)
),
- aJoinRoomState(
- contentState = aLoadedContentState(
- joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock,
- topic = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt" +
- " ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco" +
- " laboris nisi ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit in" +
- " voluptate velit esse cillum dolore eu fugiat nulla pariatur excepteur sint occaecat cupidatat" +
- " non proident sunt in culpa qui officia deserunt mollit anim id est laborum",
- numberOfMembers = 888,
- )
- ),
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(null))
),
@@ -81,6 +70,29 @@ open class JoinRoomStateProvider : PreviewParameterProvider {
isDm = true,
)
),
+ aJoinRoomState(
+ contentState = aLoadedContentState(
+ joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock,
+ topic = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt" +
+ " ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco" +
+ " laboris nisi ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit in" +
+ " voluptate velit esse cillum dolore eu fugiat nulla pariatur excepteur sint occaecat cupidatat" +
+ " non proident sunt in culpa qui officia deserunt mollit anim id est laborum",
+ numberOfMembers = 888,
+ )
+ ),
+ aJoinRoomState(
+ knockMessage = "Let me in please!",
+ contentState = aLoadedContentState(
+ joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock,
+ topic = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt" +
+ " ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco" +
+ " laboris nisi ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit in" +
+ " voluptate velit esse cillum dolore eu fugiat nulla pariatur excepteur sint occaecat cupidatat" +
+ " non proident sunt in culpa qui officia deserunt mollit anim id est laborum",
+ numberOfMembers = 888,
+ )
+ ),
aJoinRoomState(
contentState = aLoadedContentState(
name = "A knocked Room",
diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt
index 3a1c7c8421..d06b5badf3 100644
--- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt
+++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt
@@ -390,13 +390,18 @@ private fun DefaultLoadedContent(
)
} else if (contentState.joinAuthorisationStatus is JoinAuthorisationStatus.CanKnock) {
Spacer(modifier = Modifier.height(24.dp))
+ val supportingText = if (knockMessage.isNotEmpty()) {
+ "${knockMessage.length}/$MAX_KNOCK_MESSAGE_LENGTH"
+ } else {
+ stringResource(R.string.screen_join_room_knock_message_description)
+ }
TextField(
value = knockMessage,
onValueChange = onKnockMessageUpdate,
maxLines = 3,
minLines = 3,
modifier = Modifier.fillMaxWidth(),
- supportingText = stringResource(R.string.screen_join_room_knock_message_description)
+ supportingText = supportingText
)
}
}
diff --git a/features/joinroom/impl/src/main/res/values-de/translations.xml b/features/joinroom/impl/src/main/res/values-de/translations.xml
index 95718ce371..cbdf0c34a3 100644
--- a/features/joinroom/impl/src/main/res/values-de/translations.xml
+++ b/features/joinroom/impl/src/main/res/values-de/translations.xml
@@ -1,7 +1,14 @@
+ "Anfrage abbrechen"
+ "Ja, abbrechen"
+ "Möchten Sie Ihre Beitrittsanfrage für diesen Chatroom wirklich stornieren?"
+ "Beitrittsanfrage stornieren"
"Raum beitreten"
"Anklopfen"
+ "Nachricht (optional)"
+ "Falls Ihre Anfrage, dem Raum beizutreten, akzeptiert wird, werden Sie eine Einladung erhalten."
+ "Beitrittsanfrage geschickt"
"%1$s unterstützt noch keine Spaces. Du kannst auf Spaces im Web zugreifen."
"Spaces werden noch nicht unterstützt"
"Klopfe an um einen Administrator zu benachrichtigen. Nach der Freigabe kannst du dich an der Unterhaltung beteiligen."
diff --git a/features/lockscreen/impl/src/main/res/values-de/translations.xml b/features/lockscreen/impl/src/main/res/values-de/translations.xml
index 4042df3d1b..e56938285c 100644
--- a/features/lockscreen/impl/src/main/res/values-de/translations.xml
+++ b/features/lockscreen/impl/src/main/res/values-de/translations.xml
@@ -3,6 +3,7 @@
"biometrische Authentifizierung"
"biometrisches Entsperren"
"Mit Biometrie entsperren"
+ "Biometrische Daten bestätigen"
"PIN vergessen?"
"PIN-Code ändern"
"Biometrisches Entsperren zulassen"
diff --git a/features/lockscreen/impl/src/main/res/values-fr/translations.xml b/features/lockscreen/impl/src/main/res/values-fr/translations.xml
index a8b3757022..b77df23254 100644
--- a/features/lockscreen/impl/src/main/res/values-fr/translations.xml
+++ b/features/lockscreen/impl/src/main/res/values-fr/translations.xml
@@ -3,6 +3,7 @@
"l’authentification biométrique"
"déverrouillage biométrique"
"Déverrouiller avec la biométrie"
+ "Confirmer la biométrie"
"Code PIN oublié?"
"Modifier le code PIN"
"Autoriser le déverrouillage biométrique"
diff --git a/features/lockscreen/impl/src/main/res/values-ru/translations.xml b/features/lockscreen/impl/src/main/res/values-ru/translations.xml
index a70ff5015c..eae4799f93 100644
--- a/features/lockscreen/impl/src/main/res/values-ru/translations.xml
+++ b/features/lockscreen/impl/src/main/res/values-ru/translations.xml
@@ -3,6 +3,7 @@
"биометрическая идентификация"
"биометрическая разблокировка"
"Разблокировать с помощью биометрии"
+ "Подтвердить биометрические данные"
"Забыли PIN-код?"
"Изменить PIN-код"
"Разрешить биометрическую разблокировку"
diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml
index 10ed45beee..468056f6b7 100644
--- a/features/login/impl/src/main/res/values-de/translations.xml
+++ b/features/login/impl/src/main/res/values-de/translations.xml
@@ -60,6 +60,7 @@ Versuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Ger
"Wähle %1$s"
"\"Neues Gerät verknüpfen\""
"Scanne den QR-Code mit diesem Gerät"
+ "Nur verfügbar für den Fall dass Ihr Kontoanbieter dies unterstützt."
"Öffne %1$s auf einem anderen Gerät, um den QR-Code zu erhalten"
"Verwende den QR-Code, der auf dem anderen Gerät angezeigt wird."
"Erneut versuchen"
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt
index fc3fba9c59..8cbb7b6d74 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt
@@ -40,6 +40,7 @@ import io.element.android.features.messages.impl.timeline.TimelineController
import io.element.android.features.messages.impl.timeline.debug.EventDebugInfoNode
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentWithAttachment
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
@@ -51,6 +52,7 @@ import io.element.android.libraries.architecture.BackstackWithOverlayBox
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.overlay.Overlay
+import io.element.android.libraries.architecture.overlay.operation.hide
import io.element.android.libraries.architecture.overlay.operation.show
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.MatrixClient
@@ -66,8 +68,8 @@ import io.element.android.libraries.matrix.api.room.joinedRoomMembers
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.ui.messages.LocalRoomMemberProfilesCache
import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerNode
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import io.element.android.libraries.textcomposer.mentions.LocalMentionSpanTheme
import io.element.android.libraries.textcomposer.mentions.MentionSpanTheme
import io.element.android.services.analytics.api.AnalyticsService
@@ -86,6 +88,7 @@ class MessagesFlowNode @AssistedInject constructor(
private val showLocationEntryPoint: ShowLocationEntryPoint,
private val createPollEntryPoint: CreatePollEntryPoint,
private val elementCallEntryPoint: ElementCallEntryPoint,
+ private val mediaViewerEntryPoint: MediaViewerEntryPoint,
private val analyticsService: AnalyticsService,
private val room: MatrixRoom,
private val roomMemberProfilesCache: RoomMemberProfilesCache,
@@ -228,14 +231,22 @@ class MessagesFlowNode @AssistedInject constructor(
createNode(buildContext, listOf(callback, inputs))
}
is NavTarget.MediaViewer -> {
- val inputs = MediaViewerNode.Inputs(
+ val params = MediaViewerEntryPoint.Params(
mediaInfo = navTarget.mediaInfo,
mediaSource = navTarget.mediaSource,
thumbnailSource = navTarget.thumbnailSource,
canDownload = true,
canShare = true,
)
- createNode(buildContext, listOf(inputs))
+ val callback = object : MediaViewerEntryPoint.Callback {
+ override fun onDone() {
+ overlay.hide()
+ }
+ }
+ mediaViewerEntryPoint.nodeBuilder(this, buildContext)
+ .params(params)
+ .callback(callback)
+ .build()
}
is NavTarget.AttachmentPreview -> {
val inputs = AttachmentsPreviewNode.Inputs(navTarget.attachment)
@@ -319,100 +330,93 @@ class MessagesFlowNode @AssistedInject constructor(
}
private fun processEventClick(event: TimelineItem.Event): Boolean {
- return when (event.content) {
+ val navTarget = when (event.content) {
is TimelineItemImageContent -> {
- val navTarget = NavTarget.MediaViewer(
- mediaInfo = MediaInfo(
- filename = event.content.filename,
- caption = event.content.caption,
- mimeType = event.content.mimeType,
- formattedFileSize = event.content.formattedFileSize,
- fileExtension = event.content.fileExtension
- ),
+ buildMediaViewerNavTarget(
+ event = event,
+ content = event.content,
mediaSource = event.content.mediaSource,
thumbnailSource = event.content.thumbnailSource,
)
- overlay.show(navTarget)
- true
}
is TimelineItemStickerContent -> {
/* Sticker may have an empty url and no thumbnail
if encrypted on certain bridges */
- if (event.content.preferredMediaSource != null) {
- val navTarget = NavTarget.MediaViewer(
- mediaInfo = MediaInfo(
- filename = event.content.filename,
- caption = event.content.caption,
- mimeType = event.content.mimeType,
- formattedFileSize = event.content.formattedFileSize,
- fileExtension = event.content.fileExtension
- ),
- mediaSource = event.content.preferredMediaSource,
+ event.content.preferredMediaSource?.let { preferredMediaSource ->
+ buildMediaViewerNavTarget(
+ event = event,
+ content = event.content,
+ mediaSource = preferredMediaSource,
thumbnailSource = event.content.thumbnailSource,
)
- overlay.show(navTarget)
- true
- } else {
- false
}
}
is TimelineItemVideoContent -> {
- val navTarget = NavTarget.MediaViewer(
- mediaInfo = MediaInfo(
- filename = event.content.filename,
- caption = event.content.caption,
- mimeType = event.content.mimeType,
- formattedFileSize = event.content.formattedFileSize,
- fileExtension = event.content.fileExtension
- ),
- mediaSource = event.content.videoSource,
+ buildMediaViewerNavTarget(
+ event = event,
+ content = event.content,
+ mediaSource = event.content.mediaSource,
thumbnailSource = event.content.thumbnailSource,
)
- overlay.show(navTarget)
- true
}
is TimelineItemFileContent -> {
- val navTarget = NavTarget.MediaViewer(
- mediaInfo = MediaInfo(
- filename = event.content.filename,
- caption = event.content.caption,
- mimeType = event.content.mimeType,
- formattedFileSize = event.content.formattedFileSize,
- fileExtension = event.content.fileExtension
- ),
- mediaSource = event.content.fileSource,
+ buildMediaViewerNavTarget(
+ event = event,
+ content = event.content,
+ mediaSource = event.content.mediaSource,
thumbnailSource = event.content.thumbnailSource,
)
- overlay.show(navTarget)
- true
}
is TimelineItemAudioContent -> {
- val navTarget = NavTarget.MediaViewer(
- mediaInfo = MediaInfo(
- filename = event.content.filename,
- caption = event.content.caption,
- mimeType = event.content.mimeType,
- formattedFileSize = event.content.formattedFileSize,
- fileExtension = event.content.fileExtension
- ),
+ buildMediaViewerNavTarget(
+ event = event,
+ content = event.content,
mediaSource = event.content.mediaSource,
thumbnailSource = null,
)
- overlay.show(navTarget)
- true
}
is TimelineItemLocationContent -> {
- val navTarget = NavTarget.LocationViewer(
+ NavTarget.LocationViewer(
location = event.content.location,
description = event.content.description,
)
+ }
+ else -> null
+ }
+ return when (navTarget) {
+ is NavTarget.MediaViewer -> {
overlay.show(navTarget)
true
}
+ is NavTarget.LocationViewer -> {
+ backstack.push(navTarget)
+ true
+ }
else -> false
}
}
+ private fun buildMediaViewerNavTarget(
+ event: TimelineItem.Event,
+ content: TimelineItemEventContentWithAttachment,
+ mediaSource: MediaSource,
+ thumbnailSource: MediaSource?,
+ ): NavTarget {
+ return NavTarget.MediaViewer(
+ mediaInfo = MediaInfo(
+ filename = content.filename,
+ caption = content.caption,
+ mimeType = content.mimeType,
+ formattedFileSize = content.formattedFileSize,
+ fileExtension = content.fileExtension,
+ senderName = event.safeSenderName,
+ dateSent = event.sentTime,
+ ),
+ mediaSource = mediaSource,
+ thumbnailSource = thumbnailSource,
+ )
+ }
+
@Composable
override fun View(modifier: Modifier) {
mentionSpanTheme.updateStyles(currentUserId = room.sessionId)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt
index 1798584853..7d5bad4d63 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt
@@ -28,6 +28,8 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.compound.theme.ElementTheme
+import io.element.android.features.messages.impl.actionlist.ActionListPresenter
+import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter
@@ -65,6 +67,7 @@ class MessagesNode @AssistedInject constructor(
messageComposerPresenterFactory: MessageComposerPresenter.Factory,
timelinePresenterFactory: TimelinePresenter.Factory,
presenterFactory: MessagesPresenter.Factory,
+ actionListPresenterFactory: ActionListPresenter.Factory,
private val timelineItemPresenterFactories: TimelineItemPresenterFactories,
private val mediaPlayer: MediaPlayer,
private val permalinkParser: PermalinkParser,
@@ -73,6 +76,7 @@ class MessagesNode @AssistedInject constructor(
navigator = this,
composerPresenter = messageComposerPresenterFactory.create(this),
timelinePresenter = timelinePresenterFactory.create(this),
+ actionListPresenter = actionListPresenterFactory.create(TimelineItemActionPostProcessor.Default)
)
private val callbacks = plugins()
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 e39056ec9b..4895390ab8 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
@@ -28,9 +28,8 @@ import im.vector.app.features.analytics.plan.PinUnpinAction
import io.element.android.appconfig.MessageComposerConfig
import io.element.android.features.messages.api.timeline.HtmlConverterProvider
import io.element.android.features.messages.impl.actionlist.ActionListEvents
-import io.element.android.features.messages.impl.actionlist.ActionListPresenter
+import io.element.android.features.messages.impl.actionlist.ActionListState
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
-import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
@@ -93,7 +92,7 @@ class MessagesPresenter @AssistedInject constructor(
@Assisted private val timelinePresenter: Presenter,
private val timelineProtectionPresenter: Presenter,
private val identityChangeStatePresenter: Presenter,
- actionListPresenterFactory: ActionListPresenter.Factory,
+ @Assisted private val actionListPresenter: Presenter,
private val customReactionPresenter: Presenter,
private val reactionSummaryPresenter: Presenter,
private val readReceiptBottomSheetPresenter: Presenter,
@@ -110,14 +109,13 @@ class MessagesPresenter @AssistedInject constructor(
private val permalinkParser: PermalinkParser,
private val analyticsService: AnalyticsService,
) : Presenter {
- private val actionListPresenter = actionListPresenterFactory.create(TimelineItemActionPostProcessor.Default)
-
@AssistedFactory
interface Factory {
fun create(
navigator: MessagesNavigator,
composerPresenter: Presenter,
timelinePresenter: Presenter,
+ actionListPresenter: Presenter,
): MessagesPresenter
}
@@ -272,7 +270,8 @@ class MessagesPresenter @AssistedInject constructor(
timelineState: TimelineState,
) = launch {
when (action) {
- TimelineItemAction.Copy -> handleCopyContents(targetEvent)
+ TimelineItemAction.CopyText -> handleCopyContents(targetEvent)
+ TimelineItemAction.CopyCaption -> handleCopyCaption(targetEvent)
TimelineItemAction.CopyLink -> handleCopyLink(targetEvent)
TimelineItemAction.Redact -> handleActionRedact(targetEvent)
TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState, enableTextFormatting)
@@ -403,26 +402,28 @@ class MessagesPresenter @AssistedInject constructor(
}
}
- private fun handleActionAddCaption(
+ private suspend fun handleActionAddCaption(
targetEvent: TimelineItem.Event,
composerState: MessageComposerState,
) {
val composerMode = MessageComposerMode.EditCaption(
eventOrTransactionId = targetEvent.eventOrTransactionId,
content = "",
+ showCaptionCompatibilityWarning = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaCaptionWarning),
)
composerState.eventSink(
MessageComposerEvents.SetMode(composerMode)
)
}
- private fun handleActionEditCaption(
+ private suspend fun handleActionEditCaption(
targetEvent: TimelineItem.Event,
composerState: MessageComposerState,
) {
val composerMode = MessageComposerMode.EditCaption(
eventOrTransactionId = targetEvent.eventOrTransactionId,
content = (targetEvent.content as? TimelineItemEventContentWithAttachment)?.caption.orEmpty(),
+ showCaptionCompatibilityWarning = featureFlagsService.isFeatureEnabled(FeatureFlags.MediaCaptionWarning),
)
composerState.eventSink(
MessageComposerEvents.SetMode(composerMode)
@@ -488,11 +489,17 @@ class MessagesPresenter @AssistedInject constructor(
is TimelineItemStateContent -> event.content.body
else -> return
}
-
clipboardHelper.copyPlainText(content)
-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
snackbarDispatcher.post(SnackbarMessage(R.string.screen_room_timeline_message_copied))
}
}
+
+ private suspend fun handleCopyCaption(event: TimelineItem.Event) {
+ val content = (event.content as? TimelineItemEventContentWithAttachment)?.caption ?: return
+ clipboardHelper.copyPlainText(content)
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_copied_to_clipboard))
+ }
+ }
}
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 e228f3eb73..411ff37c8f 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
@@ -21,6 +21,7 @@ import dagger.assisted.AssistedInject
import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled
import io.element.android.features.messages.impl.UserEventPermissions
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
+import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionComparator
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory
@@ -37,6 +38,8 @@ import io.element.android.features.messages.impl.timeline.model.event.canBeForwa
import io.element.android.features.messages.impl.timeline.model.event.canReact
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.di.RoomScope
+import io.element.android.libraries.featureflag.api.FeatureFlagService
+import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
@@ -60,6 +63,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
private val room: MatrixRoom,
private val userSendFailureFactory: VerifiedUserSendFailureFactory,
+ private val featureFlagService: FeatureFlagService,
) : ActionListPresenter {
@AssistedFactory
@ContributesBinding(RoomScope::class)
@@ -67,6 +71,8 @@ class DefaultActionListPresenter @AssistedInject constructor(
override fun create(postProcessor: TimelineItemActionPostProcessor): DefaultActionListPresenter
}
+ private val comparator = TimelineItemActionComparator()
+
@Composable
override fun present(): ActionListState {
val localCoroutineScope = rememberCoroutineScope()
@@ -134,7 +140,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
}
}
- private fun buildActions(
+ private suspend fun buildActions(
timelineItem: TimelineItem.Event,
usersEventPermissions: UserEventPermissions,
isDeveloperModeEnabled: Boolean,
@@ -142,7 +148,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
isEventPinned: Boolean,
): List {
val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther
- return buildList {
+ return buildSet {
if (timelineItem.canBeRepliedTo && usersEventPermissions.canSendMessage) {
if (timelineItem.isThreaded) {
add(TimelineItemAction.ReplyInThread)
@@ -157,7 +163,9 @@ class DefaultActionListPresenter @AssistedInject constructor(
if (timelineItem.content is TimelineItemEventContentWithAttachment) {
// Caption
if (timelineItem.content.caption == null) {
- add(TimelineItemAction.AddCaption)
+ if (featureFlagService.isFeatureEnabled(FeatureFlags.MediaCaptionCreation)) {
+ add(TimelineItemAction.AddCaption)
+ }
} else {
add(TimelineItemAction.EditCaption)
add(TimelineItemAction.RemoveCaption)
@@ -178,7 +186,9 @@ class DefaultActionListPresenter @AssistedInject constructor(
}
}
if (timelineItem.content.canBeCopied()) {
- add(TimelineItemAction.Copy)
+ add(TimelineItemAction.CopyText)
+ } else if ((timelineItem.content as? TimelineItemEventContentWithAttachment)?.caption.isNullOrBlank().not()) {
+ add(TimelineItemAction.CopyCaption)
}
if (timelineItem.isRemote) {
add(TimelineItemAction.CopyLink)
@@ -194,6 +204,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
}
}
.postFilter(timelineItem.content)
+ .sortedWith(comparator)
.let(postProcessor::process)
}
}
@@ -201,7 +212,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
/**
* Post filter the actions based on the content of the event.
*/
-private fun List.postFilter(content: TimelineItemEventContent): List {
+private fun Iterable.postFilter(content: TimelineItemEventContent): Iterable {
return filter { action ->
when (content) {
is TimelineItemCallNotifyContent,
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 78e65c839a..a5f027a535 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
@@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.actionlist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
+import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionComparator
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.anUnsignedDeviceSendFailure
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
@@ -22,7 +23,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
import kotlinx.collections.immutable.ImmutableList
-import kotlinx.collections.immutable.persistentListOf
+import kotlinx.collections.immutable.toPersistentList
open class ActionListStateProvider : PreviewParameterProvider {
override val values: Sequence
@@ -50,7 +51,9 @@ open class ActionListStateProvider : PreviewParameterProvider {
),
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
- actions = aTimelineItemActionList(),
+ actions = aTimelineItemActionList(
+ copyAction = TimelineItemAction.CopyCaption,
+ ),
)
),
anActionListState(
@@ -61,7 +64,9 @@ open class ActionListStateProvider : PreviewParameterProvider {
),
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
- actions = aTimelineItemActionList(),
+ actions = aTimelineItemActionList(
+ copyAction = TimelineItemAction.CopyCaption,
+ ),
)
),
anActionListState(
@@ -72,7 +77,9 @@ open class ActionListStateProvider : PreviewParameterProvider {
),
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
- actions = aTimelineItemActionList(),
+ actions = aTimelineItemActionList(
+ copyAction = null,
+ ),
)
),
anActionListState(
@@ -83,18 +90,22 @@ open class ActionListStateProvider : PreviewParameterProvider {
),
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
- actions = aTimelineItemActionList(),
+ actions = aTimelineItemActionList(
+ copyAction = TimelineItemAction.CopyCaption,
+ ),
)
),
anActionListState(
target = ActionListState.Target.Success(
event = aTimelineItemEvent(
- content = aTimelineItemVoiceContent(),
+ content = aTimelineItemVoiceContent(caption = null),
timelineItemReactions = reactionsState
),
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
- actions = aTimelineItemActionList(),
+ actions = aTimelineItemActionList(
+ copyAction = null,
+ ),
)
),
anActionListState(
@@ -161,27 +172,31 @@ fun anActionListState(
eventSink = eventSink
)
-fun aTimelineItemActionList(): ImmutableList {
- return persistentListOf(
+fun aTimelineItemActionList(
+ copyAction: TimelineItemAction? = TimelineItemAction.CopyText
+): ImmutableList {
+ return setOfNotNull(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.Copy,
+ copyAction,
TimelineItemAction.CopyLink,
TimelineItemAction.Edit,
TimelineItemAction.Redact,
TimelineItemAction.ReportContent,
TimelineItemAction.ViewSource,
)
+ .sortedWith(TimelineItemActionComparator())
+ .toPersistentList()
}
fun aTimelineItemPollActionList(): ImmutableList {
- return persistentListOf(
+ return setOf(
TimelineItemAction.EndPoll,
TimelineItemAction.Reply,
- TimelineItemAction.Copy,
+ TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
- TimelineItemAction.ViewSource,
- TimelineItemAction.ReportContent,
TimelineItemAction.Redact,
)
+ .sortedWith(TimelineItemActionComparator())
+ .toPersistentList()
}
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 979f041297..f700dcc6b1 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
@@ -22,7 +22,8 @@ sealed class TimelineItemAction(
) {
data object ViewInTimeline : TimelineItemAction(CommonStrings.action_view_in_timeline, CompoundDrawables.ic_compound_visibility_on)
data object Forward : TimelineItemAction(CommonStrings.action_forward, CompoundDrawables.ic_compound_forward)
- data object Copy : TimelineItemAction(CommonStrings.action_copy, CompoundDrawables.ic_compound_copy)
+ data object CopyText : TimelineItemAction(CommonStrings.action_copy_text, CompoundDrawables.ic_compound_copy)
+ data object CopyCaption : TimelineItemAction(CommonStrings.action_copy_caption, 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)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemActionComparator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemActionComparator.kt
new file mode 100644
index 0000000000..8eef2d7619
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemActionComparator.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.features.messages.impl.actionlist.model
+
+class TimelineItemActionComparator : Comparator {
+ // See order in https://www.figma.com/design/ux3tYoZV9WghC7hHT9Fhk0/Compound-iOS-Components?node-id=2946-2392
+ private val orderedList = listOf(
+ TimelineItemAction.EndPoll,
+ TimelineItemAction.ViewInTimeline,
+ TimelineItemAction.Reply,
+ TimelineItemAction.ReplyInThread,
+ TimelineItemAction.Forward,
+ TimelineItemAction.Pin,
+ TimelineItemAction.Unpin,
+ TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
+ TimelineItemAction.AddCaption,
+ TimelineItemAction.EditCaption,
+ TimelineItemAction.CopyCaption,
+ TimelineItemAction.RemoveCaption,
+ TimelineItemAction.ViewSource,
+ TimelineItemAction.ReportContent,
+ TimelineItemAction.Redact,
+ )
+
+ override fun compare(o1: TimelineItemAction, o2: TimelineItemAction): Int {
+ val index1 = orderedList.indexOf(o1)
+ val index2 = orderedList.indexOf(o2)
+ return index1.compareTo(index2)
+ }
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewNode.kt
index 2417d8346e..e89d9a5052 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewNode.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewNode.kt
@@ -20,12 +20,14 @@ import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.RoomScope
+import io.element.android.libraries.mediaviewer.api.local.LocalMediaRenderer
@ContributesNode(RoomScope::class)
class AttachmentsPreviewNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List,
presenterFactory: AttachmentsPreviewPresenter.Factory,
+ private val localMediaRenderer: LocalMediaRenderer,
) : Node(buildContext, plugins = plugins) {
data class Inputs(val attachment: Attachment) : NodeInputs
@@ -46,6 +48,7 @@ class AttachmentsPreviewNode @AssistedInject constructor(
val state = presenter.present()
AttachmentsPreviewView(
state = state,
+ localMediaRenderer = localMediaRenderer,
modifier = modifier
)
}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt
index bc3e121070..cda414934a 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt
@@ -8,7 +8,9 @@
package io.element.android.features.messages.impl.attachments.preview
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -19,10 +21,16 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
+import io.element.android.libraries.androidutils.file.safeDelete
+import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
+import io.element.android.libraries.featureflag.api.FeatureFlagService
+import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.mediaupload.api.MediaSender
+import io.element.android.libraries.mediaupload.api.MediaUploadInfo
+import io.element.android.libraries.mediaupload.api.allFiles
import io.element.android.libraries.textcomposer.model.TextEditorState
import io.element.android.libraries.textcomposer.model.rememberMarkdownTextEditorState
import kotlinx.coroutines.CancellationException
@@ -39,6 +47,7 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(
private val mediaSender: MediaSender,
private val permalinkBuilder: PermalinkBuilder,
private val temporaryUriDeleter: TemporaryUriDeleter,
+ private val featureFlagService: FeatureFlagService,
) : Presenter {
@AssistedFactory
interface Factory {
@@ -63,19 +72,64 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(
val ongoingSendAttachmentJob = remember { mutableStateOf(null) }
+ val userSentAttachment = remember { mutableStateOf(false) }
+ val allowCaption by featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionCreation).collectAsState(initial = false)
+ val showCaptionCompatibilityWarning by featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionWarning).collectAsState(initial = false)
+
+ val mediaUploadInfoState = remember { mutableStateOf>(AsyncData.Uninitialized) }
+ LaunchedEffect(Unit) {
+ preProcessAttachment(
+ attachment,
+ mediaUploadInfoState,
+ )
+ }
+
+ LaunchedEffect(userSentAttachment.value, mediaUploadInfoState.value) {
+ if (userSentAttachment.value) {
+ // User confirmed sending the attachment
+ when (val mediaUploadInfo = mediaUploadInfoState.value) {
+ is AsyncData.Success -> {
+ // Pre-processing is done, send the attachment
+ val caption = markdownTextEditorState.getMessageMarkdown(permalinkBuilder)
+ .takeIf { it.isNotEmpty() }
+ ongoingSendAttachmentJob.value = coroutineScope.launch {
+ sendPreProcessedMedia(
+ mediaUploadInfo = mediaUploadInfo.data,
+ caption = caption,
+ sendActionState = sendActionState,
+ )
+ }
+ }
+ is AsyncData.Failure -> {
+ // Pre-processing has failed, show the error
+ sendActionState.value = SendActionState.Failure(mediaUploadInfo.error)
+ }
+ AsyncData.Uninitialized,
+ is AsyncData.Loading -> {
+ // Pre-processing is still in progress, do nothing
+ }
+ }
+ }
+ }
+
fun handleEvents(attachmentsPreviewEvents: AttachmentsPreviewEvents) {
when (attachmentsPreviewEvents) {
- is AttachmentsPreviewEvents.SendAttachment -> {
- val caption = markdownTextEditorState.getMessageMarkdown(permalinkBuilder)
- .takeIf { it.isNotEmpty() }
- ongoingSendAttachmentJob.value = coroutineScope.sendAttachment(
- attachment = attachment,
- caption = caption,
- sendActionState = sendActionState,
- )
+ is AttachmentsPreviewEvents.SendAttachment -> coroutineScope.launch {
+ val useSendQueue = featureFlagService.isFeatureEnabled(FeatureFlags.MediaUploadOnSendQueue)
+ userSentAttachment.value = true
+ val instantSending = mediaUploadInfoState.value.isReady() && useSendQueue
+ sendActionState.value = if (instantSending) {
+ SendActionState.Sending.InstantSending
+ } else {
+ SendActionState.Sending.Processing
+ }
}
AttachmentsPreviewEvents.Cancel -> {
- coroutineScope.cancel(attachment)
+ coroutineScope.cancel(
+ attachment,
+ mediaUploadInfoState.value,
+ sendActionState,
+ )
}
AttachmentsPreviewEvents.ClearSendState -> {
ongoingSendAttachmentJob.value?.let {
@@ -91,60 +145,101 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(
attachment = attachment,
sendActionState = sendActionState.value,
textEditorState = textEditorState,
+ allowCaption = allowCaption,
+ showCaptionCompatibilityWarning = showCaptionCompatibilityWarning,
eventSink = ::handleEvents
)
}
- private fun CoroutineScope.sendAttachment(
+ private fun CoroutineScope.preProcessAttachment(
attachment: Attachment,
- caption: String?,
- sendActionState: MutableState,
+ mediaUploadInfoState: MutableState>,
) = launch {
when (attachment) {
is Attachment.Media -> {
- sendMedia(
+ preProcessMedia(
mediaAttachment = attachment,
- caption = caption,
- sendActionState = sendActionState,
+ mediaUploadInfoState = mediaUploadInfoState,
)
}
}
}
+ private suspend fun preProcessMedia(
+ mediaAttachment: Attachment.Media,
+ mediaUploadInfoState: MutableState>,
+ ) {
+ mediaUploadInfoState.value = AsyncData.Loading()
+ mediaSender.preProcessMedia(
+ uri = mediaAttachment.localMedia.uri,
+ mimeType = mediaAttachment.localMedia.info.mimeType,
+ ).fold(
+ onSuccess = { mediaUploadInfo ->
+ mediaUploadInfoState.value = AsyncData.Success(mediaUploadInfo)
+ },
+ onFailure = {
+ Timber.e(it, "Failed to pre-process media")
+ if (it is CancellationException) {
+ throw it
+ } else {
+ mediaUploadInfoState.value = AsyncData.Failure(it)
+ }
+ }
+ )
+ }
+
private fun CoroutineScope.cancel(
attachment: Attachment,
+ mediaUploadInfo: AsyncData,
+ sendActionState: MutableState,
) = launch {
// Delete the temporary file
when (attachment) {
is Attachment.Media -> {
temporaryUriDeleter.delete(attachment.localMedia.uri)
+ mediaUploadInfo.dataOrNull()?.let { data ->
+ cleanUp(data)
+ }
}
}
+ // Reset the sendActionState to ensure that dialog is closed before the screen
+ sendActionState.value = SendActionState.Done
onDoneListener()
}
- private suspend fun sendMedia(
- mediaAttachment: Attachment.Media,
+ private fun cleanUp(
+ mediaUploadInfo: MediaUploadInfo,
+ ) {
+ mediaUploadInfo.allFiles().forEach { file ->
+ file.safeDelete()
+ }
+ }
+
+ private suspend fun sendPreProcessedMedia(
+ mediaUploadInfo: MediaUploadInfo,
caption: String?,
sendActionState: MutableState,
) = runCatching {
val context = coroutineContext
val progressCallback = object : ProgressCallback {
override fun onProgress(current: Long, total: Long) {
+ // Note will not happen if useSendQueue is true
if (context.isActive) {
sendActionState.value = SendActionState.Sending.Uploading(current.toFloat() / total.toFloat())
}
}
}
- sendActionState.value = SendActionState.Sending.Processing
- mediaSender.sendMedia(
- uri = mediaAttachment.localMedia.uri,
- mimeType = mediaAttachment.localMedia.info.mimeType,
+ mediaSender.sendPreProcessedMedia(
+ mediaUploadInfo = mediaUploadInfo,
caption = caption,
+ formattedCaption = null,
progressCallback = progressCallback
).getOrThrow()
}.fold(
onSuccess = {
+ cleanUp(mediaUploadInfo)
+ // Reset the sendActionState to ensure that dialog is closed before the screen
+ sendActionState.value = SendActionState.Done
onDoneListener()
},
onFailure = { error ->
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt
index 5fed2acfb2..739efa8d24 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt
@@ -15,11 +15,10 @@ data class AttachmentsPreviewState(
val attachment: Attachment,
val sendActionState: SendActionState,
val textEditorState: TextEditorState,
+ val allowCaption: Boolean,
+ val showCaptionCompatibilityWarning: Boolean,
val eventSink: (AttachmentsPreviewEvents) -> Unit
-) {
- // Keep the val to eventually set to false for some mimetypes.
- val allowCaption: Boolean = true
-}
+)
@Immutable
sealed interface SendActionState {
@@ -27,9 +26,11 @@ sealed interface SendActionState {
@Immutable
sealed interface Sending : SendActionState {
+ data object InstantSending : Sending
data object Processing : Sending
data class Uploading(val progress: Float) : Sending
}
data class Failure(val error: Throwable) : SendActionState
+ data object Done : SendActionState
}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt
index 78f3ffc81a..b718936a1c 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt
@@ -10,12 +10,9 @@ package io.element.android.features.messages.impl.attachments.preview
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.core.net.toUri
import io.element.android.features.messages.impl.attachments.Attachment
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.local.aVideoMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anApkMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anAudioMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anImageMediaInfo
import io.element.android.libraries.textcomposer.model.TextEditorState
import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown
@@ -23,11 +20,11 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider
get() = sequenceOf(
anAttachmentsPreviewState(),
- anAttachmentsPreviewState(mediaInfo = aVideoMediaInfo()),
- anAttachmentsPreviewState(mediaInfo = anAudioMediaInfo()),
- anAttachmentsPreviewState(mediaInfo = anApkMediaInfo()),
+ anAttachmentsPreviewState(sendActionState = SendActionState.Sending.Processing),
anAttachmentsPreviewState(sendActionState = SendActionState.Sending.Uploading(0.5f)),
anAttachmentsPreviewState(sendActionState = SendActionState.Failure(RuntimeException("error"))),
+ anAttachmentsPreviewState(allowCaption = false),
+ anAttachmentsPreviewState(showCaptionCompatibilityWarning = true),
)
}
@@ -35,11 +32,15 @@ fun anAttachmentsPreviewState(
mediaInfo: MediaInfo = anImageMediaInfo(),
textEditorState: TextEditorState = aTextEditorStateMarkdown(),
sendActionState: SendActionState = SendActionState.Idle,
+ allowCaption: Boolean = true,
+ showCaptionCompatibilityWarning: Boolean = true,
) = AttachmentsPreviewState(
attachment = Attachment.Media(
localMedia = LocalMedia("file://path".toUri(), mediaInfo),
),
sendActionState = sendActionState,
textEditorState = textEditorState,
+ allowCaption = allowCaption,
+ showCaptionCompatibilityWarning = showCaptionCompatibilityWarning,
eventSink = {}
)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt
index 1380add329..a91baaad8c 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt
@@ -8,18 +8,22 @@
package io.element.android.features.messages.impl.attachments.preview
import androidx.activity.compose.BackHandler
+import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@@ -34,20 +38,20 @@ import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar
-import io.element.android.libraries.mediaviewer.api.local.LocalMediaView
-import io.element.android.libraries.mediaviewer.api.local.rememberLocalMediaViewState
+import io.element.android.libraries.designsystem.utils.CommonDrawables
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+import io.element.android.libraries.mediaviewer.api.local.LocalMediaRenderer
import io.element.android.libraries.textcomposer.TextComposer
import io.element.android.libraries.textcomposer.model.MessageComposerMode
import io.element.android.libraries.textcomposer.model.VoiceMessageState
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.wysiwyg.display.TextDisplay
-import me.saket.telephoto.zoomable.ZoomSpec
-import me.saket.telephoto.zoomable.rememberZoomableState
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AttachmentsPreviewView(
state: AttachmentsPreviewState,
+ localMediaRenderer: LocalMediaRenderer,
modifier: Modifier = Modifier,
) {
fun postSendAttachment() {
@@ -79,9 +83,11 @@ fun AttachmentsPreviewView(
title = {},
)
}
- ) {
+ ) { paddingValues ->
AttachmentPreviewContent(
+ modifier = Modifier.padding(paddingValues),
state = state,
+ localMediaRenderer = localMediaRenderer,
onSendClick = ::postSendAttachment,
)
}
@@ -99,12 +105,17 @@ private fun AttachmentSendStateView(
onRetryClick: () -> Unit
) {
when (sendActionState) {
- is SendActionState.Sending -> {
+ is SendActionState.Sending.Processing -> {
ProgressDialog(
- type = when (sendActionState) {
- is SendActionState.Sending.Uploading -> ProgressDialogType.Determinate(sendActionState.progress)
- SendActionState.Sending.Processing -> ProgressDialogType.Indeterminate
- },
+ type = ProgressDialogType.Indeterminate,
+ text = stringResource(id = CommonStrings.common_sending),
+ showCancelButton = true,
+ onDismissRequest = onDismissClick,
+ )
+ }
+ is SendActionState.Sending.Uploading -> {
+ ProgressDialog(
+ type = ProgressDialogType.Determinate(sendActionState.progress),
text = stringResource(id = CommonStrings.common_sending),
showCancelButton = true,
onDismissRequest = onDismissClick,
@@ -124,30 +135,23 @@ private fun AttachmentSendStateView(
@Composable
private fun AttachmentPreviewContent(
state: AttachmentsPreviewState,
+ localMediaRenderer: LocalMediaRenderer,
onSendClick: () -> Unit,
+ modifier: Modifier = Modifier,
) {
- Box(
- modifier = Modifier
+ Column(
+ modifier = modifier
.fillMaxSize()
.navigationBarsPadding(),
) {
Box(
- modifier = Modifier.fillMaxSize(),
+ modifier = Modifier
+ .weight(1f),
contentAlignment = Alignment.Center
) {
when (val attachment = state.attachment) {
is Attachment.Media -> {
- val localMediaViewState = rememberLocalMediaViewState(
- zoomableState = rememberZoomableState(
- zoomSpec = ZoomSpec(maxZoomFactor = 4f, preventOverOrUnderZoom = false)
- )
- )
- LocalMediaView(
- modifier = Modifier.fillMaxSize(),
- localMedia = attachment.localMedia,
- localMediaViewState = localMediaViewState,
- onClick = {}
- )
+ localMediaRenderer.Render(attachment.localMedia)
}
}
}
@@ -158,7 +162,6 @@ private fun AttachmentPreviewContent(
.fillMaxWidth()
.background(ElementTheme.colors.bgCanvasDefault)
.height(IntrinsicSize.Min)
- .align(Alignment.BottomCenter)
.imePadding(),
)
}
@@ -174,7 +177,10 @@ private fun AttachmentsPreviewBottomActions(
modifier = modifier,
state = state.textEditorState,
voiceMessageState = VoiceMessageState.Idle,
- composerMode = MessageComposerMode.Attachment(state.allowCaption),
+ composerMode = MessageComposerMode.Attachment(
+ allowCaption = state.allowCaption,
+ showCaptionCompatibilityWarning = state.showCaptionCompatibilityWarning,
+ ),
onRequestFocus = {},
onSendMessage = onSendClick,
showTextFormatting = false,
@@ -200,5 +206,15 @@ private fun AttachmentsPreviewBottomActions(
internal fun AttachmentsPreviewViewPreview(@PreviewParameter(AttachmentsPreviewStateProvider::class) state: AttachmentsPreviewState) = ElementPreviewDark {
AttachmentsPreviewView(
state = state,
+ localMediaRenderer = object : LocalMediaRenderer {
+ @Composable
+ override fun Render(localMedia: LocalMedia) {
+ Image(
+ painter = painterResource(id = CommonDrawables.sample_background),
+ modifier = Modifier.fillMaxSize(),
+ contentDescription = null,
+ )
+ }
+ }
)
}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt
index 688b392fb6..148aa3d2ad 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt
@@ -19,6 +19,7 @@ import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
+import io.element.android.features.messages.impl.actionlist.ActionListPresenter
import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.model.TimelineItem
@@ -35,6 +36,7 @@ class PinnedMessagesListNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List,
presenterFactory: PinnedMessagesListPresenter.Factory,
+ actionListPresenterFactory: ActionListPresenter.Factory,
private val timelineItemPresenterFactories: TimelineItemPresenterFactories,
private val permalinkParser: PermalinkParser,
) : Node(buildContext, plugins = plugins), PinnedMessagesListNavigator {
@@ -47,7 +49,10 @@ class PinnedMessagesListNode @AssistedInject constructor(
fun onForwardEventClick(eventId: EventId)
}
- private val presenter = presenterFactory.create(this)
+ private val presenter = presenterFactory.create(
+ navigator = this,
+ actionListPresenter = actionListPresenterFactory.create(PinnedMessagesListTimelineActionPostProcessor())
+ )
private val callbacks = plugins()
private fun onEventClick(event: TimelineItem.Event) {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt
index 4673ae57b2..eb3412b30c 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt
@@ -23,7 +23,7 @@ import dagger.assisted.AssistedInject
import im.vector.app.features.analytics.plan.Interaction
import im.vector.app.features.analytics.plan.PinUnpinAction
import io.element.android.features.messages.impl.UserEventPermissions
-import io.element.android.features.messages.impl.actionlist.ActionListPresenter
+import io.element.android.features.messages.impl.actionlist.ActionListState
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProvider
import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
@@ -64,13 +64,16 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
private val timelineProvider: PinnedEventsTimelineProvider,
private val timelineProtectionPresenter: Presenter,
private val snackbarDispatcher: SnackbarDispatcher,
- actionListPresenterFactory: ActionListPresenter.Factory,
+ @Assisted private val actionListPresenter: Presenter,
private val appCoroutineScope: CoroutineScope,
private val analyticsService: AnalyticsService,
) : Presenter {
@AssistedFactory
interface Factory {
- fun create(navigator: PinnedMessagesListNavigator): PinnedMessagesListPresenter
+ fun create(
+ navigator: PinnedMessagesListNavigator,
+ actionListPresenter: Presenter,
+ ): PinnedMessagesListPresenter
}
private val timelineItemsFactory: TimelineItemsFactory = timelineItemsFactoryCreator.create(
@@ -79,7 +82,6 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
computeReactions = false,
)
)
- private val actionListPresenter = actionListPresenterFactory.create(PinnedMessagesListTimelineActionPostProcessor())
@Composable
override fun present(): PinnedMessagesListState {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProvider.kt
index 5aab1a5bf1..2234aa09a9 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProvider.kt
@@ -63,6 +63,7 @@ class DefaultHtmlConverterProvider @Inject constructor(
return TextDisplay.Custom(mentionSpan)
}
},
+ isEditor = false,
isMention = { _, url -> mentionDetector?.isMention(url).orFalse() }
).apply {
configureWith(editorStyle)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt
index e84f7ccbc2..b91b4ccc17 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt
@@ -40,6 +40,15 @@ fun TimelineItemEncryptedView(
UtdCause.UnknownDevice -> {
CommonStrings.common_unable_to_decrypt_insecure_device to CompoundDrawables.ic_compound_block
}
+ UtdCause.HistoricalMessage -> {
+ CommonStrings.timeline_decryption_failure_historical_event_no_key_backup to CompoundDrawables.ic_compound_block
+ }
+ UtdCause.WithheldUnverifiedOrInsecureDevice -> {
+ CommonStrings.timeline_decryption_failure_withheld_unverified to CompoundDrawables.ic_compound_block
+ }
+ UtdCause.WithheldBySender -> {
+ CommonStrings.timeline_decryption_failure_unable_to_decrypt to CompoundDrawables.ic_compound_error
+ }
else -> {
CommonStrings.common_waiting_for_decryption_key to CompoundDrawables.ic_compound_time
}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemInformativeView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemInformativeView.kt
index 58f2f25712..304527e806 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemInformativeView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemInformativeView.kt
@@ -8,8 +8,10 @@
package io.element.android.features.messages.impl.timeline.components.event
import androidx.annotation.DrawableRes
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
@@ -44,14 +46,18 @@ fun TimelineItemInformativeView(
)
)
},
- verticalAlignment = Alignment.CenterVertically,
) {
- Icon(
- resourceId = iconResourceId,
- tint = MaterialTheme.colorScheme.secondary,
- contentDescription = iconDescription,
- modifier = Modifier.size(16.dp)
- )
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier.height(20.dp)
+ ) {
+ Icon(
+ resourceId = iconResourceId,
+ tint = MaterialTheme.colorScheme.secondary,
+ contentDescription = iconDescription,
+ modifier = Modifier.size(16.dp)
+ )
+ }
Spacer(modifier = Modifier.width(4.dp))
Text(
fontStyle = FontStyle.Italic,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt
index 7f6f8ee436..3100d90d45 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt
@@ -12,10 +12,10 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.libraries.matrix.api.core.EventId
open class ReactionSummaryStateProvider : PreviewParameterProvider {
- override val values = sequenceOf(anActionListState())
+ override val values = sequenceOf(aReactionSummaryState())
}
-fun anActionListState(): ReactionSummaryState {
+fun aReactionSummaryState(): ReactionSummaryState {
val reactions = aTimelineItemReactions(8, true).reactions
return ReactionSummaryState(
target = ReactionSummaryState.Summary(
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt
index 867cb694db..c2515560f5 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt
@@ -147,7 +147,7 @@ class TimelineItemContentMessageFactory @Inject constructor(
formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(),
isEdited = content.isEdited,
thumbnailSource = messageType.info?.thumbnailSource,
- videoSource = messageType.source,
+ mediaSource = messageType.source,
mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream,
width = messageType.info?.width?.toInt(),
height = messageType.info?.height?.toInt(),
@@ -186,6 +186,8 @@ class TimelineItemContentMessageFactory @Inject constructor(
duration = messageType.info?.duration ?: Duration.ZERO,
mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream,
waveform = messageType.details?.waveform?.toImmutableList() ?: persistentListOf(),
+ formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0),
+ fileExtension = fileExtensionExtractor.extractFromName(messageType.filename)
)
}
false -> {
@@ -211,7 +213,7 @@ class TimelineItemContentMessageFactory @Inject constructor(
formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(),
isEdited = content.isEdited,
thumbnailSource = messageType.info?.thumbnailSource,
- fileSource = messageType.source,
+ mediaSource = messageType.source,
mimeType = messageType.info?.mimetype ?: MimeTypes.fromFileExtension(fileExtension),
formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0),
fileExtension = fileExtension
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt
index 46176cc474..a3b2061b92 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt
@@ -17,10 +17,10 @@ data class TimelineItemAudioContent(
override val formattedCaption: CharSequence?,
override val isEdited: Boolean,
val duration: Duration,
- val mediaSource: MediaSource,
- val mimeType: String,
- val formattedFileSize: String,
- val fileExtension: String,
+ override val mediaSource: MediaSource,
+ override val mimeType: String,
+ override val formattedFileSize: String,
+ override val fileExtension: String,
) : TimelineItemEventContentWithAttachment {
val fileExtensionAndSize =
formatFileExtensionAndSize(
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEncryptedContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEncryptedContentProvider.kt
index 7aa44e03f0..b312024ebb 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEncryptedContentProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEncryptedContentProvider.kt
@@ -33,6 +33,24 @@ open class TimelineItemEncryptedContentProvider : PreviewParameterProvider,
) : TimelineItemEventContentWithAttachment {
override val type: String = "TimelineItemAudioContent"
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt
index bd7308d970..0c3fd246ca 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt
@@ -53,4 +53,6 @@ fun aTimelineItemVoiceContent(
mediaSource = mediaSource,
mimeType = mimeType,
waveform = waveform.toPersistentList(),
+ formattedFileSize = "1.0 MB",
+ fileExtension = "ogg",
)
diff --git a/features/messages/impl/src/main/res/values-de/translations.xml b/features/messages/impl/src/main/res/values-de/translations.xml
index 785a615cab..e235088a60 100644
--- a/features/messages/impl/src/main/res/values-de/translations.xml
+++ b/features/messages/impl/src/main/res/values-de/translations.xml
@@ -31,6 +31,7 @@
"Emoji hinzufügen"
"Dies ist der Anfang von %1$s."
"Dies ist der Anfang dieses Gesprächs."
+ "Anruftyp wird nicht unterstützt. Fragen Sie nach, ob der Anrufer die neue Element X-App verwenden kann."
"Weniger anzeigen"
"Nachricht wurde kopiert"
"Du bist nicht berechtigt, in diesem Raum zu schreiben"
diff --git a/features/messages/impl/src/main/res/values-fr/translations.xml b/features/messages/impl/src/main/res/values-fr/translations.xml
index ab47aed0ca..132d175eb8 100644
--- a/features/messages/impl/src/main/res/values-fr/translations.xml
+++ b/features/messages/impl/src/main/res/values-fr/translations.xml
@@ -31,6 +31,7 @@
"Ajouter un émoji"
"Ceci est le début de %1$s."
"Ceci est le début de cette conversation."
+ "Appel non pris en charge. Demandez à l’appelant s’il peut utiliser la nouvelle application Element X pour vous appeler."
"Afficher moins"
"Message copié"
"Vous n’êtes pas autorisé à publier dans ce salon"
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 61606a51de..8cb7464a9a 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
@@ -14,7 +14,7 @@ import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.PinUnpinAction
import io.element.android.features.messages.impl.actionlist.ActionListEvents
import io.element.android.features.messages.impl.actionlist.ActionListState
-import io.element.android.features.messages.impl.actionlist.FakeActionListPresenter
+import io.element.android.features.messages.impl.actionlist.anActionListState
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.crypto.identity.anIdentityChangeState
import io.element.android.features.messages.impl.fixtures.aMessageEvent
@@ -45,6 +45,8 @@ import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
+import io.element.android.libraries.featureflag.api.FeatureFlagService
+import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
@@ -242,7 +244,7 @@ class MessagesPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Copy, event))
+ initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.CopyText, event))
skipItems(2)
assertThat(clipboardHelper.clipboardContents).isEqualTo((event.content as TimelineItemTextContent).body)
}
@@ -369,7 +371,7 @@ class MessagesPresenterTest {
formattedCaption = null,
isEdited = false,
duration = 10.milliseconds,
- videoSource = MediaSource(AN_AVATAR_URL),
+ mediaSource = MediaSource(AN_AVATAR_URL),
thumbnailSource = MediaSource(AN_AVATAR_URL),
mimeType = MimeTypes.Mp4,
blurHash = null,
@@ -411,7 +413,7 @@ class MessagesPresenterTest {
caption = null,
isEdited = false,
formattedCaption = null,
- fileSource = MediaSource(AN_AVATAR_URL),
+ mediaSource = MediaSource(AN_AVATAR_URL),
thumbnailSource = MediaSource(AN_AVATAR_URL),
formattedFileSize = "10 MB",
mimeType = MimeTypes.Pdf,
@@ -1007,6 +1009,37 @@ class MessagesPresenterTest {
composerMode = MessageComposerMode.EditCaption(
eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
content = A_CAPTION,
+ showCaptionCompatibilityWarning = true,
+ )
+ )
+ )
+ }
+ }
+
+ @Test
+ fun `present - handle action edit caption without warning`() = runTest {
+ val messageEvent = aMessageEvent(
+ content = aTimelineItemImageContent(
+ caption = A_CAPTION,
+ )
+ )
+ val composerRecorder = EventsRecorder()
+ val presenter = createMessagesPresenter(
+ messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
+ featureFlagService = FakeFeatureFlagService(
+ initialState = mapOf(FeatureFlags.MediaCaptionWarning.key to false)
+ )
+ )
+ presenter.test {
+ val initialState = awaitItem()
+ initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EditCaption, messageEvent))
+ awaitItem()
+ composerRecorder.assertSingle(
+ MessageComposerEvents.SetMode(
+ composerMode = MessageComposerMode.EditCaption(
+ eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
+ content = A_CAPTION,
+ showCaptionCompatibilityWarning = false,
)
)
)
@@ -1033,6 +1066,37 @@ class MessagesPresenterTest {
composerMode = MessageComposerMode.EditCaption(
eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
content = "",
+ showCaptionCompatibilityWarning = true,
+ )
+ )
+ )
+ }
+ }
+
+ @Test
+ fun `present - handle action add caption without warning`() = runTest {
+ val composerRecorder = EventsRecorder()
+ val presenter = createMessagesPresenter(
+ messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
+ featureFlagService = FakeFeatureFlagService(
+ initialState = mapOf(FeatureFlags.MediaCaptionWarning.key to false)
+ )
+ )
+ val messageEvent = aMessageEvent(
+ content = aTimelineItemImageContent(
+ caption = null,
+ )
+ )
+ presenter.test {
+ val initialState = awaitItem()
+ initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.AddCaption, messageEvent))
+ awaitItem()
+ composerRecorder.assertSingle(
+ MessageComposerEvents.SetMode(
+ composerMode = MessageComposerMode.EditCaption(
+ eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
+ content = "",
+ showCaptionCompatibilityWarning = false,
)
)
)
@@ -1097,6 +1161,7 @@ class MessagesPresenterTest {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
+ featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
timelineEventSink: (TimelineEvents) -> Unit = {},
@@ -1109,14 +1174,13 @@ class MessagesPresenterTest {
},
actionListEventSink: (ActionListEvents) -> Unit = {},
): MessagesPresenter {
- val featureFlagService = FakeFeatureFlagService()
return MessagesPresenter(
room = matrixRoom,
composerPresenter = messageComposerPresenter,
voiceMessageComposerPresenter = { aVoiceMessageComposerState() },
timelinePresenter = { aTimelineState(eventSink = timelineEventSink) },
timelineProtectionPresenter = { aTimelineProtectionState() },
- actionListPresenterFactory = FakeActionListPresenter.Factory(actionListEventSink),
+ actionListPresenter = { anActionListState(eventSink = actionListEventSink) },
customReactionPresenter = { aCustomReactionState() },
reactionSummaryPresenter = { aReactionSummaryState() },
readReceiptBottomSheetPresenter = { aReadReceiptBottomSheetState() },
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 b79468f820..49db6f6c95 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
@@ -26,6 +26,8 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent
import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList
+import io.element.android.libraries.featureflag.api.FeatureFlags
+import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.test.AN_EVENT_ID
@@ -174,8 +176,8 @@ class ActionListPresenterTest {
TimelineItemAction.Reply,
TimelineItemAction.Forward,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
)
@@ -219,8 +221,8 @@ class ActionListPresenterTest {
TimelineItemAction.ReplyInThread,
TimelineItemAction.Forward,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
)
@@ -266,8 +268,8 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Forward,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
)
@@ -312,8 +314,8 @@ class ActionListPresenterTest {
TimelineItemAction.Reply,
TimelineItemAction.Forward,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
TimelineItemAction.Redact,
@@ -359,8 +361,8 @@ class ActionListPresenterTest {
TimelineItemAction.Reply,
TimelineItemAction.Forward,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
TimelineItemAction.Redact,
@@ -406,10 +408,10 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.Edit,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.Redact,
)
@@ -451,10 +453,10 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.ReplyInThread,
TimelineItemAction.Forward,
- TimelineItemAction.Edit,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.Redact,
)
@@ -499,10 +501,10 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.Edit,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
)
)
@@ -545,7 +547,58 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
+ TimelineItemAction.Pin,
+ TimelineItemAction.CopyLink,
TimelineItemAction.AddCaption,
+ TimelineItemAction.ViewSource,
+ TimelineItemAction.Redact,
+ )
+ )
+ )
+ initialState.eventSink.invoke(ActionListEvents.Clear)
+ assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None)
+ }
+ }
+
+ @Test
+ fun `present - compute for a media item - caption disabled`() = runTest {
+ val presenter = createActionListPresenter(
+ isDeveloperModeEnabled = true,
+ isPinFeatureEnabled = true,
+ allowCaption = false,
+ )
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ val messageEvent = aMessageEvent(
+ isMine = true,
+ isEditable = true,
+ content = aTimelineItemImageContent(),
+ )
+ initialState.eventSink.invoke(
+ ActionListEvents.ComputeForMessage(
+ event = messageEvent,
+ userEventPermissions = aUserEventPermissions(
+ canRedactOwn = true,
+ canRedactOther = false,
+ canSendMessage = true,
+ canSendReaction = true,
+ canPinUnpin = true,
+ ),
+ )
+ )
+ val successState = awaitItem()
+ assertThat(successState.target).isEqualTo(
+ ActionListState.Target.Success(
+ event = messageEvent,
+ displayEmojiReactions = true,
+ verifiedUserSendFailure = VerifiedUserSendFailure.None,
+ actions = persistentListOf(
+ TimelineItemAction.Reply,
+ TimelineItemAction.Forward,
+ // Not here
+ // TimelineItemAction.AddCaption,
TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
TimelineItemAction.ViewSource,
@@ -593,10 +646,11 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.EditCaption,
- TimelineItemAction.RemoveCaption,
TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
+ TimelineItemAction.EditCaption,
+ TimelineItemAction.CopyCaption,
+ TimelineItemAction.RemoveCaption,
TimelineItemAction.ViewSource,
TimelineItemAction.Redact,
)
@@ -607,6 +661,54 @@ class ActionListPresenterTest {
}
}
+ @Test
+ fun `present - compute for a media with caption item - other user event`() = runTest {
+ val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ val messageEvent = aMessageEvent(
+ isMine = false,
+ isEditable = false,
+ content = aTimelineItemImageContent(
+ caption = A_CAPTION,
+ ),
+ )
+ initialState.eventSink.invoke(
+ ActionListEvents.ComputeForMessage(
+ event = messageEvent,
+ userEventPermissions = aUserEventPermissions(
+ canRedactOwn = true,
+ canRedactOther = false,
+ canSendMessage = true,
+ canSendReaction = true,
+ canPinUnpin = true,
+ ),
+ )
+ )
+ val successState = awaitItem()
+ assertThat(successState.target).isEqualTo(
+ ActionListState.Target.Success(
+ event = messageEvent,
+ displayEmojiReactions = true,
+ verifiedUserSendFailure = VerifiedUserSendFailure.None,
+ actions = persistentListOf(
+ TimelineItemAction.Reply,
+ TimelineItemAction.Forward,
+ TimelineItemAction.Pin,
+ TimelineItemAction.CopyLink,
+ TimelineItemAction.CopyCaption,
+ TimelineItemAction.ViewSource,
+ TimelineItemAction.ReportContent,
+ )
+ )
+ )
+ initialState.eventSink.invoke(ActionListEvents.Clear)
+ assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None)
+ }
+ }
+
@Test
fun `present - compute for a state item in debug build`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
@@ -711,10 +813,10 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.Edit,
TimelineItemAction.Pin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
TimelineItemAction.Redact,
)
)
@@ -758,9 +860,9 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.Edit,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.Redact,
)
@@ -812,10 +914,10 @@ class ActionListPresenterTest {
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
- TimelineItemAction.Edit,
TimelineItemAction.Unpin,
- TimelineItemAction.Copy,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
+ TimelineItemAction.CopyText,
TimelineItemAction.ViewSource,
TimelineItemAction.Redact,
)
@@ -908,7 +1010,7 @@ class ActionListPresenterTest {
verifiedUserSendFailure = VerifiedUserSendFailure.None,
actions = persistentListOf(
TimelineItemAction.Edit,
- TimelineItemAction.Copy,
+ TimelineItemAction.CopyText,
TimelineItemAction.Redact,
)
)
@@ -947,11 +1049,11 @@ class ActionListPresenterTest {
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
actions = persistentListOf(
- TimelineItemAction.Reply,
- TimelineItemAction.Edit,
TimelineItemAction.EndPoll,
+ TimelineItemAction.Reply,
TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
+ TimelineItemAction.Edit,
TimelineItemAction.Redact,
)
)
@@ -990,8 +1092,8 @@ class ActionListPresenterTest {
displayEmojiReactions = true,
verifiedUserSendFailure = VerifiedUserSendFailure.None,
actions = persistentListOf(
- TimelineItemAction.Reply,
TimelineItemAction.EndPoll,
+ TimelineItemAction.Reply,
TimelineItemAction.Pin,
TimelineItemAction.CopyLink,
TimelineItemAction.Redact,
@@ -1052,7 +1154,9 @@ class ActionListPresenterTest {
val messageEvent = aMessageEvent(
isMine = true,
isEditable = false,
- content = aTimelineItemVoiceContent(),
+ content = aTimelineItemVoiceContent(
+ caption = null,
+ ),
)
initialState.eventSink.invoke(
ActionListEvents.ComputeForMessage(
@@ -1151,6 +1255,7 @@ private fun createActionListPresenter(
isDeveloperModeEnabled: Boolean,
isPinFeatureEnabled: Boolean,
room: MatrixRoom = FakeMatrixRoom(),
+ allowCaption: Boolean = true,
): ActionListPresenter {
val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled)
return DefaultActionListPresenter(
@@ -1158,6 +1263,11 @@ private fun createActionListPresenter(
appPreferencesStore = preferencesStore,
isPinnedMessagesFeatureEnabled = { isPinFeatureEnabled },
room = room,
- userSendFailureFactory = VerifiedUserSendFailureFactory(room)
+ userSendFailureFactory = VerifiedUserSendFailureFactory(room),
+ featureFlagService = FakeFeatureFlagService(
+ initialState = mapOf(
+ FeatureFlags.MediaCaptionCreation.key to allowCaption,
+ ),
+ )
)
}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/FakeActionListPresenter.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/FakeActionListPresenter.kt
deleted file mode 100644
index 14f62a1daf..0000000000
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/FakeActionListPresenter.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2024 New Vector Ltd.
- *
- * SPDX-License-Identifier: AGPL-3.0-only
- * Please see LICENSE in the repository root for full details.
- */
-
-package io.element.android.features.messages.impl.actionlist
-
-import androidx.compose.runtime.Composable
-import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
-
-class FakeActionListPresenter(private val eventSink: (ActionListEvents) -> Unit = {}) : ActionListPresenter {
- class Factory(private val eventSink: (ActionListEvents) -> Unit = {}) : ActionListPresenter.Factory {
- override fun create(postProcessor: TimelineItemActionPostProcessor): ActionListPresenter {
- return FakeActionListPresenter(eventSink)
- }
- }
-
- @Composable
- override fun present(): ActionListState {
- return anActionListState(eventSink = eventSink)
- }
-}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt
index 4f35c592f1..92e43aa03a 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt
@@ -20,6 +20,8 @@ import io.element.android.features.messages.impl.attachments.preview.OnDoneListe
import io.element.android.features.messages.impl.attachments.preview.SendActionState
import io.element.android.features.messages.impl.fixtures.aMediaAttachment
import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
+import io.element.android.libraries.featureflag.api.FeatureFlags
+import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.media.AudioInfo
import io.element.android.libraries.matrix.api.media.FileInfo
@@ -40,10 +42,12 @@ import io.element.android.libraries.preferences.test.InMemorySessionPreferencesS
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.fake.FakeTemporaryUriDeleter
import io.element.android.tests.testutils.lambda.any
+import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test
import io.mockk.mockk
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
@@ -60,6 +64,40 @@ class AttachmentsPreviewPresenterTest {
private val mockMediaUrl: Uri = mockk("localMediaUri")
+ @Test
+ fun `present - initial state`() = runTest {
+ createAttachmentsPreviewPresenter().test {
+ skipItems(1)
+ val initialState = awaitItem()
+ assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(initialState.allowCaption).isTrue()
+ assertThat(initialState.showCaptionCompatibilityWarning).isTrue()
+ }
+ }
+
+ @Test
+ fun `present - initial state no caption warning`() = runTest {
+ createAttachmentsPreviewPresenter(
+ showCaptionCompatibilityWarning = false,
+ ).test {
+ skipItems(1)
+ val initialState = awaitItem()
+ assertThat(initialState.showCaptionCompatibilityWarning).isFalse()
+ }
+ }
+
+ @Test
+ fun `present - initial state - caption not allowed`() = runTest {
+ createAttachmentsPreviewPresenter(
+ allowCaption = false,
+ ).test {
+ skipItems(1)
+ val initialState = awaitItem()
+ assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(initialState.allowCaption).isFalse()
+ }
+ }
+
@Test
fun `present - send media success scenario`() = runTest {
val sendFileResult = lambdaRecorder> { _, _, _, _, _ ->
@@ -84,16 +122,142 @@ class AttachmentsPreviewPresenterTest {
val initialState = awaitItem()
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(0f))
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(0.5f))
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(1f))
- advanceUntilIdle()
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
sendFileResult.assertions().isCalledOnce()
onDoneListener.assertions().isCalledOnce()
}
}
+ @Test
+ fun `present - send media after pre-processing success scenario`() = runTest {
+ val sendFileResult = lambdaRecorder> { _, _, _, _, _ ->
+ Result.success(FakeMediaUploadHandler())
+ }
+ val room = FakeMatrixRoom(
+ sendFileResult = sendFileResult,
+ )
+ val onDoneListener = lambdaRecorder { }
+ val processLatch = CompletableDeferred()
+ val presenter = createAttachmentsPreviewPresenter(
+ room = room,
+ mediaPreProcessor = FakeMediaPreProcessor(
+ processLatch = processLatch,
+ ),
+ onDoneListener = { onDoneListener() },
+ )
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
+ // Pre-processing finishes
+ processLatch.complete(Unit)
+ advanceUntilIdle()
+ initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.InstantSending)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
+ sendFileResult.assertions().isCalledOnce()
+ onDoneListener.assertions().isCalledOnce()
+ }
+ }
+
+ @Test
+ fun `present - send media before pre-processing success scenario`() = runTest {
+ val sendFileResult = lambdaRecorder> { _, _, _, _, _ ->
+ Result.success(FakeMediaUploadHandler())
+ }
+ val room = FakeMatrixRoom(
+ sendFileResult = sendFileResult,
+ )
+ val onDoneListener = lambdaRecorder { }
+ val processLatch = CompletableDeferred()
+ val presenter = createAttachmentsPreviewPresenter(
+ room = room,
+ mediaPreProcessor = FakeMediaPreProcessor(
+ processLatch = processLatch,
+ ),
+ onDoneListener = { onDoneListener() },
+ )
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
+ initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ // Pre-processing finishes
+ processLatch.complete(Unit)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
+ sendFileResult.assertions().isCalledOnce()
+ onDoneListener.assertions().isCalledOnce()
+ }
+ }
+
+ @Test
+ fun `present - send media with pre-processing failure after user sends media`() = runTest {
+ val room = FakeMatrixRoom()
+ val onDoneListener = lambdaRecorder { }
+ val processLatch = CompletableDeferred()
+ val presenter = createAttachmentsPreviewPresenter(
+ room = room,
+ mediaPreProcessor = FakeMediaPreProcessor().apply {
+ givenResult(Result.failure(Exception()))
+ },
+ onDoneListener = { onDoneListener() },
+ )
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
+ initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ // Pre-processing finishes
+ processLatch.complete(Unit)
+ assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Failure::class.java)
+ }
+ }
+
+ @Test
+ fun `present - send media with pre-processing failure before user sends media`() = runTest {
+ val room = FakeMatrixRoom()
+ val onDoneListener = lambdaRecorder { }
+ val processLatch = CompletableDeferred()
+ val presenter = createAttachmentsPreviewPresenter(
+ room = room,
+ mediaPreProcessor = FakeMediaPreProcessor().apply {
+ givenResult(Result.failure(Exception()))
+ },
+ onDoneListener = { onDoneListener() },
+ )
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
+ // Pre-processing finishes
+ processLatch.complete(Unit)
+ advanceUntilIdle()
+ initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.InstantSending)
+ assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Failure::class.java)
+ }
+ }
+
@Test
fun `present - cancel scenario`() = runTest {
val onDoneListener = lambdaRecorder { }
@@ -108,6 +272,8 @@ class AttachmentsPreviewPresenterTest {
val initialState = awaitItem()
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.eventSink(AttachmentsPreviewEvents.Cancel)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
deleteCallback.assertions().isCalledOnce()
onDoneListener.assertions().isCalledOnce()
}
@@ -138,8 +304,10 @@ class AttachmentsPreviewPresenterTest {
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.textEditorState.setMarkdown(A_CAPTION)
initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
- advanceUntilIdle()
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
sendImageResult.assertions().isCalledOnce().with(
any(),
any(),
@@ -177,8 +345,10 @@ class AttachmentsPreviewPresenterTest {
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.textEditorState.setMarkdown(A_CAPTION)
initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
- advanceUntilIdle()
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
sendVideoResult.assertions().isCalledOnce().with(
any(),
any(),
@@ -214,8 +384,10 @@ class AttachmentsPreviewPresenterTest {
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.textEditorState.setMarkdown(A_CAPTION)
initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
- advanceUntilIdle()
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done)
sendAudioResult.assertions().isCalledOnce().with(
any(),
any(),
@@ -243,8 +415,9 @@ class AttachmentsPreviewPresenterTest {
val initialState = awaitItem()
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
- val loadingState = awaitItem()
- assertThat(loadingState.sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
val failureState = awaitItem()
assertThat(failureState.sendActionState).isEqualTo(SendActionState.Failure(failure))
sendFileResult.assertions().isCalledOnce()
@@ -263,6 +436,8 @@ class AttachmentsPreviewPresenterTest {
val initialState = awaitItem()
assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle)
initialState.eventSink(AttachmentsPreviewEvents.SendAttachment)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
+ assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing)
initialState.eventSink(AttachmentsPreviewEvents.ClearSendState)
assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Idle)
@@ -277,7 +452,10 @@ class AttachmentsPreviewPresenterTest {
permalinkBuilder: PermalinkBuilder = FakePermalinkBuilder(),
mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(),
temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(),
- onDoneListener: OnDoneListener = OnDoneListener {},
+ onDoneListener: OnDoneListener = OnDoneListener { lambdaError() },
+ mediaUploadOnSendQueueEnabled: Boolean = true,
+ allowCaption: Boolean = true,
+ showCaptionCompatibilityWarning: Boolean = true,
): AttachmentsPreviewPresenter {
return AttachmentsPreviewPresenter(
attachment = aMediaAttachment(localMedia),
@@ -285,6 +463,13 @@ class AttachmentsPreviewPresenterTest {
mediaSender = MediaSender(mediaPreProcessor, room, InMemorySessionPreferencesStore()),
permalinkBuilder = permalinkBuilder,
temporaryUriDeleter = temporaryUriDeleter,
+ featureFlagService = FakeFeatureFlagService(
+ initialState = mapOf(
+ FeatureFlags.MediaUploadOnSendQueue.key to mediaUploadOnSendQueueEnabled,
+ FeatureFlags.MediaCaptionCreation.key to allowCaption,
+ FeatureFlags.MediaCaptionWarning.key to showCaptionCompatibilityWarning,
+ ),
+ )
)
}
}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt
index 405d356edf..51c4cb43ba 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt
@@ -35,7 +35,7 @@ import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
-import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorWithoutValidation
+import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt
index d0b41bbb1e..a56da055aa 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt
@@ -1586,7 +1586,12 @@ fun anEditMode(
fun anEditCaptionMode(
eventOrTransactionId: EventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
caption: String = A_CAPTION,
-) = MessageComposerMode.EditCaption(eventOrTransactionId, caption)
+ showCaptionCompatibilityWarning: Boolean = false,
+) = MessageComposerMode.EditCaption(
+ eventOrTransactionId = eventOrTransactionId,
+ content = caption,
+ showCaptionCompatibilityWarning = showCaptionCompatibilityWarning,
+)
fun aReplyMode() = MessageComposerMode.Reply(
replyToDetails = InReplyToDetails.Loading(AN_EVENT_ID),
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt
index 1036788cbb..ed92a34df3 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt
@@ -9,7 +9,7 @@ package io.element.android.features.messages.impl.pinned.list
import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.PinUnpinAction
-import io.element.android.features.messages.impl.actionlist.FakeActionListPresenter
+import io.element.android.features.messages.impl.actionlist.anActionListState
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactoryCreator
import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProvider
@@ -312,7 +312,7 @@ class PinnedMessagesListPresenterTest {
timelineProvider = timelineProvider,
timelineProtectionPresenter = { aTimelineProtectionState() },
snackbarDispatcher = SnackbarDispatcher(),
- actionListPresenterFactory = FakeActionListPresenter.Factory(),
+ actionListPresenter = { anActionListState() },
analyticsService = analyticsService,
appCoroutineScope = this,
)
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessorTest.kt
new file mode 100644
index 0000000000..7043d3f848
--- /dev/null
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessorTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.features.messages.impl.pinned.list
+
+import com.google.common.truth.Truth.assertThat
+import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
+import org.junit.Test
+
+class PinnedMessagesListTimelineActionPostProcessorTest {
+ @Test
+ fun `ensure that ViewInTimeline is added`() {
+ val sut = PinnedMessagesListTimelineActionPostProcessor()
+ val result = sut.process(
+ listOf()
+ )
+ assertThat(result).isEqualTo(
+ listOf(TimelineItemAction.ViewInTimeline)
+ )
+ }
+
+ @Test
+ fun `ensure that some actions are kept and some other are filtered out`() {
+ val sut = PinnedMessagesListTimelineActionPostProcessor()
+ val result = sut.process(
+ listOf(
+ TimelineItemAction.Forward,
+ TimelineItemAction.CopyText,
+ TimelineItemAction.CopyCaption,
+ TimelineItemAction.CopyLink,
+ TimelineItemAction.Redact,
+ TimelineItemAction.Reply,
+ TimelineItemAction.ReplyInThread,
+ TimelineItemAction.Edit,
+ TimelineItemAction.EditCaption,
+ TimelineItemAction.AddCaption,
+ TimelineItemAction.RemoveCaption,
+ TimelineItemAction.ViewSource,
+ TimelineItemAction.ReportContent,
+ TimelineItemAction.EndPoll,
+ TimelineItemAction.Pin,
+ TimelineItemAction.Unpin,
+ )
+ )
+ assertThat(result).isEqualTo(
+ listOf(
+ TimelineItemAction.ViewInTimeline,
+ TimelineItemAction.Unpin,
+ TimelineItemAction.Forward,
+ TimelineItemAction.ViewSource,
+ )
+ )
+ }
+}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt
index 07ff31690e..fb853f4472 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt
@@ -64,7 +64,7 @@ import io.element.android.libraries.matrix.test.media.aMediaSource
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.timeline.aStickerContent
import io.element.android.libraries.matrix.ui.components.A_BLUR_HASH
-import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorWithoutValidation
+import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.test.runTest
@@ -239,7 +239,7 @@ class TimelineItemContentMessageFactoryTest {
formattedCaption = null,
isEdited = false,
duration = Duration.ZERO,
- videoSource = MediaSource(url = "url", json = null),
+ mediaSource = MediaSource(url = "url", json = null),
thumbnailSource = null,
aspectRatio = null,
blurHash = null,
@@ -291,7 +291,7 @@ class TimelineItemContentMessageFactoryTest {
formattedCaption = SpannedString("formatted"),
isEdited = true,
duration = 1.minutes,
- videoSource = MediaSource(url = "url", json = null),
+ mediaSource = MediaSource(url = "url", json = null),
thumbnailSource = MediaSource("url_thumbnail"),
aspectRatio = 3f,
blurHash = A_BLUR_HASH,
@@ -380,7 +380,9 @@ class TimelineItemContentMessageFactoryTest {
duration = Duration.ZERO,
mediaSource = MediaSource(url = "url", json = null),
mimeType = MimeTypes.OctetStream,
- waveform = emptyList().toImmutableList()
+ waveform = emptyList().toImmutableList(),
+ fileExtension = "",
+ formattedFileSize = "0 Bytes",
)
assertThat(result).isEqualTo(expected)
}
@@ -419,7 +421,9 @@ class TimelineItemContentMessageFactoryTest {
duration = 1.minutes,
mediaSource = MediaSource(url = "url", json = null),
mimeType = MimeTypes.Ogg,
- waveform = persistentListOf(1f, 2f)
+ waveform = persistentListOf(1f, 2f),
+ fileExtension = "ogg",
+ formattedFileSize = "123 Bytes",
)
assertThat(result).isEqualTo(expected)
}
@@ -571,7 +575,7 @@ class TimelineItemContentMessageFactoryTest {
caption = null,
formattedCaption = null,
isEdited = false,
- fileSource = MediaSource(url = "url", json = null),
+ mediaSource = MediaSource(url = "url", json = null),
thumbnailSource = null,
formattedFileSize = "0 Bytes",
fileExtension = "",
@@ -612,7 +616,7 @@ class TimelineItemContentMessageFactoryTest {
caption = null,
formattedCaption = null,
isEdited = true,
- fileSource = MediaSource(url = "url", json = null),
+ mediaSource = MediaSource(url = "url", json = null),
thumbnailSource = MediaSource("url_thumbnail"),
formattedFileSize = "123 Bytes",
fileExtension = "pdf",
diff --git a/features/preferences/impl/src/main/res/values-de/translations.xml b/features/preferences/impl/src/main/res/values-de/translations.xml
index 7804663579..7d83685eda 100644
--- a/features/preferences/impl/src/main/res/values-de/translations.xml
+++ b/features/preferences/impl/src/main/res/values-de/translations.xml
@@ -8,6 +8,8 @@
"Benutzerdefinierte Element-Aufruf-Basis-URL"
"Lege eine eigene Basis-URL für Element Call fest."
"Ungültige URL, bitte stelle sicher, dass du das Protokoll (http/https) und die richtige Adresse angibst."
+ "Laden Sie Fotos und Videos schneller hoch und reduzieren Sie die Datennutzung"
+ "Optimieren Sie die Medienqualität"
"Anbieter für Push-Benachrichtigungen"
"Deaktiviere den Rich-Text-Editor, um Markdown manuell einzugeben."
"Lesebestätigungen"
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
index 5aab0be9f8..317be0b282 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
@@ -15,6 +15,7 @@ import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
+import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
@@ -33,20 +34,16 @@ import io.element.android.features.roomdetails.impl.members.details.RoomMemberDe
import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsNode
import io.element.android.features.roomdetails.impl.rolesandpermissions.RolesAndPermissionsFlowNode
import io.element.android.features.userprofile.shared.UserProfileNodeHelper
-import io.element.android.features.userprofile.shared.avatar.AvatarPreviewNode
import io.element.android.libraries.architecture.BackstackWithOverlayBox
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.overlay.operation.show
-import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
-import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.MatrixRoom
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerNode
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.parcelize.Parcelize
@@ -61,6 +58,7 @@ class RoomDetailsFlowNode @AssistedInject constructor(
private val analyticsService: AnalyticsService,
private val messagesEntryPoint: MessagesEntryPoint,
private val knockRequestsListEntryPoint: KnockRequestsListEntryPoint,
+ private val mediaViewerEntryPoint: MediaViewerEntryPoint,
) : BaseFlowNode(
backstack = BackStack(
initialElement = plugins.filterIsInstance().first().initialElement.toNavTarget(),
@@ -211,22 +209,18 @@ class RoomDetailsFlowNode @AssistedInject constructor(
createNode(buildContext, plugins)
}
is NavTarget.AvatarPreview -> {
- // We need to fake the MimeType here for the viewer to work.
- val mimeType = MimeTypes.Images
- val input = MediaViewerNode.Inputs(
- mediaInfo = MediaInfo(
- filename = navTarget.name,
- caption = null,
- mimeType = mimeType,
- formattedFileSize = "",
- fileExtension = ""
- ),
- mediaSource = MediaSource(url = navTarget.avatarUrl),
- thumbnailSource = null,
- canDownload = false,
- canShare = false,
- )
- createNode(buildContext, listOf(input))
+ val callback = object : MediaViewerEntryPoint.Callback {
+ override fun onDone() {
+ backstack.pop()
+ }
+ }
+ mediaViewerEntryPoint.nodeBuilder(this, buildContext)
+ .avatar(
+ navTarget.name,
+ navTarget.avatarUrl,
+ )
+ .callback(callback)
+ .build()
}
is NavTarget.PollHistory -> {
diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml
index 8671c381b8..3b8b70c40f 100644
--- a/features/roomlist/impl/src/main/res/values-de/translations.xml
+++ b/features/roomlist/impl/src/main/res/values-de/translations.xml
@@ -7,8 +7,10 @@
"Erstelle einen neuen Wiederherstellungsschlüssel, mit dem du deinen verschlüsselten Nachrichtenverlauf wiederherstellen kannst, wenn du dich an einem neuen Gerät anmeldest."
"Wiederherstellung einrichten"
"Wiederherstellung einrichten"
- "Dein Chat-Backup ist derzeit nicht synchronisiert. Du musst deinen Wiederherstellungsschlüssel bestätigen, um Zugriff auf dein Chat-Backup zu erhalten."
- "Wiederherstellungsschlüssel bestätigen."
+ "Bestätigen Sie die Validität Ihres Wiederherstellungsschlüssels, um weiterhin auf Ihren Schlüsselspeicher und den Nachrichtenverlauf zugreifen zu können."
+ "Geben Sie Ihren Wiederherstellungsschlüssel ein"
+ "Haben Sie Ihren Wiederherstellungsschlüssel vergessen?"
+ "Ihr Schlüsselspeicher ist nicht synchronisiert"
"Damit du keinen wichtigen Anruf verpasst, ändere bitte deine Einstellungen so, dass du bei gesperrtem Telefon Benachrichtigungen im Vollbildmodus erhältst."
"Verbessere dein Anruferlebnis"
"Möchtest du die Einladung zum Betreten von %1$s wirklich ablehnen?"
@@ -17,6 +19,7 @@
"Einladung ablehnen"
"Keine Einladungen"
"%1$s (%2$s) hat dich eingeladen"
+ "Beitrittsanfrage geschickt"
"Dies ist ein einmaliger Vorgang, danke fürs Warten."
"Dein Konto wird eingerichtet."
"Eine Unterthaltung oder Raum erstellen"
diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt
index 5d9aeec21e..241f132252 100644
--- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt
+++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/SecureBackupFlowNode.kt
@@ -28,6 +28,7 @@ import io.element.android.features.securebackup.impl.root.SecureBackupRootNode
import io.element.android.features.securebackup.impl.setup.SecureBackupSetupNode
import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
+import io.element.android.libraries.architecture.appyx.canPop
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope
import kotlinx.parcelize.Parcelize
@@ -111,10 +112,10 @@ class SecureBackupFlowNode @AssistedInject constructor(
NavTarget.EnterRecoveryKey -> {
val callback = object : SecureBackupEnterRecoveryKeyNode.Callback {
override fun onEnterRecoveryKeySuccess() {
- if (callbacks.isNotEmpty()) {
- callbacks.forEach { it.onDone() }
- } else {
+ if (backstack.canPop()) {
backstack.pop()
+ } else {
+ callbacks.forEach { it.onDone() }
}
}
}
diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml
index 7201aaba3a..29e43e2e2f 100644
--- a/features/securebackup/impl/src/main/res/values-de/translations.xml
+++ b/features/securebackup/impl/src/main/res/values-de/translations.xml
@@ -2,11 +2,15 @@
"Backup deaktivieren"
"Backup aktivieren"
- "Das Backup stellt sicher, dass du deinen Nachrichtenverlauf nicht verlierst. %1$s."
- "Backup"
+ "Speichern Sie Ihre verschlüsselte Identität und Ihre codierten Nachrichtenschlüssel auf dem Server. Auf diese Weise können Sie Ihren Nachrichtenverlauf auf allen neuen Geräten einsehen. %1$s."
+ "Schlüsselspeicher"
+ "Der Schlüsselspeicher muss aktiviert sein, um Datenwiederherstellung zu ermöglichen."
+ "Schlüssel von diesem Gerät hochladen"
+ "Schlüsselspeicherung zulassen"
"Wiederherstellungsschlüssel ändern"
+ "Stellen Sie Ihre verschlüsselte Identität und Ihren Nachrichtenverlauf mit einem Wiederherstellungsschlüssel wieder her, falls Sie den Zugang zu allen Ihren Geräten verloren haben."
"Wiederherstellungsschlüssel eingeben"
- "Dein Chat-Backup ist derzeit nicht synchronisiert."
+ "Dein Schlüssel ist derzeit nicht synchronisiert."
"Wiederherstellung einrichten"
"Erhalte Zugriff auf deine verschlüsselten Nachrichten, wenn du alle deine Geräte verlierst oder von %1$s überall abgemeldet bist."
@@ -33,6 +37,8 @@
"Deine Kontodaten, Kontakte, Einstellungen und die Liste der Chats bleiben erhalten"
"Du verlierst alle deine bisherigen Nachrichten sofern sie nicht auf einem anderen Gerät vorliegen"
"Du musst alle deine bestehenden Geräte und Kontakte erneut verifizieren."
+ "Setzen Sie Ihre Identität nur dann zurück, wenn Sie keinen Zugriff auf ein anderes Ihrer angemeldeten Geräte und auch Ihren Wiederherstellungsschlüssel verloren haben."
+ "Sie können es nicht bestätigen? Dann müssen Sie Ihre Identität zurücksetzen."
"Ausschalten"
"Du verlierst deine verschlüsselten Nachrichten, wenn du auf allen Geräten abgemeldet bist."
"Bist du sicher, dass du das Backup deaktivieren willst?"
@@ -42,7 +48,7 @@
"Bist du sicher, dass du das Backup deaktivieren willst?"
"Hier kannst Du einen neuen Wiederherstellungsschlüssel erstellen. Nachdem Du einen neuen Wiederherstellungsschlüssel erstellt hast, funktioniert dein alter Schlüssel nicht mehr."
"Wiederherstellungsschlüssel erstellen"
- "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst"
+ "Geben Sie dies an niemanden weiter!"
"Wiederherstellungsschlüssel geändert"
"Wiederherstellungsschlüssel ändern?"
@@ -51,23 +57,24 @@
" erstellen"
"Sorge dafür, dass niemand diesen Bildschirm sehen kann!"
- "Bitte versuche es noch einmal, um den Zugriff auf dein Chat-Backup zu bestätigen."
+ "Bitte versuchen Sie erneut, den Zugriff auf Ihren Schlüsselspeicher zu bestätigen."
"Falscher Wiederherstellungsschlüssel"
"Dies funktioniert auch mit einem Sicherheitsschlüssel oder Sicherheitsphrase."
"Eingeben…"
"Hast du deinen Wiederherstellungschlüssel vergessen?"
"Wiederherstellungsschlüssel bestätigt"
+ "Geben Sie Ihren Wiederherstellungsschlüssel ein"
"Wiederherstellungsschlüssel kopiert"
"Generieren…"
"Wiederherstellungsschlüssel speichern"
- "Notiere dir deinen Wiederherstellungsschlüssel an einem sicheren Ort oder speichere ihn in einem Passwort-Manager."
+ "Schreiben Sie Ihren Wiederherstellungsschlüssel in eine verschlüsselte Datei, oder in einem Passwort-Manager oder in einem Safe. "
"Tippe, um den Wiederherstellungsschlüssel zu kopieren"
"Speichere deinen Wiederherstellungsschlüssel"
"Nach diesem Schritt kannst du nicht mehr auf deinen neuen Wiederherstellungsschlüssel zugreifen."
"Hast du deinen Wiederherstellungsschlüssel gespeichert?"
"Dein Chat-Backup ist durch einen Wiederherstellungsschlüssel geschützt. Wenn du nach der Einrichtung einen neuen Wiederherstellungsschlüssel brauchst, kannst du ihn über die Option \"Wiederherstellungsschlüssel ändern\" neu erstellen."
"Wiederherstellungsschlüssel erstellen"
- "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst"
+ "Geben Sie dies an niemanden weiter!"
"Einrichtung der Wiederherstellung erfolgreich"
"Wiederherstellung einrichten"
"Ja, zurücksetzen"
diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt
index b544ad4750..ce0d4a07f0 100644
--- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt
+++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt
@@ -15,6 +15,7 @@ import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
+import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
@@ -24,18 +25,14 @@ import io.element.android.features.call.api.ElementCallEntryPoint
import io.element.android.features.userprofile.api.UserProfileEntryPoint
import io.element.android.features.userprofile.impl.root.UserProfileNode
import io.element.android.features.userprofile.shared.UserProfileNodeHelper
-import io.element.android.features.userprofile.shared.avatar.AvatarPreviewNode
import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs
-import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerNode
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import kotlinx.parcelize.Parcelize
@ContributesNode(SessionScope::class)
@@ -44,6 +41,7 @@ class UserProfileFlowNode @AssistedInject constructor(
@Assisted plugins: List,
private val elementCallEntryPoint: ElementCallEntryPoint,
private val sessionIdHolder: CurrentSessionIdHolder,
+ private val mediaViewerEntryPoint: MediaViewerEntryPoint,
) : BaseFlowNode(
backstack = BackStack(
initialElement = NavTarget.Root,
@@ -80,22 +78,18 @@ class UserProfileFlowNode @AssistedInject constructor(
createNode(buildContext, listOf(callback, params))
}
is NavTarget.AvatarPreview -> {
- // We need to fake the MimeType here for the viewer to work.
- val mimeType = MimeTypes.Images
- val input = MediaViewerNode.Inputs(
- mediaInfo = MediaInfo(
+ val callback = object : MediaViewerEntryPoint.Callback {
+ override fun onDone() {
+ backstack.pop()
+ }
+ }
+ mediaViewerEntryPoint.nodeBuilder(this, buildContext)
+ .avatar(
filename = navTarget.name,
- caption = null,
- mimeType = mimeType,
- formattedFileSize = "",
- fileExtension = "",
- ),
- mediaSource = MediaSource(url = navTarget.avatarUrl),
- thumbnailSource = null,
- canDownload = false,
- canShare = false,
- )
- createNode(buildContext, listOf(input))
+ avatarUrl = navTarget.avatarUrl
+ )
+ .callback(callback)
+ .build()
}
}
}
diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/avatar/AvatarPreviewNode.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/avatar/AvatarPreviewNode.kt
deleted file mode 100644
index 159b7f56f6..0000000000
--- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/avatar/AvatarPreviewNode.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2024 New Vector Ltd.
- *
- * SPDX-License-Identifier: AGPL-3.0-only
- * Please see LICENSE in the repository root for full details.
- */
-
-package io.element.android.features.userprofile.shared.avatar
-
-import com.bumble.appyx.core.modality.BuildContext
-import com.bumble.appyx.core.plugin.Plugin
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedInject
-import io.element.android.anvilannotations.ContributesNode
-import io.element.android.libraries.di.SessionScope
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerNode
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerPresenter
-
-@ContributesNode(SessionScope::class)
-class AvatarPreviewNode @AssistedInject constructor(
- @Assisted buildContext: BuildContext,
- @Assisted plugins: List,
- presenterFactory: MediaViewerPresenter.Factory,
-) : MediaViewerNode(buildContext, plugins, presenterFactory)
diff --git a/features/userprofile/shared/src/main/res/values-de/translations.xml b/features/userprofile/shared/src/main/res/values-de/translations.xml
index ff20101939..f96af58bae 100644
--- a/features/userprofile/shared/src/main/res/values-de/translations.xml
+++ b/features/userprofile/shared/src/main/res/values-de/translations.xml
@@ -13,5 +13,7 @@
"Blockierung aufheben"
"Der Nutzer kann dir wieder Nachrichten senden & alle Nachrichten des Nutzers werden wieder angezeigt."
"Blockierung aufheben"
+ "Verwenden Sie die Web-App, um diesen Benutzer zu verifizieren."
+ "Überprüfen Sie %1$s"
"Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten"
diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml
index 1ddda0126b..4534411033 100644
--- a/features/verifysession/impl/src/main/res/values-de/translations.xml
+++ b/features/verifysession/impl/src/main/res/values-de/translations.xml
@@ -1,5 +1,6 @@
+ "Sie können es nicht bestätigen?"
"Erstelle einen neuen Wiederherstellungsschlüssel"
"Verifiziere dieses Gerät, um sicheres Messaging einzurichten."
"Bestätige, dass du es bist"
@@ -16,6 +17,7 @@
"Vergleiche die Zahlen"
"Deine neue Session ist nun verifiziert. Sie hat Zugriff auf deine verschlüsselten Nachrichten und wird von anderen Benutzern als vertrauenswürdig eingestuft."
"Wiederherstellungsschlüssel eingeben"
+ "Entweder ist bei der Anfrage ein Timeout aufgetreten, oder die Anfrage wurde abgelehnt, oder es gab eine Nichtübereinstimmung bei der Überprüfung."
"Beweise deine Identität, um auf deinen verschlüsselten Nachrichtenverlauf zuzugreifen."
"Öffne eine bestehende Session"
"Verifizierung wiederholen"
@@ -23,8 +25,20 @@
"Warten auf eine Übereinstimmung"
"Vergleiche eine spezielle Reihe von Emojis."
"Vergleiche die einzelnen Emojis und stelle sicher, dass sie in der gleichen Reihenfolge erscheinen."
+ "Angemeldet"
+ "Entweder ist bei der Anfrage ein Timeout aufgetreten, oder die Anfrage wurde abgelehnt, oder es gab eine Nichtübereinstimmung bei der Überprüfung."
+ "Überprüfung fehlgeschlagen"
+ "Fahren Sie nur fort, falls Sie für diese Überprüfung verantwortlich sind.."
+ "Verifizieren Sie das andere Gerät, um die Sicherheit Ihres Nachrichtenverlaufs zu gewährleisten."
+ "Jetzt können Sie gesichert Nachrichten auf Ihrem anderen Gerät lesen oder senden."
+ "Gerät verifiziert"
+ "Verifizierung angefordert"
"Sie stimmen nicht überein"
"Sie stimmen überein"
+ "Stellen Sie sicher, dass die App auf dem anderen Gerät geöffnet ist, bevor Sie die Überprüfung auf diesem Gerät aus starten."
+ "Öffnen Sie die App auf einem anderen verifizierten Gerät"
+ "Sie sollten ein Popup-Fenster auf dem anderen Gerät sehen. Starten Sie die Überprüfung von dort aus."
+ "Starten Sie die Überprüfung auf dem anderen Gerät"
"Akzeptiere die Anfrage, um den Verifizierungsprozess in deiner anderen Session zu starten, um fortzufahren."
"Warten auf die Annahme der Anfrage"
"Abmelden…"
diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml
index 2ee77b1f7d..46c24d253e 100644
--- a/features/verifysession/impl/src/main/res/values-pl/translations.xml
+++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml
@@ -17,6 +17,7 @@
"Porównaj liczby"
"Twoja nowa sesja jest teraz zweryfikowana. Ma ona dostęp do Twoich zaszyfrowanych wiadomości, a inni użytkownicy będą widzieć ją jako zaufaną."
"Wprowadź klucz przywracania"
+ "Albo upłynął limit czasu żądania, albo żądanie zostało odrzucone, albo wystąpił błąd weryfikacji."
"Udowodnij, że to ty, aby uzyskać dostęp do historii zaszyfrowanych wiadomości."
"Otwórz istniejącą sesję"
"Ponów weryfikację"
@@ -25,9 +26,11 @@
"Porównaj unikalny zestaw emoji."
"Porównaj unikalne emoji, upewniając się, że pojawiły się w tej samej kolejności."
"Zalogowano"
+ "Albo upłynął limit czasu żądania, albo żądanie zostało odrzucone, albo wystąpił błąd weryfikacji."
"Weryfikacja nie powiodła się"
"Kontynuuj tylko, jeśli to Ty zainicjowałeś tę weryfikację."
"Zweryfikuj drugie urządzenie, aby zabezpieczyć historię wiadomości."
+ "Już możesz bezpiecznie czytać lub wysyłać wiadomości na drugim urządzeniu."
"Urządzenie zweryfikowane"
"Zażądano weryfikacji"
"Nie pasują do siebie"
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 3225075b24..513bdc9328 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -21,7 +21,7 @@ constraintlayout = "2.2.0"
constraintlayout_compose = "1.1.0"
lifecycle = "2.8.7"
activity = "1.9.3"
-media3 = "1.4.1"
+media3 = "1.5.0"
camera = "1.4.0"
# Compose
@@ -46,14 +46,14 @@ coil = "2.7.0"
showkase = "1.0.3"
appyx = "1.5.1"
sqldelight = "2.0.2"
-wysiwyg = "2.37.13"
+wysiwyg = "2.37.14"
telephoto = "0.14.0"
# Dependency analysis
dependencyAnalysis = "2.5.0"
# DI
-dagger = "2.52"
+dagger = "2.53"
anvil = "0.4.0"
# Auto service
@@ -150,7 +150,7 @@ test_arch_core = "androidx.arch.core:core-testing:2.2.0"
test_junit = "junit:junit:4.13.2"
test_runner = "androidx.test:runner:1.6.2"
test_mockk = "io.mockk:mockk:1.13.13"
-test_konsist = "com.lemonappdev:konsist:0.16.1"
+test_konsist = "com.lemonappdev:konsist:0.17.1"
test_turbine = "app.cash.turbine:turbine:1.2.0"
test_truth = "com.google.truth:truth:1.4.4"
test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.18"
@@ -173,7 +173,7 @@ jsoup = "org.jsoup:jsoup:1.18.1"
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0"
timber = "com.jakewharton.timber:timber:5.0.1"
-matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.65"
+matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.68"
matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" }
matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" }
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
@@ -201,7 +201,7 @@ matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.28.0"
# Emojibase
matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.3.3"
-sigpwned_emoji4j = "com.sigpwned:emoji4j-core:15.1.2"
+sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0"
# Di
inject = "javax.inject:javax.inject:1"
@@ -233,7 +233,7 @@ kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
anvil = { id = "dev.zacsweers.anvil", version.ref = "anvil" }
detekt = "io.gitlab.arturbosch.detekt:1.23.7"
-ktlint = "org.jlleitschuh.gradle.ktlint:12.1.1"
+ktlint = "org.jlleitschuh.gradle.ktlint:12.1.2"
dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12"
dependencycheck = "org.owasp.dependencycheck:11.1.0"
dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" }
@@ -241,6 +241,6 @@ paparazzi = "app.cash.paparazzi:1.3.5"
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" }
knit = { id = "org.jetbrains.kotlinx.knit", version = "0.5.0" }
-sonarqube = "org.sonarqube:6.0.0.5145"
+sonarqube = "org.sonarqube:6.0.1.5171"
licensee = "app.cash.licensee:1.12.0"
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
diff --git a/libraries/dateformatter/api/build.gradle.kts b/libraries/dateformatter/api/build.gradle.kts
index 1aabe2a563..6ec28b9eb9 100644
--- a/libraries/dateformatter/api/build.gradle.kts
+++ b/libraries/dateformatter/api/build.gradle.kts
@@ -11,4 +11,9 @@ plugins {
android {
namespace = "io.element.android.libraries.dateformatter.api"
+
+ dependencies {
+ testImplementation(libs.test.junit)
+ testImplementation(libs.test.truth)
+ }
}
diff --git a/libraries/dateformatter/api/src/main/kotlin/io/element/android/libraries/dateformatter/api/DurationFormatter.kt b/libraries/dateformatter/api/src/main/kotlin/io/element/android/libraries/dateformatter/api/DurationFormatter.kt
new file mode 100644
index 0000000000..7f8473b416
--- /dev/null
+++ b/libraries/dateformatter/api/src/main/kotlin/io/element/android/libraries/dateformatter/api/DurationFormatter.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.dateformatter.api
+
+import java.util.Locale
+
+/**
+ * Convert milliseconds to human readable duration.
+ * Hours in 1 digit or more.
+ * Minutes in 2 digits when hours are available.
+ * Seconds always on 2 digits.
+ * Example:
+ * - when the duration is longer than 1 hour:
+ * - "10:23:34"
+ * - "1:23:34"
+ * - "1:03:04"
+ * - when the duration is shorter:
+ * - "4:56"
+ * - "14:06"
+ * - Less than one minute:
+ * - "0:00"
+ * - "0:01"
+ * - "0:59"
+ */
+fun Long.toHumanReadableDuration(): String {
+ val inSeconds = this / 1_000
+ val hours = inSeconds / 3_600
+ val minutes = inSeconds % 3_600 / 60
+ val seconds = inSeconds % 60
+ return if (hours > 0) {
+ String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds)
+ } else {
+ String.format(Locale.US, "%d:%02d", minutes, seconds)
+ }
+}
diff --git a/libraries/dateformatter/api/src/test/kotlin/io/element/android/libraries/dateformatter/api/DurationFormatterTest.kt b/libraries/dateformatter/api/src/test/kotlin/io/element/android/libraries/dateformatter/api/DurationFormatterTest.kt
new file mode 100644
index 0000000000..1b8c155f9c
--- /dev/null
+++ b/libraries/dateformatter/api/src/test/kotlin/io/element/android/libraries/dateformatter/api/DurationFormatterTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.dateformatter.api
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class DurationFormatterTest {
+ @Test
+ fun `format seconds only`() {
+ assertThat(buildDuration().toHumanReadableDuration()).isEqualTo("0:00")
+ assertThat(buildDuration(seconds = 1).toHumanReadableDuration()).isEqualTo("0:01")
+ assertThat(buildDuration(seconds = 59).toHumanReadableDuration()).isEqualTo("0:59")
+ }
+
+ @Test
+ fun `format minutes and seconds`() {
+ assertThat(buildDuration(minutes = 1).toHumanReadableDuration()).isEqualTo("1:00")
+ assertThat(buildDuration(minutes = 1, seconds = 30).toHumanReadableDuration()).isEqualTo("1:30")
+ assertThat(buildDuration(minutes = 59, seconds = 59).toHumanReadableDuration()).isEqualTo("59:59")
+ }
+
+ @Test
+ fun `format hours, minutes and seconds`() {
+ assertThat(buildDuration(hours = 1).toHumanReadableDuration()).isEqualTo("1:00:00")
+ assertThat(buildDuration(hours = 1, minutes = 1, seconds = 1).toHumanReadableDuration()).isEqualTo("1:01:01")
+ assertThat(buildDuration(hours = 24, minutes = 59, seconds = 59).toHumanReadableDuration()).isEqualTo("24:59:59")
+ assertThat(buildDuration(hours = 25, minutes = 0, seconds = 0).toHumanReadableDuration()).isEqualTo("25:00:00")
+ }
+
+ private fun buildDuration(
+ hours: Int = 0,
+ minutes: Int = 0,
+ seconds: Int = 0
+ ): Long {
+ return (hours * 60 * 60 + minutes * 60 + seconds) * 1000L
+ }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Slider.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Slider.kt
index b5edbb2d65..5c0095b7b6 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Slider.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Slider.kt
@@ -5,19 +5,32 @@
* Please see LICENSE in the repository root for full details.
*/
+@file:OptIn(ExperimentalMaterial3Api::class)
+
package io.element.android.libraries.designsystem.theme.components
+import androidx.compose.foundation.interaction.DragInteraction
import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.height
+import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SliderColors
import androidx.compose.material3.SliderDefaults
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawWithContent
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup
@@ -32,8 +45,20 @@ fun Slider(
steps: Int = 0,
onValueChangeFinish: (() -> Unit)? = null,
colors: SliderColors = SliderDefaults.colors(),
- interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
+ interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+ useCustomLayout: Boolean = false,
) {
+ val thumbColor = ElementTheme.colors.iconOnSolidPrimary
+ var isUserInteracting by remember { mutableStateOf(false) }
+ LaunchedEffect(interactionSource) {
+ interactionSource.interactions.collect { interaction ->
+ isUserInteracting = when (interaction) {
+ is DragInteraction.Start,
+ is PressInteraction.Press -> true
+ else -> false
+ }
+ }
+ }
androidx.compose.material3.Slider(
value = value,
onValueChange = onValueChange,
@@ -43,6 +68,54 @@ fun Slider(
steps = steps,
onValueChangeFinished = onValueChangeFinish,
colors = colors,
+ thumb = {
+ if (useCustomLayout) {
+ SliderDefaults.Thumb(
+ modifier = Modifier.drawWithContent {
+ drawContent()
+ if (isUserInteracting.not()) {
+ drawCircle(thumbColor, radius = 8.dp.toPx())
+ }
+ },
+ interactionSource = interactionSource,
+ colors = colors.copy(
+ thumbColor = ElementTheme.colors.iconPrimary,
+ ),
+ enabled = enabled,
+ thumbSize = DpSize(
+ if (isUserInteracting) 44.dp else 22.dp,
+ 22.dp,
+ ),
+ )
+ } else {
+ SliderDefaults.Thumb(
+ interactionSource = interactionSource,
+ colors = colors,
+ enabled = enabled
+ )
+ }
+ },
+ track = { sliderState ->
+ if (useCustomLayout) {
+ SliderDefaults.Track(
+ modifier = Modifier.height(8.dp),
+ colors = colors.copy(
+ activeTrackColor = Color(0x66E0EDFF),
+ inactiveTrackColor = Color(0x66E0EDFF),
+ ),
+ enabled = enabled,
+ sliderState = sliderState,
+ thumbTrackGapSize = 0.dp,
+ drawStopIndicator = { },
+ )
+ } else {
+ SliderDefaults.Track(
+ colors = colors,
+ enabled = enabled,
+ sliderState = sliderState,
+ )
+ }
+ },
interactionSource = interactionSource,
)
}
@@ -55,5 +128,6 @@ internal fun SlidersPreview() = ElementThemedPreview {
Slider(onValueChange = { value = it }, value = value, enabled = true)
Slider(steps = 10, onValueChange = { value = it }, value = value, enabled = true)
Slider(onValueChange = { value = it }, value = value, enabled = false)
+ Slider(onValueChange = { value = it }, value = value, enabled = true, useCustomLayout = true)
}
}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/HideKeyboardWhenDisposed.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/HideKeyboardWhenDisposed.kt
new file mode 100644
index 0000000000..0e18528605
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/HideKeyboardWhenDisposed.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.designsystem.utils
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+
+@Composable
+fun HideKeyboardWhenDisposed() {
+ val keyboardController = LocalSoftwareKeyboardController.current
+ DisposableEffect(Unit) {
+ onDispose {
+ keyboardController?.hide()
+ }
+ }
+}
diff --git a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml
index 1b99fd2e5d..8c99ba44de 100644
--- a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml
+++ b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml
@@ -28,7 +28,7 @@
"%1$s hat dich eingeladen"
"%1$s hat den Raum betreten"
"Du hast den Raum betreten"
- "%1$s hat angefragt beizutreten"
+ "%1$s beantragt den Beitritt"
"%1$s hat %2$s den Beitritt erlaubt"
"Du hast %1$s den Beitritt erlaubt."
"Du hast angefragt beizutreten"
diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt
index 490c12ebe0..7d21ed1138 100644
--- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt
+++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt
@@ -140,4 +140,18 @@ enum class FeatureFlags(
defaultValue = { buildMeta -> buildMeta.buildType != BuildType.RELEASE },
isFinished = false,
),
+ MediaCaptionCreation(
+ key = "feature.media_caption_creation",
+ title = "Allow creation of media captions",
+ description = null,
+ defaultValue = { true },
+ isFinished = false,
+ ),
+ MediaCaptionWarning(
+ key = "feature.media_caption_creation_warning",
+ title = "Show a compatibility warning on media captions creation",
+ description = null,
+ defaultValue = { true },
+ isFinished = false,
+ ),
}
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/UtdCause.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/UtdCause.kt
index c89b4169c6..51427c6cba 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/UtdCause.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/UtdCause.kt
@@ -12,5 +12,22 @@ enum class UtdCause {
SentBeforeWeJoined,
VerificationViolation,
UnsignedDevice,
- UnknownDevice
+ UnknownDevice,
+
+ /**
+ * Expected utd because this is a device-historical message and
+ * key storage is not setup or not configured correctly.
+ */
+ HistoricalMessage,
+
+ /**
+ * The key was withheld on purpose because your device is insecure and/or the
+ * sender trust requirement settings are not met for your device.
+ */
+ WithheldUnverifiedOrInsecureDevice,
+
+ /**
+ * Key is withheld by sender.
+ */
+ WithheldBySender,
}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/UtdTracker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/UtdTracker.kt
index cda2cc1893..edbeb1d23d 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/UtdTracker.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/UtdTracker.kt
@@ -27,6 +27,7 @@ class UtdTracker(
UtdCause.UNKNOWN_DEVICE -> {
Error.Name.ExpectedSentByInsecureDevice
}
+ UtdCause.HISTORICAL_MESSAGE -> Error.Name.HistoricalMessage
}
val event = Error(
context = null,
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt
index 17ba1d2c4d..1d07a3e019 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt
@@ -15,7 +15,6 @@ import io.element.android.libraries.matrix.api.media.MediaSource
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.Client
-import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
import org.matrix.rustcomponents.sdk.use
import java.io.File
import org.matrix.rustcomponents.sdk.MediaSource as RustMediaSource
@@ -86,7 +85,7 @@ class RustMediaLoader(
return if (json != null) {
RustMediaSource.fromJson(json)
} else {
- mediaSourceFromUrl(url)
+ RustMediaSource.fromUrl(url)
}
}
}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt
index 84f34ae9bf..d39d45c067 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt
@@ -141,7 +141,7 @@ class RustRoomFactory(
}
val innerRoom = try {
roomListItem.previewRoom(via = emptyList())
- } catch (e: RoomListException) {
+ } catch (e: Exception) {
Timber.e(e, "Failed to get pending room for $roomId")
return@withContext null
}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewInfoMapper.kt
index 3ff3c1b098..0da22426ba 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewInfoMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewInfoMapper.kt
@@ -7,6 +7,7 @@
package io.element.android.libraries.matrix.impl.room.preview
+import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
@@ -25,7 +26,7 @@ object RoomPreviewInfoMapper {
avatarUrl = info.avatarUrl,
numberOfJoinedMembers = info.numJoinedMembers.toLong(),
roomType = info.roomType.map(),
- isHistoryWorldReadable = info.isHistoryWorldReadable,
+ isHistoryWorldReadable = info.isHistoryWorldReadable.orFalse(),
isJoined = info.membership == Membership.JOINED,
isInvited = info.membership == Membership.INVITED,
isPublic = info.joinRule == JoinRule.Public,
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt
index f85dc5acc1..7711c5af37 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt
@@ -145,6 +145,7 @@ private fun RustUtdCause.map(): UtdCause {
RustUtdCause.VERIFICATION_VIOLATION -> UtdCause.VerificationViolation
RustUtdCause.UNSIGNED_DEVICE -> UtdCause.UnsignedDevice
RustUtdCause.UNKNOWN_DEVICE -> UtdCause.UnknownDevice
+ RustUtdCause.HISTORICAL_MESSAGE -> UtdCause.HistoricalMessage
}
}
diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt
index 77e6d021d5..b9618d86dd 100644
--- a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt
+++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt
@@ -27,6 +27,35 @@ class MediaSender @Inject constructor(
private val ongoingUploadJobs = ConcurrentHashMap()
val hasOngoingMediaUploads get() = ongoingUploadJobs.isNotEmpty()
+ suspend fun preProcessMedia(
+ uri: Uri,
+ mimeType: String,
+ ): Result {
+ val compressIfPossible = sessionPreferencesStore.doesCompressMedia().first()
+ return preProcessor
+ .process(
+ uri = uri,
+ mimeType = mimeType,
+ deleteOriginal = false,
+ compressIfPossible = compressIfPossible,
+ )
+ }
+
+ suspend fun sendPreProcessedMedia(
+ mediaUploadInfo: MediaUploadInfo,
+ caption: String?,
+ formattedCaption: String?,
+ progressCallback: ProgressCallback?,
+ ): Result {
+ return room.sendMedia(
+ uploadInfo = mediaUploadInfo,
+ progressCallback = progressCallback,
+ caption = caption,
+ formattedCaption = formattedCaption
+ )
+ .handleSendResult()
+ }
+
suspend fun sendMedia(
uri: Uri,
mimeType: String,
diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaUploadInfo.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaUploadInfo.kt
index 279acd1719..dfc36a40f5 100644
--- a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaUploadInfo.kt
+++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaUploadInfo.kt
@@ -22,3 +22,11 @@ sealed interface MediaUploadInfo {
data class VoiceMessage(override val file: File, val audioInfo: AudioInfo, val waveform: List) : MediaUploadInfo
data class AnyFile(override val file: File, val fileInfo: FileInfo) : MediaUploadInfo
}
+
+fun MediaUploadInfo.allFiles(): List {
+ return listOfNotNull(
+ file,
+ (this@allFiles as? MediaUploadInfo.Image)?.thumbnailFile,
+ (this@allFiles as? MediaUploadInfo.Video)?.thumbnailFile,
+ )
+}
diff --git a/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt b/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt
index efb3b77ed8..3ec4efcfaa 100644
--- a/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt
+++ b/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt
@@ -16,10 +16,13 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
import io.element.android.libraries.mediaupload.api.MediaUploadInfo
import io.element.android.tests.testutils.simulateLongTask
+import kotlinx.coroutines.CompletableDeferred
import java.io.File
import kotlin.time.Duration.Companion.seconds
-class FakeMediaPreProcessor : MediaPreProcessor {
+class FakeMediaPreProcessor(
+ private val processLatch: CompletableDeferred? = null,
+) : MediaPreProcessor {
var processCallCount = 0
private set
@@ -41,6 +44,7 @@ class FakeMediaPreProcessor : MediaPreProcessor {
deleteOriginal: Boolean,
compressIfPossible: Boolean
): Result = simulateLongTask {
+ processLatch?.await()
processCallCount++
result
}
diff --git a/libraries/mediaviewer/api/build.gradle.kts b/libraries/mediaviewer/api/build.gradle.kts
index d55528bbe3..d36a3605d2 100644
--- a/libraries/mediaviewer/api/build.gradle.kts
+++ b/libraries/mediaviewer/api/build.gradle.kts
@@ -13,44 +13,12 @@ plugins {
android {
namespace = "io.element.android.libraries.mediaviewer.api"
- testOptions {
- unitTests {
- isIncludeAndroidResources = true
- }
- }
}
setupAnvil()
dependencies {
- implementation(libs.coil.compose)
- implementation(libs.androidx.media3.exoplayer)
- implementation(libs.androidx.media3.ui)
- implementation(libs.coroutines.core)
- implementation(libs.dagger)
- implementation(libs.telephoto.zoomableimage)
- implementation(libs.vanniktech.blurhash)
- implementation(libs.telephoto.flick)
-
- implementation(projects.libraries.androidutils)
- implementation(projects.libraries.architecture)
implementation(projects.libraries.core)
- implementation(projects.libraries.di)
- implementation(projects.libraries.designsystem)
+ implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
- implementation(projects.libraries.matrixui)
- implementation(projects.libraries.uiStrings)
-
- testImplementation(projects.libraries.matrix.test)
- testImplementation(projects.libraries.mediaviewer.test)
- testImplementation(projects.tests.testutils)
- testImplementation(libs.test.junit)
- testImplementation(libs.test.truth)
- testImplementation(libs.test.mockk)
- testImplementation(libs.test.robolectric)
- testImplementation(libs.test.turbine)
- testImplementation(libs.coroutines.core)
- testImplementation(libs.coroutines.test)
- testImplementation(libs.androidx.compose.ui.test.junit)
- testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/MediaInfo.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt
similarity index 51%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/MediaInfo.kt
rename to libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt
index 5ded65b2b3..5c317b1d6a 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/MediaInfo.kt
+++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt
@@ -1,11 +1,11 @@
/*
- * Copyright 2023, 2024 New Vector Ltd.
+ * Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local
+package io.element.android.libraries.mediaviewer.api
import android.os.Parcelable
import io.element.android.libraries.core.mimetype.MimeTypes
@@ -18,44 +18,73 @@ data class MediaInfo(
val mimeType: String,
val formattedFileSize: String,
val fileExtension: String,
+ val senderName: String?,
+ val dateSent: String?,
) : Parcelable
-fun anImageMediaInfo(): MediaInfo = MediaInfo(
+fun anImageMediaInfo(
+ caption: String? = null,
+ senderName: String? = null,
+ dateSent: String? = null,
+): MediaInfo = MediaInfo(
filename = "an image file.jpg",
- caption = null,
+ caption = caption,
mimeType = MimeTypes.Jpeg,
formattedFileSize = "4MB",
fileExtension = "jpg",
+ senderName = senderName,
+ dateSent = dateSent,
)
-fun aVideoMediaInfo(): MediaInfo = MediaInfo(
+fun aVideoMediaInfo(
+ caption: String? = null,
+ senderName: String? = null,
+ dateSent: String? = null,
+): MediaInfo = MediaInfo(
filename = "a video file.mp4",
- caption = null,
+ caption = caption,
mimeType = MimeTypes.Mp4,
formattedFileSize = "14MB",
fileExtension = "mp4",
+ senderName = senderName,
+ dateSent = dateSent,
)
-fun aPdfMediaInfo(): MediaInfo = MediaInfo(
+fun aPdfMediaInfo(
+ senderName: String? = null,
+ dateSent: String? = null,
+): MediaInfo = MediaInfo(
filename = "a pdf file.pdf",
caption = null,
mimeType = MimeTypes.Pdf,
formattedFileSize = "23MB",
fileExtension = "pdf",
+ senderName = senderName,
+ dateSent = dateSent,
)
-fun anApkMediaInfo(): MediaInfo = MediaInfo(
+fun anApkMediaInfo(
+ senderName: String? = null,
+ dateSent: String? = null,
+): MediaInfo = MediaInfo(
filename = "an apk file.apk",
caption = null,
mimeType = MimeTypes.Apk,
formattedFileSize = "50MB",
fileExtension = "apk",
+ senderName = senderName,
+ dateSent = dateSent,
)
-fun anAudioMediaInfo(): MediaInfo = MediaInfo(
+fun anAudioMediaInfo(
+ senderName: String? = null,
+ dateSent: String? = null,
+): MediaInfo = MediaInfo(
filename = "an audio file.mp3",
caption = null,
mimeType = MimeTypes.Mp3,
formattedFileSize = "7MB",
fileExtension = "mp3",
+ senderName = senderName,
+ dateSent = dateSent,
)
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt
new file mode 100644
index 0000000000..fb5ee5dece
--- /dev/null
+++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.api
+
+import com.bumble.appyx.core.modality.BuildContext
+import com.bumble.appyx.core.node.Node
+import com.bumble.appyx.core.plugin.Plugin
+import io.element.android.libraries.architecture.FeatureEntryPoint
+import io.element.android.libraries.architecture.NodeInputs
+import io.element.android.libraries.matrix.api.media.MediaSource
+
+interface MediaViewerEntryPoint : FeatureEntryPoint {
+ fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
+
+ interface NodeBuilder {
+ fun callback(callback: Callback): NodeBuilder
+ fun params(params: Params): NodeBuilder
+ fun avatar(filename: String, avatarUrl: String): NodeBuilder
+ fun build(): Node
+ }
+
+ interface Callback : Plugin {
+ fun onDone()
+ }
+
+ data class Params(
+ val mediaInfo: MediaInfo,
+ val mediaSource: MediaSource,
+ val thumbnailSource: MediaSource?,
+ val canDownload: Boolean,
+ val canShare: Boolean,
+ ) : NodeInputs
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMedia.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMedia.kt
index 56bda259a6..fade670697 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMedia.kt
+++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMedia.kt
@@ -10,6 +10,7 @@ package io.element.android.libraries.mediaviewer.api.local
import android.net.Uri
import android.os.Parcelable
import androidx.compose.runtime.Immutable
+import io.element.android.libraries.mediaviewer.api.MediaInfo
import kotlinx.parcelize.Parcelize
@Parcelize
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaFactory.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaFactory.kt
index 9200070263..beeccb7c48 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaFactory.kt
+++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaFactory.kt
@@ -9,6 +9,7 @@ package io.element.android.libraries.mediaviewer.api.local
import android.net.Uri
import io.element.android.libraries.matrix.api.media.MediaFile
+import io.element.android.libraries.mediaviewer.api.MediaInfo
interface LocalMediaFactory {
/**
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaRenderer.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaRenderer.kt
new file mode 100644
index 0000000000..3b387ef0d7
--- /dev/null
+++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaRenderer.kt
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.api.local
+
+import androidx.compose.runtime.Composable
+
+interface LocalMediaRenderer {
+ @Composable
+ fun Render(localMedia: LocalMedia)
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaView.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaView.kt
deleted file mode 100644
index 7b63c22121..0000000000
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaView.kt
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2023, 2024 New Vector Ltd.
- *
- * SPDX-License-Identifier: AGPL-3.0-only
- * Please see LICENSE in the repository root for full details.
- */
-
-package io.element.android.libraries.mediaviewer.api.local
-
-import android.annotation.SuppressLint
-import android.net.Uri
-import android.view.View
-import android.view.ViewGroup.LayoutParams.MATCH_PARENT
-import android.widget.FrameLayout
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.interaction.MutableInteractionSource
-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.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.GraphicEq
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.draw.rotate
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalInspectionMode
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.viewinterop.AndroidView
-import androidx.lifecycle.Lifecycle
-import androidx.media3.common.MediaItem
-import androidx.media3.common.Player
-import androidx.media3.ui.AspectRatioFrameLayout
-import androidx.media3.ui.PlayerView
-import io.element.android.compound.theme.ElementTheme
-import io.element.android.compound.tokens.generated.CompoundIcons
-import io.element.android.libraries.core.bool.orFalse
-import io.element.android.libraries.core.mimetype.MimeTypes
-import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAudio
-import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage
-import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo
-import io.element.android.libraries.designsystem.theme.components.Icon
-import io.element.android.libraries.designsystem.theme.components.Text
-import io.element.android.libraries.designsystem.utils.CommonDrawables
-import io.element.android.libraries.designsystem.utils.KeepScreenOn
-import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
-import io.element.android.libraries.mediaviewer.api.helper.formatFileExtensionAndSize
-import io.element.android.libraries.mediaviewer.api.local.exoplayer.ExoPlayerWrapper
-import io.element.android.libraries.mediaviewer.api.local.pdf.PdfViewer
-import io.element.android.libraries.mediaviewer.api.local.pdf.rememberPdfViewerState
-import io.element.android.libraries.ui.strings.CommonStrings
-import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage
-import me.saket.telephoto.zoomable.rememberZoomableImageState
-
-@Composable
-fun LocalMediaView(
- localMedia: LocalMedia?,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
- localMediaViewState: LocalMediaViewState = rememberLocalMediaViewState(),
- mediaInfo: MediaInfo? = localMedia?.info,
-) {
- val mimeType = mediaInfo?.mimeType
- when {
- mimeType.isMimeTypeImage() -> MediaImageView(
- localMediaViewState = localMediaViewState,
- localMedia = localMedia,
- modifier = modifier,
- onClick = onClick,
- )
- mimeType.isMimeTypeVideo() -> MediaVideoView(
- localMediaViewState = localMediaViewState,
- localMedia = localMedia,
- modifier = modifier,
- onClick = onClick,
- )
- mimeType == MimeTypes.Pdf -> MediaPDFView(
- localMediaViewState = localMediaViewState,
- localMedia = localMedia,
- modifier = modifier,
- onClick = onClick,
- )
- // TODO handle audio with exoplayer
- else -> MediaFileView(
- localMediaViewState = localMediaViewState,
- uri = localMedia?.uri,
- info = mediaInfo,
- modifier = modifier,
- onClick = onClick,
- )
- }
-}
-
-@Composable
-private fun MediaImageView(
- localMediaViewState: LocalMediaViewState,
- localMedia: LocalMedia?,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
-) {
- if (LocalInspectionMode.current) {
- Image(
- painter = painterResource(id = CommonDrawables.sample_background),
- modifier = modifier,
- contentDescription = null,
- )
- } else {
- val zoomableImageState = rememberZoomableImageState(localMediaViewState.zoomableState)
- localMediaViewState.isReady = zoomableImageState.isImageDisplayed
- ZoomableAsyncImage(
- modifier = modifier,
- state = zoomableImageState,
- model = localMedia?.uri,
- contentDescription = stringResource(id = CommonStrings.common_image),
- contentScale = ContentScale.Fit,
- onClick = { onClick() }
- )
- }
-}
-
-@Composable
-private fun MediaVideoView(
- localMediaViewState: LocalMediaViewState,
- localMedia: LocalMedia?,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
-) {
- if (LocalInspectionMode.current) {
- Text(
- modifier = modifier
- .background(ElementTheme.colors.bgSubtlePrimary)
- .wrapContentSize(),
- text = "A Video Player will render here",
- )
- } else {
- ExoPlayerMediaVideoView(
- localMediaViewState = localMediaViewState,
- localMedia = localMedia,
- onClick = onClick,
- modifier = modifier,
- )
- }
-}
-
-@SuppressLint("UnsafeOptInUsageError")
-@Composable
-private fun ExoPlayerMediaVideoView(
- localMediaViewState: LocalMediaViewState,
- localMedia: LocalMedia?,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
-) {
- var playableState: PlayableState.Playable by remember {
- mutableStateOf(PlayableState.Playable(isPlaying = false, isShowingControls = false))
- }
- localMediaViewState.playableState = playableState
-
- val context = LocalContext.current
- val playerListener = object : Player.Listener {
- override fun onRenderedFirstFrame() {
- localMediaViewState.isReady = true
- }
-
- override fun onIsPlayingChanged(isPlaying: Boolean) {
- playableState = playableState.copy(isPlaying = isPlaying)
- }
- }
- val exoPlayer = remember {
- ExoPlayerWrapper.create(context)
- .apply {
- addListener(playerListener)
- this.prepare()
- }
- }
- if (localMedia?.uri != null) {
- LaunchedEffect(localMedia.uri) {
- val mediaItem = MediaItem.fromUri(localMedia.uri)
- exoPlayer.setMediaItem(mediaItem)
- }
- } else {
- exoPlayer.setMediaItems(emptyList())
- }
- KeepScreenOn(playableState.isPlaying)
- AndroidView(
- factory = {
- PlayerView(context).apply {
- player = exoPlayer
- resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
- layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
- setOnClickListener {
- onClick()
- }
- setControllerVisibilityListener(PlayerView.ControllerVisibilityListener { visibility ->
- val isShowingControls = visibility == View.VISIBLE
- playableState = playableState.copy(isShowingControls = isShowingControls)
- })
- controllerShowTimeoutMs = 1500
- setShowPreviousButton(false)
- setShowFastForwardButton(false)
- setShowRewindButton(false)
- setShowNextButton(false)
- showController()
- }
- },
- onRelease = { playerView ->
- playerView.setOnClickListener(null)
- playerView.setControllerVisibilityListener(null as PlayerView.ControllerVisibilityListener?)
- playerView.player = null
- },
- modifier = modifier
- )
-
- OnLifecycleEvent { _, event ->
- when (event) {
- Lifecycle.Event.ON_RESUME -> exoPlayer.play()
- Lifecycle.Event.ON_PAUSE -> exoPlayer.pause()
- Lifecycle.Event.ON_DESTROY -> {
- exoPlayer.release()
- exoPlayer.removeListener(playerListener)
- }
- else -> Unit
- }
- }
-}
-
-@Composable
-private fun MediaPDFView(
- localMediaViewState: LocalMediaViewState,
- localMedia: LocalMedia?,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
-) {
- val pdfViewerState = rememberPdfViewerState(
- model = localMedia?.uri,
- zoomableState = localMediaViewState.zoomableState,
- )
- localMediaViewState.isReady = pdfViewerState.isLoaded
- PdfViewer(
- pdfViewerState = pdfViewerState,
- onClick = onClick,
- modifier = modifier,
- )
-}
-
-@Composable
-private fun MediaFileView(
- localMediaViewState: LocalMediaViewState,
- uri: Uri?,
- info: MediaInfo?,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
-) {
- val isAudio = info?.mimeType.isMimeTypeAudio().orFalse()
- localMediaViewState.isReady = uri != null
-
- val interactionSource = remember { MutableInteractionSource() }
- Box(
- modifier = modifier
- .padding(horizontal = 8.dp)
- .clickable(
- onClick = onClick,
- interactionSource = interactionSource,
- indication = null
- ),
- contentAlignment = Alignment.Center
- ) {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Box(
- modifier = Modifier
- .size(72.dp)
- .clip(CircleShape)
- .background(MaterialTheme.colorScheme.onBackground),
- contentAlignment = Alignment.Center,
- ) {
- Icon(
- imageVector = if (isAudio) Icons.Outlined.GraphicEq else CompoundIcons.Attachment(),
- contentDescription = null,
- tint = MaterialTheme.colorScheme.background,
- modifier = Modifier
- .size(32.dp)
- .rotate(if (isAudio) 0f else -45f),
- )
- }
- if (info != null) {
- Spacer(modifier = Modifier.height(20.dp))
- Text(
- text = info.filename,
- maxLines = 2,
- style = ElementTheme.typography.fontBodyLgRegular,
- overflow = TextOverflow.Ellipsis,
- textAlign = TextAlign.Center,
- color = MaterialTheme.colorScheme.primary
- )
- Spacer(modifier = Modifier.height(4.dp))
- Text(
- text = formatFileExtensionAndSize(info.fileExtension, info.formattedFileSize),
- style = ElementTheme.typography.fontBodyMdRegular,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- color = MaterialTheme.colorScheme.primary
- )
- }
- }
- }
-}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractor.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractor.kt
index 32ca151160..e7586a6f87 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractor.kt
+++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractor.kt
@@ -7,30 +7,6 @@
package io.element.android.libraries.mediaviewer.api.util
-import android.webkit.MimeTypeMap
-import com.squareup.anvil.annotations.ContributesBinding
-import io.element.android.libraries.di.AppScope
-import javax.inject.Inject
-
interface FileExtensionExtractor {
fun extractFromName(name: String): String
}
-
-@ContributesBinding(AppScope::class)
-class FileExtensionExtractorWithValidation @Inject constructor() : FileExtensionExtractor {
- override fun extractFromName(name: String): String {
- val fileExtension = name.substringAfterLast('.', "")
- // Makes sure the extension is known by the system, otherwise default to binary extension.
- return if (MimeTypeMap.getSingleton().hasExtension(fileExtension)) {
- fileExtension
- } else {
- "bin"
- }
- }
-}
-
-class FileExtensionExtractorWithoutValidation : FileExtensionExtractor {
- override fun extractFromName(name: String): String {
- return name.substringAfterLast('.', "")
- }
-}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerStateProvider.kt
deleted file mode 100644
index 2ae215ac96..0000000000
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerStateProvider.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2023, 2024 New Vector Ltd.
- *
- * SPDX-License-Identifier: AGPL-3.0-only
- * Please see LICENSE in the repository root for full details.
- */
-
-package io.element.android.libraries.mediaviewer.api.viewer
-
-import android.net.Uri
-import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import io.element.android.libraries.architecture.AsyncData
-import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.local.aPdfMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.aVideoMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anApkMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anAudioMediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anImageMediaInfo
-
-open class MediaViewerStateProvider : PreviewParameterProvider {
- override val values: Sequence
- get() = sequenceOf(
- aMediaViewerState(),
- aMediaViewerState(AsyncData.Loading()),
- aMediaViewerState(AsyncData.Failure(IllegalStateException("error"))),
- aMediaViewerState(
- AsyncData.Success(
- LocalMedia(Uri.EMPTY, anImageMediaInfo())
- ),
- anImageMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Success(
- LocalMedia(Uri.EMPTY, aVideoMediaInfo())
- ),
- aVideoMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Success(
- LocalMedia(Uri.EMPTY, aPdfMediaInfo())
- ),
- aPdfMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Loading(),
- anApkMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Success(
- LocalMedia(Uri.EMPTY, anApkMediaInfo())
- ),
- anApkMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Loading(),
- anAudioMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Success(
- LocalMedia(Uri.EMPTY, anAudioMediaInfo())
- ),
- anAudioMediaInfo(),
- ),
- aMediaViewerState(
- AsyncData.Success(
- LocalMedia(Uri.EMPTY, anImageMediaInfo())
- ),
- anImageMediaInfo(),
- canDownload = false,
- canShare = false,
- ),
- )
-}
-
-fun aMediaViewerState(
- downloadedMedia: AsyncData = AsyncData.Uninitialized,
- mediaInfo: MediaInfo = anImageMediaInfo(),
- canDownload: Boolean = true,
- canShare: Boolean = true,
- eventSink: (MediaViewerEvents) -> Unit = {},
-) = MediaViewerState(
- mediaInfo = mediaInfo,
- thumbnailSource = null,
- downloadedMedia = downloadedMedia,
- snackbarMessage = null,
- canDownload = canDownload,
- canShare = canShare,
- eventSink = eventSink,
-)
diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts
index a814f64ab7..5ebc252343 100644
--- a/libraries/mediaviewer/impl/build.gradle.kts
+++ b/libraries/mediaviewer/impl/build.gradle.kts
@@ -13,6 +13,11 @@ plugins {
android {
namespace = "io.element.android.libraries.mediaviewer.impl"
+ testOptions {
+ unitTests {
+ isIncludeAndroidResources = true
+ }
+ }
}
setupAnvil()
@@ -21,6 +26,23 @@ dependencies {
implementation(libs.coroutines.core)
implementation(libs.dagger)
+ implementation(libs.coil.compose)
+ implementation(libs.androidx.media3.exoplayer)
+ implementation(libs.androidx.media3.ui)
+ implementation(libs.telephoto.zoomableimage)
+ implementation(libs.vanniktech.blurhash)
+ implementation(libs.telephoto.flick)
+
+ implementation(projects.libraries.androidutils)
+ implementation(projects.libraries.architecture)
+ implementation(projects.libraries.core)
+ implementation(projects.libraries.dateformatter.api)
+ implementation(projects.libraries.di)
+ implementation(projects.libraries.designsystem)
+ implementation(projects.libraries.matrix.api)
+ implementation(projects.libraries.matrixui)
+ implementation(projects.libraries.uiStrings)
+
api(projects.libraries.mediaviewer.api)
implementation(projects.libraries.androidutils)
implementation(projects.libraries.core)
@@ -39,4 +61,6 @@ dependencies {
testImplementation(libs.test.turbine)
testImplementation(libs.coroutines.core)
testImplementation(libs.coroutines.test)
+ testImplementation(libs.androidx.compose.ui.test.junit)
+ testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt
new file mode 100644
index 0000000000..86d7bca722
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl
+
+import com.bumble.appyx.core.modality.BuildContext
+import com.bumble.appyx.core.node.Node
+import com.bumble.appyx.core.plugin.Plugin
+import com.squareup.anvil.annotations.ContributesBinding
+import io.element.android.libraries.architecture.createNode
+import io.element.android.libraries.core.mimetype.MimeTypes
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.matrix.api.media.MediaSource
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
+import io.element.android.libraries.mediaviewer.impl.viewer.MediaViewerNode
+import javax.inject.Inject
+
+@ContributesBinding(AppScope::class)
+class DefaultMediaViewerEntryPoint @Inject constructor() : MediaViewerEntryPoint {
+ override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): MediaViewerEntryPoint.NodeBuilder {
+ val plugins = ArrayList()
+
+ return object : MediaViewerEntryPoint.NodeBuilder {
+ override fun callback(callback: MediaViewerEntryPoint.Callback): MediaViewerEntryPoint.NodeBuilder {
+ plugins += callback
+ return this
+ }
+
+ override fun params(params: MediaViewerEntryPoint.Params): MediaViewerEntryPoint.NodeBuilder {
+ plugins += params
+ return this
+ }
+
+ override fun avatar(filename: String, avatarUrl: String): MediaViewerEntryPoint.NodeBuilder {
+ // We need to fake the MimeType here for the viewer to work.
+ val mimeType = MimeTypes.Images
+ return params(
+ MediaViewerEntryPoint.Params(
+ mediaInfo = MediaInfo(
+ filename = filename,
+ caption = null,
+ mimeType = mimeType,
+ formattedFileSize = "",
+ fileExtension = "",
+ senderName = null,
+ dateSent = null,
+ ),
+ mediaSource = MediaSource(url = avatarUrl),
+ thumbnailSource = null,
+ canDownload = false,
+ canShare = false,
+ )
+ )
+ }
+
+ override fun build(): Node {
+ return parentNode.createNode(buildContext, plugins)
+ }
+ }
+ }
+}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt
index 66bed465ed..7bd92a800f 100644
--- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt
@@ -35,7 +35,6 @@ import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.LocalMediaActions
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt
index 06fefa2623..8b5163cf6c 100644
--- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt
@@ -20,9 +20,9 @@ import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.media.MediaFile
import io.element.android.libraries.matrix.api.media.toFile
+import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractor
import javax.inject.Inject
@@ -41,6 +41,8 @@ class AndroidLocalMediaFactory @Inject constructor(
name = mediaInfo.filename,
caption = mediaInfo.caption,
formattedFileSize = mediaInfo.formattedFileSize,
+ senderName = mediaInfo.senderName,
+ dateSent = mediaInfo.dateSent,
)
override fun createFromUri(
@@ -54,6 +56,8 @@ class AndroidLocalMediaFactory @Inject constructor(
name = name,
caption = null,
formattedFileSize = formattedFileSize,
+ senderName = null,
+ dateSent = null,
)
private fun createFromUri(
@@ -61,7 +65,9 @@ class AndroidLocalMediaFactory @Inject constructor(
mimeType: String?,
name: String?,
caption: String?,
- formattedFileSize: String?
+ formattedFileSize: String?,
+ senderName: String?,
+ dateSent: String?,
): LocalMedia {
val resolvedMimeType = mimeType ?: context.getMimeType(uri) ?: MimeTypes.OctetStream
val fileName = name ?: context.getFileName(uri) ?: ""
@@ -74,7 +80,9 @@ class AndroidLocalMediaFactory @Inject constructor(
filename = fileName,
caption = caption,
formattedFileSize = fileSize,
- fileExtension = fileExtension
+ fileExtension = fileExtension,
+ senderName = senderName,
+ dateSent = dateSent,
)
)
}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt
new file mode 100644
index 0000000000..b801ebe00f
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local
+
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.squareup.anvil.annotations.ContributesBinding
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+import io.element.android.libraries.mediaviewer.api.local.LocalMediaRenderer
+import me.saket.telephoto.zoomable.ZoomSpec
+import me.saket.telephoto.zoomable.rememberZoomableState
+import javax.inject.Inject
+
+@ContributesBinding(AppScope::class)
+class DefaultLocalMediaRenderer @Inject constructor() : LocalMediaRenderer {
+ @Composable
+ override fun Render(localMedia: LocalMedia) {
+ val localMediaViewState = rememberLocalMediaViewState(
+ zoomableState = rememberZoomableState(
+ zoomSpec = ZoomSpec(maxZoomFactor = 4f, preventOverOrUnderZoom = false)
+ )
+ )
+ LocalMediaView(
+ modifier = Modifier.fillMaxSize(),
+ bottomPaddingInPixels = 0,
+ localMedia = localMedia,
+ localMediaViewState = localMediaViewState,
+ onClick = {}
+ )
+ }
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaActions.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaActions.kt
similarity index 87%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaActions.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaActions.kt
index c7f0ba7d90..92f873e2ea 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaActions.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaActions.kt
@@ -5,9 +5,10 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local
+package io.element.android.libraries.mediaviewer.impl.local
import androidx.compose.runtime.Composable
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
interface LocalMediaActions {
@Composable
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt
new file mode 100644
index 0000000000..5d0a2993df
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2023, 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import io.element.android.libraries.core.mimetype.MimeTypes
+import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage
+import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+import io.element.android.libraries.mediaviewer.impl.local.file.MediaFileView
+import io.element.android.libraries.mediaviewer.impl.local.image.MediaImageView
+import io.element.android.libraries.mediaviewer.impl.local.pdf.MediaPdfView
+import io.element.android.libraries.mediaviewer.impl.local.video.MediaVideoView
+
+@Composable
+fun LocalMediaView(
+ localMedia: LocalMedia?,
+ bottomPaddingInPixels: Int,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ localMediaViewState: LocalMediaViewState = rememberLocalMediaViewState(),
+ mediaInfo: MediaInfo? = localMedia?.info,
+) {
+ val mimeType = mediaInfo?.mimeType
+ when {
+ mimeType.isMimeTypeImage() -> MediaImageView(
+ localMediaViewState = localMediaViewState,
+ localMedia = localMedia,
+ modifier = modifier,
+ onClick = onClick,
+ )
+ mimeType.isMimeTypeVideo() -> MediaVideoView(
+ localMediaViewState = localMediaViewState,
+ bottomPaddingInPixels = bottomPaddingInPixels,
+ localMedia = localMedia,
+ modifier = modifier,
+ )
+ mimeType == MimeTypes.Pdf -> MediaPdfView(
+ localMediaViewState = localMediaViewState,
+ localMedia = localMedia,
+ modifier = modifier,
+ onClick = onClick,
+ )
+ // TODO handle audio with exoplayer
+ else -> MediaFileView(
+ localMediaViewState = localMediaViewState,
+ uri = localMedia?.uri,
+ info = mediaInfo,
+ modifier = modifier,
+ onClick = onClick,
+ )
+ }
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaViewState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaViewState.kt
similarity index 89%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaViewState.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaViewState.kt
index 0c4e2af308..8705ef49d3 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/LocalMediaViewState.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaViewState.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local
+package io.element.android.libraries.mediaviewer.impl.local
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
@@ -29,8 +29,7 @@ class LocalMediaViewState internal constructor(
sealed interface PlayableState {
data object NotPlayable : PlayableState
data class Playable(
- val isPlaying: Boolean,
- val isShowingControls: Boolean
+ val isShowingControls: Boolean,
) : PlayableState
}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt
new file mode 100644
index 0000000000..ec50ef9f4c
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.file
+
+import android.net.Uri
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.GraphicEq
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
+import io.element.android.compound.tokens.generated.CompoundIcons
+import io.element.android.libraries.core.bool.orFalse
+import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAudio
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.theme.components.Icon
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.helper.formatFileExtensionAndSize
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaViewState
+import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState
+
+@Composable
+fun MediaFileView(
+ localMediaViewState: LocalMediaViewState,
+ uri: Uri?,
+ info: MediaInfo?,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ val isAudio = info?.mimeType.isMimeTypeAudio().orFalse()
+ localMediaViewState.isReady = uri != null
+
+ val interactionSource = remember { MutableInteractionSource() }
+ Box(
+ modifier = modifier
+ .padding(horizontal = 8.dp)
+ .clickable(
+ onClick = onClick,
+ interactionSource = interactionSource,
+ indication = null
+ ),
+ contentAlignment = Alignment.Center
+ ) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Box(
+ modifier = Modifier
+ .size(72.dp)
+ .clip(CircleShape)
+ .background(MaterialTheme.colorScheme.onBackground),
+ contentAlignment = Alignment.Center,
+ ) {
+ Icon(
+ imageVector = if (isAudio) Icons.Outlined.GraphicEq else CompoundIcons.Attachment(),
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.background,
+ modifier = Modifier
+ .size(32.dp)
+ .rotate(if (isAudio) 0f else -45f),
+ )
+ }
+ if (info != null) {
+ Spacer(modifier = Modifier.height(20.dp))
+ Text(
+ text = info.filename,
+ maxLines = 2,
+ style = ElementTheme.typography.fontBodyLgRegular,
+ overflow = TextOverflow.Ellipsis,
+ textAlign = TextAlign.Center,
+ color = MaterialTheme.colorScheme.primary
+ )
+ Spacer(modifier = Modifier.height(4.dp))
+ Text(
+ text = formatFileExtensionAndSize(info.fileExtension, info.formattedFileSize),
+ style = ElementTheme.typography.fontBodyMdRegular,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ color = MaterialTheme.colorScheme.primary
+ )
+ }
+ }
+ }
+}
+
+@PreviewsDayNight
+@Composable
+internal fun MediaFileViewPreview(
+ @PreviewParameter(MediaInfoFileProvider::class) info: MediaInfo
+) = ElementPreview {
+ MediaFileView(
+ modifier = Modifier.fillMaxSize(),
+ localMediaViewState = rememberLocalMediaViewState(),
+ uri = null,
+ info = info,
+ onClick = {},
+ )
+}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt
new file mode 100644
index 0000000000..980f9eba89
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.file
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.aPdfMediaInfo
+import io.element.android.libraries.mediaviewer.api.anAudioMediaInfo
+
+open class MediaInfoFileProvider : PreviewParameterProvider {
+ override val values: Sequence
+ get() = sequenceOf(
+ aPdfMediaInfo(),
+ anAudioMediaInfo(),
+ )
+}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt
new file mode 100644
index 0000000000..a286b7dc2d
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.image
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalInspectionMode
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.utils.CommonDrawables
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaViewState
+import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState
+import io.element.android.libraries.ui.strings.CommonStrings
+import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage
+import me.saket.telephoto.zoomable.rememberZoomableImageState
+
+@Composable
+fun MediaImageView(
+ localMediaViewState: LocalMediaViewState,
+ localMedia: LocalMedia?,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ if (LocalInspectionMode.current) {
+ Image(
+ painter = painterResource(id = CommonDrawables.sample_background),
+ modifier = modifier,
+ contentDescription = null,
+ )
+ } else {
+ val zoomableImageState = rememberZoomableImageState(localMediaViewState.zoomableState)
+ localMediaViewState.isReady = zoomableImageState.isImageDisplayed
+ ZoomableAsyncImage(
+ modifier = modifier,
+ state = zoomableImageState,
+ model = localMedia?.uri,
+ contentDescription = stringResource(id = CommonStrings.common_image),
+ contentScale = ContentScale.Fit,
+ onClick = { onClick() }
+ )
+ }
+}
+
+@PreviewsDayNight
+@Composable
+internal fun MediaImageViewPreview() = ElementPreview {
+ MediaImageView(
+ modifier = Modifier.fillMaxSize(),
+ localMediaViewState = rememberLocalMediaViewState(),
+ localMedia = null,
+ onClick = {},
+ )
+}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/MediaPdfView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/MediaPdfView.kt
new file mode 100644
index 0000000000..f2694fb277
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/MediaPdfView.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.pdf
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaViewState
+
+@Composable
+fun MediaPdfView(
+ localMediaViewState: LocalMediaViewState,
+ localMedia: LocalMedia?,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ val pdfViewerState = rememberPdfViewerState(
+ model = localMedia?.uri,
+ zoomableState = localMediaViewState.zoomableState,
+ )
+ localMediaViewState.isReady = pdfViewerState.isLoaded
+ PdfViewer(
+ pdfViewerState = pdfViewerState,
+ onClick = onClick,
+ modifier = modifier,
+ )
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/ParcelFileDescriptorFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/ParcelFileDescriptorFactory.kt
similarity index 91%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/ParcelFileDescriptorFactory.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/ParcelFileDescriptorFactory.kt
index e73f24ea61..bd931cadcb 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/ParcelFileDescriptorFactory.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/ParcelFileDescriptorFactory.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local.pdf
+package io.element.android.libraries.mediaviewer.impl.local.pdf
import android.content.Context
import android.net.Uri
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfPage.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfPage.kt
similarity index 98%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfPage.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfPage.kt
index 137c3e321f..655d577fda 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfPage.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfPage.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local.pdf
+package io.element.android.libraries.mediaviewer.impl.local.pdf
import android.graphics.Bitmap
import android.graphics.Canvas
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfRendererManager.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfRendererManager.kt
similarity index 97%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfRendererManager.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfRendererManager.kt
index 255822b853..02f5ef58bf 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfRendererManager.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfRendererManager.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local.pdf
+package io.element.android.libraries.mediaviewer.impl.local.pdf
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfViewer.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfViewer.kt
similarity index 98%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfViewer.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfViewer.kt
index 6202db88b1..ffb8e83d45 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfViewer.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfViewer.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local.pdf
+package io.element.android.libraries.mediaviewer.impl.local.pdf
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfViewerState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfViewerState.kt
similarity index 97%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfViewerState.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfViewerState.kt
index 72eb73c301..095d4d15c4 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/pdf/PdfViewerState.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/pdf/PdfViewerState.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local.pdf
+package io.element.android.libraries.mediaviewer.impl.local.pdf
import android.content.Context
import androidx.compose.foundation.lazy.LazyListState
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/ExoPlayerForPreview.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/ExoPlayerForPreview.kt
new file mode 100644
index 0000000000..c517637576
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/ExoPlayerForPreview.kt
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+@file:Suppress(
+ "OVERRIDE_DEPRECATION",
+ "RedundantNullableReturnType",
+ "DEPRECATION",
+)
+
+package io.element.android.libraries.mediaviewer.impl.local.video
+
+import android.annotation.SuppressLint
+import android.media.AudioDeviceInfo
+import android.os.Looper
+import android.view.Surface
+import android.view.SurfaceHolder
+import android.view.SurfaceView
+import android.view.TextureView
+import androidx.media3.common.AudioAttributes
+import androidx.media3.common.AuxEffectInfo
+import androidx.media3.common.DeviceInfo
+import androidx.media3.common.Effect
+import androidx.media3.common.Format
+import androidx.media3.common.MediaItem
+import androidx.media3.common.MediaMetadata
+import androidx.media3.common.PlaybackParameters
+import androidx.media3.common.Player
+import androidx.media3.common.PriorityTaskManager
+import androidx.media3.common.Timeline
+import androidx.media3.common.TrackSelectionParameters
+import androidx.media3.common.Tracks
+import androidx.media3.common.VideoSize
+import androidx.media3.common.text.CueGroup
+import androidx.media3.common.util.Clock
+import androidx.media3.common.util.Size
+import androidx.media3.exoplayer.DecoderCounters
+import androidx.media3.exoplayer.ExoPlaybackException
+import androidx.media3.exoplayer.ExoPlayer
+import androidx.media3.exoplayer.PlayerMessage
+import androidx.media3.exoplayer.Renderer
+import androidx.media3.exoplayer.SeekParameters
+import androidx.media3.exoplayer.analytics.AnalyticsCollector
+import androidx.media3.exoplayer.analytics.AnalyticsListener
+import androidx.media3.exoplayer.image.ImageOutput
+import androidx.media3.exoplayer.source.MediaSource
+import androidx.media3.exoplayer.source.ShuffleOrder
+import androidx.media3.exoplayer.source.TrackGroupArray
+import androidx.media3.exoplayer.trackselection.TrackSelectionArray
+import androidx.media3.exoplayer.trackselection.TrackSelector
+import androidx.media3.exoplayer.video.VideoFrameMetadataListener
+import androidx.media3.exoplayer.video.spherical.CameraMotionListener
+import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
+
+@SuppressLint("UnsafeOptInUsageError")
+@ExcludeFromCoverage
+class ExoPlayerForPreview(
+ private val isPlaying: Boolean = false,
+) : ExoPlayer {
+ override fun getApplicationLooper(): Looper = throw NotImplementedError()
+ override fun addListener(listener: Player.Listener) {}
+ override fun removeListener(listener: Player.Listener) {}
+ override fun setMediaItems(mediaItems: MutableList) {}
+ override fun setMediaItems(mediaItems: MutableList, resetPosition: Boolean) {}
+ override fun setMediaItems(mediaItems: MutableList, startIndex: Int, startPositionMs: Long) {}
+ override fun setMediaItem(mediaItem: MediaItem) {}
+ override fun setMediaItem(mediaItem: MediaItem, startPositionMs: Long) {}
+ override fun setMediaItem(mediaItem: MediaItem, resetPosition: Boolean) {}
+ override fun addMediaItem(mediaItem: MediaItem) {}
+ override fun addMediaItem(index: Int, mediaItem: MediaItem) {}
+ override fun addMediaItems(mediaItems: MutableList) {}
+ override fun addMediaItems(index: Int, mediaItems: MutableList) {}
+ override fun moveMediaItem(currentIndex: Int, newIndex: Int) {}
+ override fun moveMediaItems(fromIndex: Int, toIndex: Int, newIndex: Int) {}
+ override fun replaceMediaItem(index: Int, mediaItem: MediaItem) {}
+ override fun replaceMediaItems(fromIndex: Int, toIndex: Int, mediaItems: MutableList) {}
+ override fun removeMediaItem(index: Int) {}
+ override fun removeMediaItems(fromIndex: Int, toIndex: Int) {}
+ override fun clearMediaItems() {}
+ override fun isCommandAvailable(command: Int): Boolean = throw NotImplementedError()
+ override fun canAdvertiseSession(): Boolean = throw NotImplementedError()
+ override fun getAvailableCommands(): Player.Commands = throw NotImplementedError()
+ override fun prepare(mediaSource: MediaSource) {}
+ override fun prepare(mediaSource: MediaSource, resetPosition: Boolean, resetState: Boolean) {}
+ override fun prepare() {}
+ override fun getPlaybackState(): Int = throw NotImplementedError()
+ override fun getPlaybackSuppressionReason(): Int = throw NotImplementedError()
+ override fun isPlaying() = isPlaying
+ override fun getPlayerError(): ExoPlaybackException? = null
+ override fun play() {}
+ override fun pause() {}
+ override fun setPlayWhenReady(playWhenReady: Boolean) {}
+ override fun getPlayWhenReady(): Boolean = throw NotImplementedError()
+ override fun setRepeatMode(repeatMode: Int) {}
+ override fun getRepeatMode(): Int = throw NotImplementedError()
+ override fun setShuffleModeEnabled(shuffleModeEnabled: Boolean) {}
+ override fun getShuffleModeEnabled(): Boolean = throw NotImplementedError()
+ override fun isLoading(): Boolean = throw NotImplementedError()
+ override fun seekToDefaultPosition() {}
+ override fun seekToDefaultPosition(mediaItemIndex: Int) {}
+ override fun seekTo(positionMs: Long) {}
+ override fun seekTo(mediaItemIndex: Int, positionMs: Long) {}
+ override fun getSeekBackIncrement(): Long = throw NotImplementedError()
+ override fun seekBack() {}
+ override fun getSeekForwardIncrement(): Long = throw NotImplementedError()
+ override fun seekForward() {}
+ override fun hasPreviousMediaItem(): Boolean = throw NotImplementedError()
+ override fun seekToPreviousWindow() {}
+ override fun seekToPreviousMediaItem() {}
+ override fun getMaxSeekToPreviousPosition(): Long = throw NotImplementedError()
+ override fun seekToPrevious() {}
+ override fun hasNext(): Boolean = throw NotImplementedError()
+ override fun hasNextWindow(): Boolean = throw NotImplementedError()
+ override fun hasNextMediaItem(): Boolean = throw NotImplementedError()
+ override fun next() {}
+ override fun seekToNextWindow() {}
+ override fun seekToNextMediaItem() {}
+ override fun seekToNext() {}
+ override fun setPlaybackParameters(playbackParameters: PlaybackParameters) {}
+ override fun setPlaybackSpeed(speed: Float) {}
+ override fun getPlaybackParameters(): PlaybackParameters = throw NotImplementedError()
+ override fun stop() {}
+ override fun release() {}
+ override fun getCurrentTracks(): Tracks = throw NotImplementedError()
+ override fun getTrackSelectionParameters(): TrackSelectionParameters = throw NotImplementedError()
+ override fun setTrackSelectionParameters(parameters: TrackSelectionParameters) {}
+ override fun getMediaMetadata(): MediaMetadata = throw NotImplementedError()
+ override fun getPlaylistMetadata(): MediaMetadata = throw NotImplementedError()
+ override fun setPlaylistMetadata(mediaMetadata: MediaMetadata) {}
+ override fun getCurrentManifest(): Any? = throw NotImplementedError()
+ override fun getCurrentTimeline(): Timeline = throw NotImplementedError()
+ override fun getCurrentPeriodIndex(): Int = throw NotImplementedError()
+ override fun getCurrentWindowIndex(): Int = throw NotImplementedError()
+ override fun getCurrentMediaItemIndex(): Int = throw NotImplementedError()
+ override fun getNextWindowIndex(): Int = throw NotImplementedError()
+ override fun getNextMediaItemIndex(): Int = throw NotImplementedError()
+ override fun getPreviousWindowIndex(): Int = throw NotImplementedError()
+ override fun getPreviousMediaItemIndex(): Int = throw NotImplementedError()
+ override fun getCurrentMediaItem(): MediaItem? = throw NotImplementedError()
+ override fun getMediaItemCount(): Int = throw NotImplementedError()
+ override fun getMediaItemAt(index: Int): MediaItem = throw NotImplementedError()
+ override fun getDuration(): Long = throw NotImplementedError()
+ override fun getCurrentPosition(): Long = throw NotImplementedError()
+ override fun getBufferedPosition(): Long = throw NotImplementedError()
+ override fun getBufferedPercentage(): Int = throw NotImplementedError()
+ override fun getTotalBufferedDuration(): Long = throw NotImplementedError()
+ override fun isCurrentWindowDynamic(): Boolean = throw NotImplementedError()
+ override fun isCurrentMediaItemDynamic(): Boolean = throw NotImplementedError()
+ override fun isCurrentWindowLive(): Boolean = throw NotImplementedError()
+ override fun isCurrentMediaItemLive(): Boolean = throw NotImplementedError()
+ override fun getCurrentLiveOffset(): Long = throw NotImplementedError()
+ override fun isCurrentWindowSeekable(): Boolean = throw NotImplementedError()
+ override fun isCurrentMediaItemSeekable(): Boolean = throw NotImplementedError()
+ override fun isPlayingAd(): Boolean = throw NotImplementedError()
+ override fun getCurrentAdGroupIndex(): Int = throw NotImplementedError()
+ override fun getCurrentAdIndexInAdGroup(): Int = throw NotImplementedError()
+ override fun getContentDuration(): Long = throw NotImplementedError()
+ override fun getContentPosition(): Long = throw NotImplementedError()
+ override fun getContentBufferedPosition(): Long = throw NotImplementedError()
+ override fun getAudioAttributes(): AudioAttributes = throw NotImplementedError()
+ override fun setVolume(volume: Float) = throw NotImplementedError()
+ override fun getVolume(): Float = throw NotImplementedError()
+ override fun clearVideoSurface() {}
+ override fun clearVideoSurface(surface: Surface?) {}
+ override fun setVideoSurface(surface: Surface?) {}
+ override fun setVideoSurfaceHolder(surfaceHolder: SurfaceHolder?) {}
+ override fun clearVideoSurfaceHolder(surfaceHolder: SurfaceHolder?) {}
+ override fun setVideoSurfaceView(surfaceView: SurfaceView?) {}
+ override fun clearVideoSurfaceView(surfaceView: SurfaceView?) {}
+ override fun setVideoTextureView(textureView: TextureView?) {}
+ override fun clearVideoTextureView(textureView: TextureView?) {}
+ override fun getVideoSize(): VideoSize = throw NotImplementedError()
+ override fun getSurfaceSize(): Size = throw NotImplementedError()
+ override fun getCurrentCues(): CueGroup = throw NotImplementedError()
+ override fun getDeviceInfo(): DeviceInfo = throw NotImplementedError()
+ override fun getDeviceVolume(): Int = throw NotImplementedError()
+ override fun isDeviceMuted(): Boolean = throw NotImplementedError()
+ override fun setDeviceVolume(volume: Int) {}
+ override fun setDeviceVolume(volume: Int, flags: Int) {}
+ override fun increaseDeviceVolume() {}
+ override fun increaseDeviceVolume(flags: Int) {}
+ override fun decreaseDeviceVolume() {}
+ override fun decreaseDeviceVolume(flags: Int) {}
+ override fun setDeviceMuted(muted: Boolean) {}
+ override fun setDeviceMuted(muted: Boolean, flags: Int) {}
+ override fun setAudioAttributes(audioAttributes: AudioAttributes, handleAudioFocus: Boolean) {}
+ override fun getAudioComponent(): ExoPlayer.AudioComponent? = throw NotImplementedError()
+ override fun getVideoComponent(): ExoPlayer.VideoComponent? = throw NotImplementedError()
+ override fun getTextComponent(): ExoPlayer.TextComponent? = throw NotImplementedError()
+ override fun getDeviceComponent(): ExoPlayer.DeviceComponent? = throw NotImplementedError()
+ override fun addAudioOffloadListener(listener: ExoPlayer.AudioOffloadListener) {}
+ override fun removeAudioOffloadListener(listener: ExoPlayer.AudioOffloadListener) {}
+ override fun getAnalyticsCollector(): AnalyticsCollector = throw NotImplementedError()
+ override fun addAnalyticsListener(listener: AnalyticsListener) {}
+ override fun removeAnalyticsListener(listener: AnalyticsListener) {}
+ override fun getRendererCount(): Int = throw NotImplementedError()
+ override fun getRendererType(index: Int): Int = throw NotImplementedError()
+ override fun getRenderer(index: Int): Renderer = throw NotImplementedError()
+ override fun getTrackSelector(): TrackSelector? = throw NotImplementedError()
+ override fun getCurrentTrackGroups(): TrackGroupArray = throw NotImplementedError()
+ override fun getCurrentTrackSelections(): TrackSelectionArray = throw NotImplementedError()
+ override fun getPlaybackLooper(): Looper = throw NotImplementedError()
+ override fun getClock(): Clock = throw NotImplementedError()
+ override fun setMediaSources(mediaSources: MutableList) {}
+ override fun setMediaSources(mediaSources: MutableList, resetPosition: Boolean) {}
+ override fun setMediaSources(mediaSources: MutableList, startMediaItemIndex: Int, startPositionMs: Long) {}
+ override fun setMediaSource(mediaSource: MediaSource) {}
+ override fun setMediaSource(mediaSource: MediaSource, startPositionMs: Long) {}
+ override fun setMediaSource(mediaSource: MediaSource, resetPosition: Boolean) {}
+ override fun addMediaSource(mediaSource: MediaSource) {}
+ override fun addMediaSource(index: Int, mediaSource: MediaSource) {}
+ override fun addMediaSources(mediaSources: MutableList) {}
+ override fun addMediaSources(index: Int, mediaSources: MutableList) {}
+ override fun setShuffleOrder(shuffleOrder: ShuffleOrder) {}
+ override fun setPreloadConfiguration(preloadConfiguration: ExoPlayer.PreloadConfiguration) {}
+ override fun getPreloadConfiguration(): ExoPlayer.PreloadConfiguration = throw NotImplementedError()
+ override fun setAudioSessionId(audioSessionId: Int) {}
+ override fun getAudioSessionId(): Int = throw NotImplementedError()
+ override fun setAuxEffectInfo(auxEffectInfo: AuxEffectInfo) {}
+ override fun clearAuxEffectInfo() {}
+ override fun setPreferredAudioDevice(audioDeviceInfo: AudioDeviceInfo?) {}
+ override fun setSkipSilenceEnabled(skipSilenceEnabled: Boolean) {}
+ override fun getSkipSilenceEnabled(): Boolean = throw NotImplementedError()
+ override fun setVideoEffects(videoEffects: MutableList) {}
+ override fun setVideoScalingMode(videoScalingMode: Int) {}
+ override fun getVideoScalingMode(): Int = throw NotImplementedError()
+ override fun setVideoChangeFrameRateStrategy(videoChangeFrameRateStrategy: Int) {}
+ override fun getVideoChangeFrameRateStrategy(): Int = throw NotImplementedError()
+ override fun setVideoFrameMetadataListener(listener: VideoFrameMetadataListener) {}
+ override fun clearVideoFrameMetadataListener(listener: VideoFrameMetadataListener) {}
+ override fun setCameraMotionListener(listener: CameraMotionListener) {}
+ override fun clearCameraMotionListener(listener: CameraMotionListener) {}
+ override fun createMessage(target: PlayerMessage.Target): PlayerMessage = throw NotImplementedError()
+ override fun setSeekParameters(seekParameters: SeekParameters?) {}
+ override fun getSeekParameters(): SeekParameters = throw NotImplementedError()
+ override fun setForegroundMode(foregroundMode: Boolean) {}
+ override fun setPauseAtEndOfMediaItems(pauseAtEndOfMediaItems: Boolean) {}
+ override fun getPauseAtEndOfMediaItems(): Boolean = throw NotImplementedError()
+ override fun getAudioFormat(): Format? = throw NotImplementedError()
+ override fun getVideoFormat(): Format? = throw NotImplementedError()
+ override fun getAudioDecoderCounters(): DecoderCounters? = throw NotImplementedError()
+ override fun getVideoDecoderCounters(): DecoderCounters? = throw NotImplementedError()
+ override fun setHandleAudioBecomingNoisy(handleAudioBecomingNoisy: Boolean) {}
+ override fun setWakeMode(wakeMode: Int) {}
+ override fun setPriority(priority: Int) {}
+ override fun setPriorityTaskManager(priorityTaskManager: PriorityTaskManager?) {}
+ override fun isSleepingForOffload(): Boolean = throw NotImplementedError()
+ override fun isTunnelingEnabled(): Boolean = throw NotImplementedError()
+ override fun isReleased(): Boolean = throw NotImplementedError()
+ override fun setImageOutput(imageOutput: ImageOutput?) {}
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/exoplayer/ExoPlayerWrapper.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/ExoPlayerWrapper.kt
similarity index 93%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/exoplayer/ExoPlayerWrapper.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/ExoPlayerWrapper.kt
index 740f1675e0..fef307c155 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/local/exoplayer/ExoPlayerWrapper.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/ExoPlayerWrapper.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.local.exoplayer
+package io.element.android.libraries.mediaviewer.impl.local.video
import android.content.Context
import androidx.media3.common.Player
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerState.kt
new file mode 100644
index 0000000000..c4e4b913a7
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerState.kt
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.video
+
+data class MediaPlayerControllerState(
+ val isVisible: Boolean,
+ val isPlaying: Boolean,
+ val progressInMillis: Long,
+ val durationInMillis: Long,
+ val isMuted: Boolean,
+)
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerStateProvider.kt
new file mode 100644
index 0000000000..78059bd4eb
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerStateProvider.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.video
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+
+open class MediaPlayerControllerStateProvider : PreviewParameterProvider {
+ override val values: Sequence = sequenceOf(
+ aMediaPlayerControllerState(),
+ aMediaPlayerControllerState(
+ isPlaying = true,
+ progressInMillis = 59_000,
+ durationInMillis = 83_000,
+ isMuted = true,
+ ),
+ )
+}
+
+private fun aMediaPlayerControllerState(
+ isVisible: Boolean = true,
+ isPlaying: Boolean = false,
+ progressInMillis: Long = 0,
+ // Default to 1 minute and 23 seconds
+ durationInMillis: Long = 83_000,
+ isMuted: Boolean = false,
+) = MediaPlayerControllerState(
+ isVisible = isVisible,
+ isPlaying = isPlaying,
+ progressInMillis = progressInMillis,
+ durationInMillis = durationInMillis,
+ isMuted = isMuted,
+)
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt
new file mode 100644
index 0000000000..2a5757aa94
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.video
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
+import io.element.android.compound.tokens.generated.CompoundIcons
+import io.element.android.libraries.dateformatter.api.toHumanReadableDuration
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.theme.components.Icon
+import io.element.android.libraries.designsystem.theme.components.IconButton
+import io.element.android.libraries.designsystem.theme.components.Slider
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.ui.strings.CommonStrings
+
+@Composable
+fun MediaPlayerControllerView(
+ state: MediaPlayerControllerState,
+ onTogglePlay: () -> Unit,
+ onSeekChange: (Float) -> Unit,
+ onToggleMute: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ AnimatedVisibility(
+ visible = state.isVisible,
+ modifier = modifier,
+ enter = fadeIn(),
+ exit = fadeOut(),
+ ) {
+ Box(
+ modifier = Modifier
+ .background(color = Color(0x99101317))
+ .padding(horizontal = 8.dp, vertical = 4.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ Row(
+ modifier = Modifier
+ .widthIn(max = 480.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ val bgColor = if (state.isPlaying) {
+ ElementTheme.colors.bgCanvasDefault
+ } else {
+ ElementTheme.colors.textPrimary
+ }
+ Box(
+ modifier = Modifier
+ .size(36.dp)
+ .background(
+ color = bgColor,
+ shape = CircleShape,
+ )
+ .clip(CircleShape)
+ .clickable { onTogglePlay() }
+ .padding(8.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ if (state.isPlaying) {
+ Icon(
+ imageVector = CompoundIcons.PauseSolid(),
+ tint = ElementTheme.colors.iconPrimary,
+ contentDescription = stringResource(CommonStrings.a11y_pause)
+ )
+ } else {
+ Icon(
+ imageVector = CompoundIcons.PlaySolid(),
+ tint = ElementTheme.colors.iconOnSolidPrimary,
+ contentDescription = stringResource(CommonStrings.a11y_play)
+ )
+ }
+ }
+ Text(
+ modifier = Modifier
+ .widthIn(min = 48.dp)
+ .padding(horizontal = 8.dp),
+ text = state.progressInMillis.toHumanReadableDuration(),
+ textAlign = TextAlign.Center,
+ color = ElementTheme.colors.textPrimary,
+ style = ElementTheme.typography.fontBodyXsMedium,
+ )
+ var lastSelectedValue by remember { mutableFloatStateOf(-1f) }
+ Slider(
+ modifier = Modifier.weight(1f),
+ valueRange = 0f..state.durationInMillis.toFloat(),
+ value = lastSelectedValue.takeIf { it >= 0 } ?: state.progressInMillis.toFloat(),
+ onValueChange = {
+ lastSelectedValue = it
+ },
+ onValueChangeFinish = {
+ onSeekChange(lastSelectedValue)
+ lastSelectedValue = -1f
+ },
+ useCustomLayout = true,
+ )
+ val formattedDuration = remember(state.durationInMillis) {
+ state.durationInMillis.toHumanReadableDuration()
+ }
+ Text(
+ modifier = Modifier
+ .widthIn(min = 48.dp)
+ .padding(horizontal = 8.dp),
+ text = formattedDuration,
+ textAlign = TextAlign.Center,
+ color = ElementTheme.colors.textPrimary,
+ style = ElementTheme.typography.fontBodyXsMedium,
+ )
+ IconButton(
+ onClick = onToggleMute,
+ ) {
+ if (state.isMuted) {
+ Icon(
+ imageVector = CompoundIcons.VolumeOffSolid(),
+ tint = ElementTheme.colors.iconPrimary,
+ contentDescription = stringResource(CommonStrings.common_unmute)
+ )
+ } else {
+ Icon(
+ imageVector = CompoundIcons.VolumeOnSolid(),
+ tint = ElementTheme.colors.iconPrimary,
+ contentDescription = stringResource(CommonStrings.common_mute)
+ )
+ }
+ }
+ }
+ }
+ }
+}
+
+@PreviewsDayNight
+@Composable
+internal fun MediaPlayerControllerViewPreview(
+ @PreviewParameter(MediaPlayerControllerStateProvider::class) state: MediaPlayerControllerState
+) = ElementPreview {
+ MediaPlayerControllerView(
+ state = state,
+ onTogglePlay = {},
+ onSeekChange = {},
+ onToggleMute = {},
+ )
+}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt
new file mode 100644
index 0000000000..1faba6f9e5
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.local.video
+
+import android.annotation.SuppressLint
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.widget.FrameLayout
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalInspectionMode
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.lifecycle.Lifecycle
+import androidx.media3.common.MediaItem
+import androidx.media3.common.Player
+import androidx.media3.common.Timeline
+import androidx.media3.exoplayer.ExoPlayer
+import androidx.media3.ui.AspectRatioFrameLayout
+import androidx.media3.ui.PlayerView
+import io.element.android.compound.theme.ElementTheme
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.text.toDp
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.utils.KeepScreenOn
+import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaViewState
+import io.element.android.libraries.mediaviewer.impl.local.PlayableState
+import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState
+import kotlinx.coroutines.delay
+import kotlin.time.Duration.Companion.seconds
+
+@SuppressLint("UnsafeOptInUsageError")
+@Composable
+fun MediaVideoView(
+ localMediaViewState: LocalMediaViewState,
+ bottomPaddingInPixels: Int,
+ localMedia: LocalMedia?,
+ modifier: Modifier = Modifier,
+) {
+ val exoPlayer = if (LocalInspectionMode.current) {
+ remember {
+ ExoPlayerForPreview()
+ }
+ } else {
+ val context = LocalContext.current
+ remember {
+ ExoPlayerWrapper.create(context)
+ }
+ }
+ ExoPlayerMediaVideoView(
+ localMediaViewState = localMediaViewState,
+ bottomPaddingInPixels = bottomPaddingInPixels,
+ exoPlayer = exoPlayer,
+ localMedia = localMedia,
+ modifier = modifier,
+ )
+}
+
+@SuppressLint("UnsafeOptInUsageError")
+@Composable
+private fun ExoPlayerMediaVideoView(
+ localMediaViewState: LocalMediaViewState,
+ bottomPaddingInPixels: Int,
+ exoPlayer: ExoPlayer,
+ localMedia: LocalMedia?,
+ modifier: Modifier = Modifier,
+) {
+ var mediaPlayerControllerState: MediaPlayerControllerState by remember {
+ mutableStateOf(
+ MediaPlayerControllerState(
+ isVisible = true,
+ isPlaying = false,
+ progressInMillis = 0,
+ durationInMillis = 0,
+ isMuted = false,
+ )
+ )
+ }
+
+ val playableState: PlayableState.Playable by remember {
+ derivedStateOf {
+ PlayableState.Playable(
+ isShowingControls = mediaPlayerControllerState.isVisible,
+ )
+ }
+ }
+
+ localMediaViewState.playableState = playableState
+
+ val playerListener = object : Player.Listener {
+ override fun onRenderedFirstFrame() {
+ localMediaViewState.isReady = true
+ }
+
+ override fun onIsPlayingChanged(isPlaying: Boolean) {
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ isPlaying = isPlaying,
+ )
+ }
+
+ override fun onVolumeChanged(volume: Float) {
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ isMuted = volume == 0f,
+ )
+ }
+
+ override fun onTimelineChanged(timeline: Timeline, reason: Int) {
+ if (reason == Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE) {
+ exoPlayer.duration.takeIf { it >= 0 }
+ ?.let {
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ durationInMillis = it,
+ )
+ }
+ }
+ }
+ }
+
+ var autoHideController by remember { mutableIntStateOf(0) }
+
+ LaunchedEffect(autoHideController) {
+ delay(5.seconds)
+ if (exoPlayer.isPlaying) {
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ isVisible = false,
+ )
+ }
+ }
+
+ LaunchedEffect(exoPlayer.isPlaying) {
+ if (exoPlayer.isPlaying) {
+ while (true) {
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ progressInMillis = exoPlayer.currentPosition,
+ )
+ delay(200)
+ }
+ } else {
+ // Ensure we render the final state
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ progressInMillis = exoPlayer.currentPosition,
+ )
+ }
+ }
+ if (localMedia?.uri != null) {
+ LaunchedEffect(localMedia.uri) {
+ val mediaItem = MediaItem.fromUri(localMedia.uri)
+ exoPlayer.setMediaItem(mediaItem)
+ }
+ } else {
+ exoPlayer.setMediaItems(emptyList())
+ }
+ KeepScreenOn(mediaPlayerControllerState.isPlaying)
+ Box(
+ modifier = modifier
+ .background(ElementTheme.colors.bgSubtlePrimary),
+ ) {
+ val context = LocalContext.current
+ if (LocalInspectionMode.current) {
+ Text(
+ modifier = Modifier
+ .background(ElementTheme.colors.bgSubtlePrimary)
+ .align(Alignment.Center),
+ text = "A Video Player will render here",
+ )
+ } else {
+ AndroidView(
+ modifier = Modifier.fillMaxSize(),
+ factory = {
+ PlayerView(context).apply {
+ player = exoPlayer
+ resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
+ layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ setOnClickListener {
+ autoHideController++
+ mediaPlayerControllerState = mediaPlayerControllerState.copy(
+ isVisible = !mediaPlayerControllerState.isVisible,
+ )
+ }
+ useController = false
+ }
+ },
+ onRelease = { playerView ->
+ playerView.setOnClickListener(null)
+ playerView.setControllerVisibilityListener(null as PlayerView.ControllerVisibilityListener?)
+ playerView.player = null
+ },
+ )
+ }
+ MediaPlayerControllerView(
+ state = mediaPlayerControllerState,
+ onTogglePlay = {
+ autoHideController++
+ if (exoPlayer.isPlaying) {
+ exoPlayer.pause()
+ } else {
+ if (exoPlayer.playbackState == Player.STATE_ENDED) {
+ exoPlayer.seekTo(0)
+ } else {
+ exoPlayer.play()
+ }
+ }
+ },
+ onSeekChange = {
+ autoHideController++
+ if (exoPlayer.isPlaying.not()) {
+ exoPlayer.play()
+ }
+ exoPlayer.seekTo(it.toLong())
+ },
+ onToggleMute = {
+ autoHideController++
+ exoPlayer.volume = if (exoPlayer.volume == 1f) 0f else 1f
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .align(Alignment.BottomCenter)
+ .padding(bottom = bottomPaddingInPixels.toDp()),
+ )
+ }
+
+ OnLifecycleEvent { _, event ->
+ when (event) {
+ Lifecycle.Event.ON_CREATE -> exoPlayer.addListener(playerListener)
+ Lifecycle.Event.ON_RESUME -> exoPlayer.prepare()
+ Lifecycle.Event.ON_PAUSE -> exoPlayer.pause()
+ Lifecycle.Event.ON_DESTROY -> {
+ exoPlayer.release()
+ exoPlayer.removeListener(playerListener)
+ }
+ else -> Unit
+ }
+ }
+}
+
+@PreviewsDayNight
+@Composable
+internal fun MediaVideoViewPreview() = ElementPreview {
+ MediaVideoView(
+ modifier = Modifier.fillMaxSize(),
+ bottomPaddingInPixels = 0,
+ localMediaViewState = rememberLocalMediaViewState(),
+ localMedia = null,
+ )
+}
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/util/FileExtensionExtractorWithValidation.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/util/FileExtensionExtractorWithValidation.kt
new file mode 100644
index 0000000000..026be26b2e
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/util/FileExtensionExtractorWithValidation.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023, 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.util
+
+import android.webkit.MimeTypeMap
+import com.squareup.anvil.annotations.ContributesBinding
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractor
+import javax.inject.Inject
+
+@ContributesBinding(AppScope::class)
+class FileExtensionExtractorWithValidation @Inject constructor() : FileExtensionExtractor {
+ override fun extractFromName(name: String): String {
+ val fileExtension = name.substringAfterLast('.', "")
+ // Makes sure the extension is known by the system, otherwise default to binary extension.
+ return if (MimeTypeMap.getSingleton().hasExtension(fileExtension)) {
+ fileExtension
+ } else {
+ "bin"
+ }
+ }
+}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerEvents.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt
similarity index 87%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerEvents.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt
index f72becb58f..ac2714584c 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerEvents.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.viewer
+package io.element.android.libraries.mediaviewer.impl.viewer
sealed interface MediaViewerEvents {
data object SaveOnDisk : MediaViewerEvents
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerNode.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt
similarity index 69%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerNode.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt
index 7d173f5291..83c7c1aca7 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerNode.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt
@@ -5,22 +5,21 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.viewer
+package io.element.android.libraries.mediaviewer.impl.viewer
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
+import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.compound.theme.ForcedDarkElementTheme
-import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.RoomScope
-import io.element.android.libraries.matrix.api.media.MediaSource
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
@ContributesNode(RoomScope::class)
open class MediaViewerNode @AssistedInject constructor(
@@ -28,15 +27,13 @@ open class MediaViewerNode @AssistedInject constructor(
@Assisted plugins: List,
presenterFactory: MediaViewerPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
- data class Inputs(
- val mediaInfo: MediaInfo,
- val mediaSource: MediaSource,
- val thumbnailSource: MediaSource?,
- val canDownload: Boolean,
- val canShare: Boolean,
- ) : NodeInputs
+ private val inputs = inputs()
- private val inputs: Inputs = inputs()
+ private fun onDone() {
+ plugins().forEach {
+ it.onDone()
+ }
+ }
private val presenter = presenterFactory.create(inputs)
@@ -47,7 +44,7 @@ open class MediaViewerNode @AssistedInject constructor(
MediaViewerView(
state = state,
modifier = modifier,
- onBackClick = this::navigateUp
+ onBackClick = ::onDone
)
}
}
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt
similarity index 94%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerPresenter.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt
index 3cef900040..068fb02b0f 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerPresenter.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.viewer
+package io.element.android.libraries.mediaviewer.impl.viewer
import android.content.ActivityNotFoundException
import androidx.compose.runtime.Composable
@@ -27,16 +27,17 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaFile
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.LocalMediaActions
import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import io.element.android.libraries.androidutils.R as UtilsR
class MediaViewerPresenter @AssistedInject constructor(
- @Assisted private val inputs: MediaViewerNode.Inputs,
+ @Assisted private val inputs: MediaViewerEntryPoint.Params,
private val localMediaFactory: LocalMediaFactory,
private val mediaLoader: MatrixMediaLoader,
private val localMediaActions: LocalMediaActions,
@@ -44,7 +45,7 @@ class MediaViewerPresenter @AssistedInject constructor(
) : Presenter {
@AssistedFactory
interface Factory {
- fun create(inputs: MediaViewerNode.Inputs): MediaViewerPresenter
+ fun create(inputs: MediaViewerEntryPoint.Params): MediaViewerPresenter
}
@Composable
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt
similarity index 85%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerState.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt
index 3dd9f1b372..94d6653241 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerState.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt
@@ -5,13 +5,13 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.viewer
+package io.element.android.libraries.mediaviewer.impl.viewer
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.media.MediaSource
+import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
data class MediaViewerState(
val mediaInfo: MediaInfo,
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt
new file mode 100644
index 0000000000..6c7a9fb704
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2023, 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.impl.viewer
+
+import android.net.Uri
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.aPdfMediaInfo
+import io.element.android.libraries.mediaviewer.api.aVideoMediaInfo
+import io.element.android.libraries.mediaviewer.api.anApkMediaInfo
+import io.element.android.libraries.mediaviewer.api.anAudioMediaInfo
+import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
+import io.element.android.libraries.mediaviewer.api.local.LocalMedia
+
+open class MediaViewerStateProvider : PreviewParameterProvider {
+ override val values: Sequence
+ get() = sequenceOf(
+ aMediaViewerState(),
+ aMediaViewerState(AsyncData.Loading()),
+ aMediaViewerState(AsyncData.Failure(IllegalStateException("error"))),
+ anImageMediaInfo(
+ senderName = "Sally Sanderson",
+ dateSent = "21 NOV, 2024",
+ caption = "A caption",
+ ).let {
+ aMediaViewerState(
+ AsyncData.Success(
+ LocalMedia(Uri.EMPTY, it)
+ ),
+ it,
+ )
+ },
+ aVideoMediaInfo(
+ senderName = "Sally Sanderson",
+ dateSent = "21 NOV, 2024",
+ caption = "A caption",
+ ).let {
+ aMediaViewerState(
+ AsyncData.Success(
+ LocalMedia(Uri.EMPTY, it)
+ ),
+ it,
+ )
+ },
+ aPdfMediaInfo().let {
+ aMediaViewerState(
+ AsyncData.Success(
+ LocalMedia(Uri.EMPTY, it)
+ ),
+ it,
+ )
+ },
+ aMediaViewerState(
+ AsyncData.Loading(),
+ anApkMediaInfo(),
+ ),
+ anApkMediaInfo().let {
+ aMediaViewerState(
+ AsyncData.Success(
+ LocalMedia(Uri.EMPTY, it)
+ ),
+ it,
+ )
+ },
+ aMediaViewerState(
+ AsyncData.Loading(),
+ anAudioMediaInfo(),
+ ),
+ anAudioMediaInfo().let {
+ aMediaViewerState(
+ AsyncData.Success(
+ LocalMedia(Uri.EMPTY, it)
+ ),
+ it,
+ )
+ },
+ anImageMediaInfo().let {
+ aMediaViewerState(
+ AsyncData.Success(
+ LocalMedia(Uri.EMPTY, it)
+ ),
+ it,
+ canDownload = false,
+ canShare = false,
+ )
+ },
+ )
+}
+
+fun aMediaViewerState(
+ downloadedMedia: AsyncData = AsyncData.Uninitialized,
+ mediaInfo: MediaInfo = anImageMediaInfo(),
+ canDownload: Boolean = true,
+ canShare: Boolean = true,
+ eventSink: (MediaViewerEvents) -> Unit = {},
+) = MediaViewerState(
+ mediaInfo = mediaInfo,
+ thumbnailSource = null,
+ downloadedMedia = downloadedMedia,
+ snackbarMessage = null,
+ canDownload = canDownload,
+ canShare = canShare,
+ eventSink = eventSink,
+)
diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt
similarity index 73%
rename from libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerView.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt
index 9f362c13fa..cdcc6f9fb2 100644
--- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerView.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt
@@ -7,18 +7,23 @@
@file:OptIn(ExperimentalMaterial3Api::class)
-package io.element.android.libraries.mediaviewer.api.viewer
+package io.element.android.libraries.mediaviewer.impl.viewer
+import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -27,6 +32,7 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
@@ -35,32 +41,37 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource
+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 coil.compose.AsyncImage
+import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
+import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold
+import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.ui.media.MediaRequestData
-import io.element.android.libraries.mediaviewer.api.R
+import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.LocalMediaView
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.local.PlayableState
-import io.element.android.libraries.mediaviewer.api.local.rememberLocalMediaViewState
+import io.element.android.libraries.mediaviewer.impl.R
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaView
+import io.element.android.libraries.mediaviewer.impl.local.PlayableState
+import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.delay
import me.saket.telephoto.flick.FlickToDismiss
@@ -79,6 +90,9 @@ fun MediaViewerView(
val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage)
var showOverlay by remember { mutableStateOf(true) }
+ val defaultBottomPaddingInPixels = if (LocalInspectionMode.current) 303 else 0
+ var bottomPaddingInPixels by remember { mutableIntStateOf(defaultBottomPaddingInPixels) }
+ BackHandler { onBackClick() }
Scaffold(
modifier,
containerColor = Color.Transparent,
@@ -86,6 +100,7 @@ fun MediaViewerView(
) {
MediaViewerPage(
showOverlay = showOverlay,
+ bottomPaddingInPixels = bottomPaddingInPixels,
state = state,
onDismiss = {
onBackClick()
@@ -95,14 +110,29 @@ fun MediaViewerView(
}
)
AnimatedVisibility(visible = showOverlay, enter = fadeIn(), exit = fadeOut()) {
- MediaViewerTopBar(
- actionsEnabled = state.downloadedMedia is AsyncData.Success,
- mimeType = state.mediaInfo.mimeType,
- onBackClick = onBackClick,
- canDownload = state.canDownload,
- canShare = state.canShare,
- eventSink = state.eventSink
- )
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .navigationBarsPadding()
+ ) {
+ MediaViewerTopBar(
+ actionsEnabled = state.downloadedMedia is AsyncData.Success,
+ senderName = state.mediaInfo.senderName,
+ dateSent = state.mediaInfo.dateSent,
+ onBackClick = onBackClick,
+ eventSink = state.eventSink
+ )
+ MediaViewerBottomBar(
+ modifier = Modifier.align(Alignment.BottomCenter),
+ actionsEnabled = state.downloadedMedia is AsyncData.Success,
+ canDownload = state.canDownload,
+ canShare = state.canShare,
+ mimeType = state.mediaInfo.mimeType,
+ caption = state.mediaInfo.caption,
+ onHeightChange = { bottomPaddingInPixels = it },
+ eventSink = state.eventSink
+ )
+ }
}
}
}
@@ -110,6 +140,7 @@ fun MediaViewerView(
@Composable
private fun MediaViewerPage(
showOverlay: Boolean,
+ bottomPaddingInPixels: Int,
state: MediaViewerState,
onDismiss: () -> Unit,
onShowOverlayChange: (Boolean) -> Unit,
@@ -166,6 +197,7 @@ private fun MediaViewerPage(
LocalMediaView(
modifier = Modifier.fillMaxSize(),
+ bottomPaddingInPixels = bottomPaddingInPixels,
localMediaViewState = localMediaViewState,
localMedia = state.downloadedMedia.dataOrNull(),
mediaInfo = state.mediaInfo,
@@ -244,23 +276,100 @@ private fun rememberShowProgress(downloadedMedia: AsyncData): Boolea
return showProgress
}
+@Suppress("UNUSED_PARAMETER")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun MediaViewerTopBar(
actionsEnabled: Boolean,
- canDownload: Boolean,
- canShare: Boolean,
- mimeType: String,
+ senderName: String?,
+ dateSent: String?,
onBackClick: () -> Unit,
eventSink: (MediaViewerEvents) -> Unit,
) {
TopAppBar(
- title = {},
+ title = {
+ if (senderName != null && dateSent != null) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(end = 48.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Text(
+ text = senderName,
+ style = ElementTheme.typography.fontBodyMdMedium,
+ color = ElementTheme.colors.textPrimary,
+ )
+ Text(
+ text = dateSent,
+ style = ElementTheme.typography.fontBodySmRegular,
+ color = ElementTheme.colors.textPrimary,
+ )
+ }
+ }
+ },
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent.copy(0.6f),
),
navigationIcon = { BackButton(onClick = onBackClick) },
actions = {
+ // TODO Add action to open infos.
+ }
+ )
+}
+
+@Composable
+private fun MediaViewerBottomBar(
+ actionsEnabled: Boolean,
+ canDownload: Boolean,
+ canShare: Boolean,
+ mimeType: String,
+ caption: String?,
+ onHeightChange: (Int) -> Unit,
+ eventSink: (MediaViewerEvents) -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .background(Color(0x99101317))
+ .onSizeChanged {
+ onHeightChange(it.height)
+ },
+ ) {
+ HorizontalDivider()
+ if (caption != null) {
+ Text(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp),
+ text = caption,
+ maxLines = 5,
+ overflow = TextOverflow.Ellipsis,
+ style = ElementTheme.typography.fontBodyLgRegular,
+ )
+ }
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(start = 8.dp, end = 8.dp, bottom = 8.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ if (canShare) {
+ IconButton(
+ enabled = actionsEnabled,
+ onClick = {
+ eventSink(MediaViewerEvents.Share)
+ },
+ modifier = Modifier.align(Alignment.CenterVertically)
+ ) {
+ Icon(
+ imageVector = CompoundIcons.ShareAndroid(),
+ contentDescription = stringResource(id = CommonStrings.action_share)
+ )
+ }
+ }
+ Spacer(modifier = Modifier.weight(1f))
IconButton(
enabled = actionsEnabled,
onClick = {
@@ -291,21 +400,8 @@ private fun MediaViewerTopBar(
)
}
}
- if (canShare) {
- IconButton(
- enabled = actionsEnabled,
- onClick = {
- eventSink(MediaViewerEvents.Share)
- },
- ) {
- Icon(
- imageVector = CompoundIcons.ShareAndroid(),
- contentDescription = stringResource(id = CommonStrings.action_share)
- )
- }
- }
}
- )
+ }
}
@Composable
diff --git a/libraries/mediaviewer/api/src/main/res/drawable/ic_apk_install.xml b/libraries/mediaviewer/impl/src/main/res/drawable/ic_apk_install.xml
similarity index 100%
rename from libraries/mediaviewer/api/src/main/res/drawable/ic_apk_install.xml
rename to libraries/mediaviewer/impl/src/main/res/drawable/ic_apk_install.xml
diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt
index eb78517a36..c341f6e751 100644
--- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt
@@ -11,10 +11,11 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.media.MediaFile
+import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.media.FakeMediaFile
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anImageMediaInfo
-import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorWithoutValidation
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
+import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@@ -25,7 +26,10 @@ class AndroidLocalMediaFactoryTest {
@Test
fun `test AndroidLocalMediaFactory`() {
val sut = createAndroidLocalMediaFactory()
- val result = sut.createFromMediaFile(aMediaFile(), anImageMediaInfo())
+ val result = sut.createFromMediaFile(aMediaFile(), anImageMediaInfo(
+ senderName = A_USER_NAME,
+ dateSent = "12:34",
+ ))
assertThat(result.uri.toString()).endsWith("aPath")
assertThat(result.info).isEqualTo(
MediaInfo(
@@ -34,6 +38,8 @@ class AndroidLocalMediaFactoryTest {
mimeType = MimeTypes.Jpeg,
formattedFileSize = "4MB",
fileExtension = "jpg",
+ senderName = A_USER_NAME,
+ dateSent = "12:34"
)
)
}
diff --git a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractorTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/util/FileExtensionExtractorWithValidationTest.kt
similarity index 70%
rename from libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractorTest.kt
rename to libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/util/FileExtensionExtractorWithValidationTest.kt
index a9ab18ce61..df16eb62e8 100644
--- a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractorTest.kt
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/util/FileExtensionExtractorWithValidationTest.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.util
+package io.element.android.libraries.mediaviewer.impl.util
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -13,7 +13,7 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
-class FileExtensionExtractorTest {
+class FileExtensionExtractorWithValidationTest {
@Test
fun `test FileExtensionExtractor with validation OK`() {
val sut = FileExtensionExtractorWithValidation()
@@ -27,11 +27,4 @@ class FileExtensionExtractorTest {
val sut = FileExtensionExtractorWithValidation()
assertThat(sut.extractFromName("test.bla")).isEqualTo("bin")
}
-
- @Test
- fun `test FileExtensionExtractor no validation`() {
- val sut = FileExtensionExtractorWithoutValidation()
- assertThat(sut.extractFromName("test.png")).isEqualTo("png")
- assertThat(sut.extractFromName("test.bla")).isEqualTo("bla")
- }
}
diff --git a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt
similarity index 94%
rename from libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt
rename to libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt
index a54ccf2cc2..cbe334216c 100644
--- a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/MediaViewerPresenterTest.kt
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt
@@ -7,7 +7,7 @@
@file:OptIn(ExperimentalCoroutinesApi::class)
-package io.element.android.libraries.mediaviewer
+package io.element.android.libraries.mediaviewer.impl.viewer
import android.net.Uri
import app.cash.molecule.RecompositionMode
@@ -18,10 +18,8 @@ import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader
import io.element.android.libraries.matrix.test.media.aMediaSource
-import io.element.android.libraries.mediaviewer.api.local.anApkMediaInfo
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerEvents
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerNode
-import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerPresenter
+import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
+import io.element.android.libraries.mediaviewer.api.anApkMediaInfo
import io.element.android.libraries.mediaviewer.test.FakeLocalMediaActions
import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory
import io.element.android.tests.testutils.WarmUpRule
@@ -144,7 +142,7 @@ class MediaViewerPresenterTest {
canDownload: Boolean = true,
): MediaViewerPresenter {
return MediaViewerPresenter(
- inputs = MediaViewerNode.Inputs(
+ inputs = MediaViewerEntryPoint.Params(
mediaInfo = TESTED_MEDIA_INFO,
mediaSource = aMediaSource(),
thumbnailSource = null,
diff --git a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt
similarity index 97%
rename from libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerViewTest.kt
rename to libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt
index ee5aef8e2e..acbfb57619 100644
--- a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/viewer/MediaViewerViewTest.kt
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt
@@ -5,7 +5,7 @@
* Please see LICENSE in the repository root for full details.
*/
-package io.element.android.libraries.mediaviewer.api.viewer
+package io.element.android.libraries.mediaviewer.impl.viewer
import android.net.Uri
import androidx.activity.ComponentActivity
@@ -18,8 +18,8 @@ import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeDown
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.anImageMediaInfo
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EventsRecorder
diff --git a/libraries/mediaviewer/test/build.gradle.kts b/libraries/mediaviewer/test/build.gradle.kts
index aa182faa98..47adf35975 100644
--- a/libraries/mediaviewer/test/build.gradle.kts
+++ b/libraries/mediaviewer/test/build.gradle.kts
@@ -18,4 +18,7 @@ dependencies {
implementation(projects.libraries.core)
implementation(projects.tests.testutils)
implementation(projects.libraries.matrix.api)
+
+ testImplementation(libs.test.junit)
+ testImplementation(libs.test.truth)
}
diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt
index b6437c212b..c8555e5bce 100644
--- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt
+++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt
@@ -9,7 +9,7 @@ package io.element.android.libraries.mediaviewer.test
import androidx.compose.runtime.Composable
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.LocalMediaActions
+import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions
import io.element.android.tests.testutils.simulateLongTask
class FakeLocalMediaActions : LocalMediaActions {
diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt
index 43474e24bb..a0f36c6f0f 100644
--- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt
+++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt
@@ -10,11 +10,11 @@ package io.element.android.libraries.mediaviewer.test
import android.net.Uri
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.media.MediaFile
+import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractor
-import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorWithoutValidation
+import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation
import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia
class FakeLocalMediaFactory(
@@ -36,7 +36,9 @@ class FakeLocalMediaFactory(
caption = null,
mimeType = mimeType ?: fallbackMimeType,
formattedFileSize = formattedFileSize ?: fallbackFileSize,
- fileExtension = fileExtensionExtractor.extractFromName(safeName)
+ fileExtension = fileExtensionExtractor.extractFromName(safeName),
+ senderName = null,
+ dateSent = null
)
return aLocalMedia(uri, mediaInfo)
}
diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/util/FileExtensionExtractorWithoutValidation.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/util/FileExtensionExtractorWithoutValidation.kt
new file mode 100644
index 0000000000..c252c216aa
--- /dev/null
+++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/util/FileExtensionExtractorWithoutValidation.kt
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.test.util
+
+import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractor
+
+class FileExtensionExtractorWithoutValidation : FileExtensionExtractor {
+ override fun extractFromName(name: String): String {
+ return name.substringAfterLast('.', "")
+ }
+}
diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/viewer/LocalMedia.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/viewer/LocalMedia.kt
index ea2953f69c..4f933b1c00 100644
--- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/viewer/LocalMedia.kt
+++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/viewer/LocalMedia.kt
@@ -8,9 +8,9 @@
package io.element.android.libraries.mediaviewer.test.viewer
import android.net.Uri
+import io.element.android.libraries.mediaviewer.api.MediaInfo
+import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
-import io.element.android.libraries.mediaviewer.api.local.MediaInfo
-import io.element.android.libraries.mediaviewer.api.local.anImageMediaInfo
fun aLocalMedia(
uri: Uri,
diff --git a/libraries/mediaviewer/test/src/test/kotlin/io/element/android/libraries/mediaviewer/test/util/FileExtensionExtractorWithoutValidationTest.kt b/libraries/mediaviewer/test/src/test/kotlin/io/element/android/libraries/mediaviewer/test/util/FileExtensionExtractorWithoutValidationTest.kt
new file mode 100644
index 0000000000..48a6fbac11
--- /dev/null
+++ b/libraries/mediaviewer/test/src/test/kotlin/io/element/android/libraries/mediaviewer/test/util/FileExtensionExtractorWithoutValidationTest.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.mediaviewer.test.util
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class FileExtensionExtractorWithoutValidationTest {
+ @Test
+ fun `extension should always be extracted even is invalid`() {
+ val sut = FileExtensionExtractorWithoutValidation()
+ assertThat(sut.extractFromName("test.png")).isEqualTo("png")
+ assertThat(sut.extractFromName("test.bla")).isEqualTo("bla")
+ }
+}
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt
index 559322eaae..6788410468 100755
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt
@@ -230,10 +230,8 @@ class DefaultNotificationCreator @Inject constructor(
.setSmallIcon(smallIcon)
.setColor(accentColor)
.apply {
- if (NotificationConfig.SUPPORT_JOIN_DECLINE_INVITE) {
- addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent))
- addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent))
- }
+ addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent))
+ addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent))
// Build the pending intent for when the notification is clicked
setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(inviteNotifiableEvent.sessionId, inviteNotifiableEvent.roomId))
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt
index ee3d392c1f..9b2cf64a7d 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt
@@ -11,12 +11,14 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
+import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.androidutils.uri.createIgnoredUri
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
import io.element.android.libraries.push.impl.notifications.NotificationBroadcastReceiver
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
+import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.toolbox.api.strings.StringProvider
import io.element.android.services.toolbox.api.systemclock.SystemClock
import javax.inject.Inject
@@ -27,8 +29,8 @@ class AcceptInvitationActionFactory @Inject constructor(
private val stringProvider: StringProvider,
private val clock: SystemClock,
) {
- // offer to type a quick accept button
- fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action {
+ fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action? {
+ if (!NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS) return null
val sessionId = inviteNotifiableEvent.sessionId.value
val roomId = inviteNotifiableEvent.roomId.value
val intent = Intent(context, NotificationBroadcastReceiver::class.java)
@@ -44,7 +46,7 @@ class AcceptInvitationActionFactory @Inject constructor(
)
return NotificationCompat.Action.Builder(
R.drawable.vector_notification_accept_invitation,
- stringProvider.getString(R.string.notification_invitation_action_join),
+ stringProvider.getString(CommonStrings.action_accept),
pendingIntent
).build()
}
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt
index b77e36cfc0..e6a2594bb8 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt
@@ -29,7 +29,7 @@ class MarkAsReadActionFactory @Inject constructor(
private val clock: SystemClock,
) {
fun create(roomInfo: RoomEventGroupInfo): NotificationCompat.Action? {
- if (!NotificationConfig.SUPPORT_MARK_AS_READ_ACTION) return null
+ if (!NotificationConfig.SHOW_MARK_AS_READ_ACTION) return null
val sessionId = roomInfo.sessionId.value
val roomId = roomInfo.roomId.value
val intent = Intent(context, NotificationBroadcastReceiver::class.java)
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt
index 3ada849026..bced0abd90 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt
@@ -34,7 +34,7 @@ class QuickReplyActionFactory @Inject constructor(
private val clock: SystemClock,
) {
fun create(roomInfo: RoomEventGroupInfo, threadId: ThreadId?): NotificationCompat.Action? {
- if (!NotificationConfig.SUPPORT_QUICK_REPLY_ACTION) return null
+ if (!NotificationConfig.SHOW_QUICK_REPLY_ACTION) return null
val sessionId = roomInfo.sessionId
val roomId = roomInfo.roomId
val replyPendingIntent = buildQuickReplyIntent(sessionId, roomId, threadId)
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt
index 309acce44c..d4eb28f141 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt
@@ -11,12 +11,14 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
+import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.androidutils.uri.createIgnoredUri
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
import io.element.android.libraries.push.impl.notifications.NotificationBroadcastReceiver
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
+import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.toolbox.api.strings.StringProvider
import io.element.android.services.toolbox.api.systemclock.SystemClock
import javax.inject.Inject
@@ -28,6 +30,7 @@ class RejectInvitationActionFactory @Inject constructor(
private val clock: SystemClock,
) {
fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action? {
+ if (!NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS) return null
val sessionId = inviteNotifiableEvent.sessionId.value
val roomId = inviteNotifiableEvent.roomId.value
val intent = Intent(context, NotificationBroadcastReceiver::class.java)
@@ -41,10 +44,9 @@ class RejectInvitationActionFactory @Inject constructor(
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
-
return NotificationCompat.Action.Builder(
R.drawable.vector_notification_reject_invitation,
- stringProvider.getString(R.string.notification_invitation_action_reject),
+ stringProvider.getString(CommonStrings.action_reject),
pendingIntent
).build()
}
diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml
index fc5edbf1d9..f16303f87c 100644
--- a/libraries/push/impl/src/main/res/values-de/translations.xml
+++ b/libraries/push/impl/src/main/res/values-de/translations.xml
@@ -23,6 +23,7 @@
- "%d Einladungen"
"Du wurdest zu einem Chat eingeladen"
+ "%1$s hat dich zum Chatten eingeladen"
"Hat Dich erwähnt: %1$s"
"Neue Nachrichten"
@@ -33,6 +34,7 @@
"Als gelesen markieren"
"Schnelle Antwort"
"Du wurdest eingeladen, den Raum zu betreten"
+ "%1$s hat dich eingeladen, dem Chatroom beizutreten"
"Ich"
"%1$s hat Dich erwähnt oder geantwortet"
"Du siehst dir die Benachrichtigung an! Klicke hier!"
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt
index d0255aa452..44846f8010 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt
@@ -11,12 +11,15 @@ import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import com.google.common.truth.Truth.assertThat
+import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_TIMESTAMP
import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.matrix.ui.media.AVATAR_THUMBNAIL_SIZE_IN_PIXEL
import io.element.android.libraries.matrix.ui.media.MediaRequestData
+import io.element.android.libraries.push.impl.notifications.factories.MARK_AS_READ_ACTION_TITLE
+import io.element.android.libraries.push.impl.notifications.factories.QUICK_REPLY_ACTION_TITLE
import io.element.android.libraries.push.impl.notifications.factories.createNotificationCreator
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
import io.element.android.libraries.push.test.notifications.FakeImageLoader
@@ -156,6 +159,13 @@ class DefaultRoomGroupMessageCreatorTest {
)
assertThat(result.number).isEqualTo(2)
assertThat(result.`when`).isEqualTo(A_TIMESTAMP + 10)
+ val actionTitles = result.actions?.map { it.title }
+ assertThat(actionTitles).isEqualTo(
+ listOfNotNull(
+ MARK_AS_READ_ACTION_TITLE.takeIf { NotificationConfig.SHOW_MARK_AS_READ_ACTION },
+ QUICK_REPLY_ACTION_TITLE.takeIf { NotificationConfig.SHOW_QUICK_REPLY_ACTION },
+ )
+ )
assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@@ -175,7 +185,12 @@ class DefaultRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null,
)
- assertThat(result.actions).isNull()
+ val actionTitles = result.actions?.map { it.title }
+ assertThat(actionTitles).isEqualTo(
+ listOfNotNull(
+ MARK_AS_READ_ACTION_TITLE.takeIf { NotificationConfig.SHOW_MARK_AS_READ_ACTION }
+ )
+ )
assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt
index 9e2f3c1038..9a25ad2a72 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt
@@ -13,6 +13,7 @@ import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.google.common.truth.Truth.assertThat
+import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_ID
@@ -151,6 +152,13 @@ class DefaultNotificationCreatorTest {
result.commonAssertions(
expectedCategory = null,
)
+ val actionTitles = result.actions?.map { it.title }
+ assertThat(actionTitles).isEqualTo(
+ listOfNotNull(
+ REJECT_INVITATION_ACTION_TITLE.takeIf { NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS },
+ ACCEPT_INVITATION_ACTION_TITLE.takeIf { NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS },
+ )
+ )
}
@Test
@@ -271,6 +279,11 @@ class DefaultNotificationCreatorTest {
}
}
+const val MARK_AS_READ_ACTION_TITLE = "MarkAsReadAction"
+const val QUICK_REPLY_ACTION_TITLE = "QuickReplyAction"
+const val ACCEPT_INVITATION_ACTION_TITLE = "AcceptInvitationAction"
+const val REJECT_INVITATION_ACTION_TITLE = "RejectInvitationAction"
+
fun createNotificationCreator(
context: Context = RuntimeEnvironment.getApplication(),
buildMeta: BuildMeta = aBuildMeta(),
@@ -291,26 +304,26 @@ fun createNotificationCreator(
markAsReadActionFactory = MarkAsReadActionFactory(
context = context,
actionIds = NotificationActionIds(buildMeta),
- stringProvider = FakeStringProvider("MarkAsReadActionFactory"),
+ stringProvider = FakeStringProvider(MARK_AS_READ_ACTION_TITLE),
clock = FakeSystemClock(),
),
quickReplyActionFactory = QuickReplyActionFactory(
context = context,
actionIds = NotificationActionIds(buildMeta),
- stringProvider = FakeStringProvider("QuickReplyActionFactory"),
+ stringProvider = FakeStringProvider(QUICK_REPLY_ACTION_TITLE),
clock = FakeSystemClock(),
),
bitmapLoader = bitmapLoader,
acceptInvitationActionFactory = AcceptInvitationActionFactory(
context = context,
actionIds = NotificationActionIds(buildMeta),
- stringProvider = FakeStringProvider("AcceptInvitationActionFactory"),
+ stringProvider = FakeStringProvider(ACCEPT_INVITATION_ACTION_TITLE),
clock = FakeSystemClock(),
),
rejectInvitationActionFactory = RejectInvitationActionFactory(
context = context,
actionIds = NotificationActionIds(buildMeta),
- stringProvider = FakeStringProvider("RejectInvitationActionFactory"),
+ stringProvider = FakeStringProvider(REJECT_INVITATION_ACTION_TITLE),
clock = FakeSystemClock(),
),
)
diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt
new file mode 100644
index 0000000000..832d95ef14
--- /dev/null
+++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.libraries.textcomposer
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
+import io.element.android.libraries.designsystem.components.BigIcon
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
+import io.element.android.libraries.designsystem.theme.components.OutlinedButton
+import io.element.android.libraries.ui.strings.CommonStrings
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun CaptionWarningBottomSheet(
+ onDismiss: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ ModalBottomSheet(
+ modifier = modifier,
+ onDismissRequest = onDismiss,
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ ) {
+ BigIcon(
+ style = BigIcon.Style.AlertSolid,
+ )
+ Text(
+ text = stringResource(CommonStrings.screen_media_upload_preview_caption_warning),
+ style = ElementTheme.typography.fontBodyMdRegular,
+ color = ElementTheme.colors.textPrimary,
+ textAlign = TextAlign.Center,
+ )
+ OutlinedButton(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 16.dp),
+ onClick = onDismiss,
+ text = stringResource(CommonStrings.action_ok),
+ )
+ }
+ }
+}
+
+@PreviewsDayNight
+@Composable
+internal fun CaptionWarningBottomSheetPreview() = ElementPreview {
+ CaptionWarningBottomSheet(
+ onDismiss = {},
+ )
+}
diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
index fe6034b8b6..274453533b 100644
--- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
+++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
@@ -10,8 +10,10 @@ package io.element.android.libraries.textcomposer
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
@@ -26,8 +28,10 @@ import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -36,11 +40,14 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
+import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.components.media.createFakeWaveform
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
+import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.utils.HideKeyboardWhenDisposed
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
@@ -66,6 +73,7 @@ import io.element.android.libraries.textcomposer.model.VoiceMessageRecorderEvent
import io.element.android.libraries.textcomposer.model.VoiceMessageState
import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown
import io.element.android.libraries.textcomposer.model.aTextEditorStateRich
+import io.element.android.libraries.textcomposer.model.showCaptionCompatibilityWarning
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.wysiwyg.compose.RichTextEditor
import io.element.android.wysiwyg.compose.RichTextEditorState
@@ -121,8 +129,8 @@ fun TextComposer(
}
val layoutModifier = modifier
- .fillMaxSize()
- .height(IntrinsicSize.Min)
+ .fillMaxSize()
+ .height(IntrinsicSize.Min)
val composerOptionsButton: @Composable () -> Unit = remember(composerMode) {
@Composable {
@@ -146,7 +154,7 @@ fun TextComposer(
val placeholder = if (composerMode.inThread) {
stringResource(id = CommonStrings.action_reply_in_thread)
- } else if (composerMode is MessageComposerMode.Attachment) {
+ } else if (composerMode is MessageComposerMode.Attachment || composerMode is MessageComposerMode.EditCaption) {
stringResource(id = R.string.rich_text_editor_composer_caption_placeholder)
} else {
stringResource(id = R.string.rich_text_editor_composer_placeholder)
@@ -182,7 +190,7 @@ fun TextComposer(
composerMode = composerMode,
onResetComposerMode = onResetComposerMode,
placeholder = placeholder,
- showPlaceholder = { state.state.text.value().isEmpty() },
+ showPlaceholder = state.state.text.value().isEmpty(),
subcomposing = subcomposing,
) {
MarkdownTextInput(
@@ -316,6 +324,7 @@ fun TextComposer(
}
}
}
+ HideKeyboardWhenDisposed()
}
@Composable
@@ -337,8 +346,8 @@ private fun StandardLayout(
if (voiceMessageState is VoiceMessageState.Preview || voiceMessageState is VoiceMessageState.Recording) {
Box(
modifier = Modifier
- .padding(bottom = 5.dp, top = 5.dp, end = 3.dp, start = 3.dp)
- .size(48.dp),
+ .padding(bottom = 5.dp, top = 5.dp, end = 3.dp, start = 3.dp)
+ .size(48.dp),
contentAlignment = Alignment.Center,
) {
voiceDeleteButton()
@@ -348,8 +357,8 @@ private fun StandardLayout(
}
Box(
modifier = Modifier
- .padding(bottom = 8.dp, top = 8.dp)
- .weight(1f)
+ .padding(bottom = 8.dp, top = 8.dp)
+ .weight(1f)
) {
voiceRecording()
}
@@ -362,16 +371,16 @@ private fun StandardLayout(
}
Box(
modifier = Modifier
- .padding(bottom = 8.dp, top = 8.dp)
- .weight(1f)
+ .padding(bottom = 8.dp, top = 8.dp)
+ .weight(1f)
) {
textInput()
}
}
Box(
- Modifier
- .padding(bottom = 5.dp, top = 5.dp, end = 6.dp, start = 6.dp)
- .size(48.dp),
+ Modifier
+ .padding(bottom = 5.dp, top = 5.dp, end = 6.dp, start = 6.dp)
+ .size(48.dp),
contentAlignment = Alignment.Center,
) {
endButton()
@@ -393,8 +402,8 @@ private fun TextFormattingLayout(
) {
Box(
modifier = Modifier
- .weight(1f)
- .padding(horizontal = 12.dp)
+ .weight(1f)
+ .padding(horizontal = 12.dp)
) {
textInput()
}
@@ -428,9 +437,9 @@ private fun TextInputBox(
composerMode: MessageComposerMode,
onResetComposerMode: () -> Unit,
placeholder: String,
- showPlaceholder: () -> Boolean,
+ showPlaceholder: Boolean,
subcomposing: Boolean,
- textInput: @Composable () -> Unit,
+ textInput: @Composable BoxScope.() -> Unit,
) {
val bgColor = ElementTheme.colors.bgSubtleSecondary
val borderColor = ElementTheme.colors.borderDisabled
@@ -438,11 +447,11 @@ private fun TextInputBox(
Column(
modifier = Modifier
- .clip(roundedCorners)
- .border(0.5.dp, borderColor, roundedCorners)
- .background(color = bgColor)
- .requiredHeightIn(min = 42.dp)
- .fillMaxSize(),
+ .clip(roundedCorners)
+ .border(0.5.dp, borderColor, roundedCorners)
+ .background(color = bgColor)
+ .requiredHeightIn(min = 42.dp)
+ .fillMaxSize(),
) {
if (composerMode is MessageComposerMode.Special) {
ComposerModeView(
@@ -453,15 +462,15 @@ private fun TextInputBox(
val defaultTypography = ElementTheme.typography.fontBodyLgRegular
Box(
modifier = Modifier
- .padding(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp)
- // Apply test tag only once, otherwise 2 nodes will have it (both the normal and subcomposing one) and tests will fail
- .then(if (!subcomposing) Modifier.testTag(TestTags.textEditor) else Modifier),
+ .padding(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp)
+ // Apply test tag only once, otherwise 2 nodes will have it (both the normal and subcomposing one) and tests will fail
+ .then(if (!subcomposing) Modifier.testTag(TestTags.textEditor) else Modifier),
contentAlignment = Alignment.CenterStart,
) {
// Placeholder
- if (showPlaceholder()) {
+ if (showPlaceholder) {
Text(
- placeholder,
+ text = placeholder,
style = defaultTypography.copy(
color = ElementTheme.colors.textSecondary,
),
@@ -471,6 +480,24 @@ private fun TextInputBox(
}
textInput()
+
+ if (showPlaceholder && composerMode.showCaptionCompatibilityWarning()) {
+ var showBottomSheet by remember { mutableStateOf(false) }
+ Icon(
+ modifier = Modifier
+ .clickable { showBottomSheet = true }
+ .padding(horizontal = 8.dp, vertical = 4.dp)
+ .align(Alignment.CenterEnd),
+ imageVector = CompoundIcons.InfoSolid(),
+ tint = ElementTheme.colors.iconCriticalPrimary,
+ contentDescription = null,
+ )
+ if (showBottomSheet) {
+ CaptionWarningBottomSheet(
+ onDismiss = { showBottomSheet = false },
+ )
+ }
+ }
}
}
}
@@ -492,7 +519,7 @@ private fun TextInput(
composerMode = composerMode,
onResetComposerMode = onResetComposerMode,
placeholder = placeholder,
- showPlaceholder = { state.messageHtml.isEmpty() },
+ showPlaceholder = state.messageHtml.isEmpty(),
subcomposing = subcomposing,
) {
RichTextEditor(
@@ -501,8 +528,8 @@ private fun TextInput(
// This prevents it gaining focus and mutating the state.
registerStateUpdates = !subcomposing,
modifier = Modifier
- .padding(top = 6.dp, bottom = 6.dp)
- .fillMaxWidth(),
+ .padding(top = 6.dp, bottom = 6.dp)
+ .fillMaxWidth(),
style = ElementRichTextEditorStyle.composerStyle(hasFocus = state.hasFocus),
resolveMentionDisplay = resolveMentionDisplay,
resolveRoomMentionDisplay = resolveRoomMentionDisplay,
@@ -602,13 +629,14 @@ internal fun TextComposerEditCaptionPreview() = ElementPreview {
internal fun TextComposerAddCaptionPreview() = ElementPreview {
PreviewColumn(
items = aTextEditorStateRichList()
- ) { _, textEditorState ->
+ ) { index, textEditorState ->
ATextComposer(
state = textEditorState,
voiceMessageState = VoiceMessageState.Idle,
composerMode = aMessageComposerModeEditCaption(
// No caption so that the UI will be in add caption mode
content = "",
+ showCompatibilityWarning = index == 0,
),
enableVoiceMessages = false,
)
@@ -657,7 +685,10 @@ internal fun TextComposerCaptionPreview() = ElementPreview {
ATextComposer(
state = textEditorState,
voiceMessageState = VoiceMessageState.Idle,
- composerMode = MessageComposerMode.Attachment(allowCaption = index < list.size),
+ composerMode = MessageComposerMode.Attachment(
+ allowCaption = index < list.size,
+ showCaptionCompatibilityWarning = index == 0,
+ ),
enableVoiceMessages = false,
)
}
@@ -762,9 +793,11 @@ fun aMessageComposerModeEdit(
fun aMessageComposerModeEditCaption(
eventOrTransactionId: EventOrTransactionId = EventId("$1234").toEventOrTransactionId(),
content: String,
+ showCompatibilityWarning: Boolean = false,
) = MessageComposerMode.EditCaption(
eventOrTransactionId = eventOrTransactionId,
- content = content
+ content = content,
+ showCaptionCompatibilityWarning = showCompatibilityWarning,
)
fun aMessageComposerModeReply(
diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt
index 4ef6cfc019..f698f7ffe9 100644
--- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt
+++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MessageComposerMode.kt
@@ -18,7 +18,10 @@ import io.element.android.libraries.matrix.ui.messages.reply.eventId
sealed interface MessageComposerMode {
data object Normal : MessageComposerMode
- data class Attachment(val allowCaption: Boolean) : MessageComposerMode
+ data class Attachment(
+ val allowCaption: Boolean,
+ val showCaptionCompatibilityWarning: Boolean,
+ ) : MessageComposerMode
sealed interface Special : MessageComposerMode
@@ -29,7 +32,8 @@ sealed interface MessageComposerMode {
data class EditCaption(
val eventOrTransactionId: EventOrTransactionId,
- val content: String
+ val content: String,
+ val showCaptionCompatibilityWarning: Boolean,
) : Special
data class Reply(
@@ -51,3 +55,11 @@ sealed interface MessageComposerMode {
replyToDetails.eventContent is MessageContent &&
(replyToDetails.eventContent as MessageContent).isThreaded
}
+
+fun MessageComposerMode.showCaptionCompatibilityWarning(): Boolean {
+ return when (this) {
+ is MessageComposerMode.Attachment -> showCaptionCompatibilityWarning
+ is MessageComposerMode.EditCaption -> showCaptionCompatibilityWarning && content.isEmpty()
+ else -> false
+ }
+}
diff --git a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml
index eb0a752053..53ea09cfa8 100644
--- a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml
+++ b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml
@@ -4,6 +4,7 @@
"Aufzählungsliste umschalten"
"Formatierungsoptionen schließen"
"Codeblock umschalten"
+ "Optionale Bildunterschrift…"
"Nachricht…"
"Einen Link erstellen"
"Link bearbeiten"
diff --git a/libraries/textcomposer/impl/src/main/res/values-et/translations.xml b/libraries/textcomposer/impl/src/main/res/values-et/translations.xml
index 1cb9d1a990..c1a8035e0e 100644
--- a/libraries/textcomposer/impl/src/main/res/values-et/translations.xml
+++ b/libraries/textcomposer/impl/src/main/res/values-et/translations.xml
@@ -4,7 +4,7 @@
"Lülita mummudega loend sisse/välja"
"Sulge vorminduse valikud"
"Lülita lähtekoodi lõik sisse/välja"
- "Pealkiri, kui soovid lisada…"
+ "Selgitus või nimi, kui soovid lisada…"
"Sõnum…"
"Lisa link"
"Muuda linki"
diff --git a/libraries/textcomposer/impl/src/main/res/values/localazy.xml b/libraries/textcomposer/impl/src/main/res/values/localazy.xml
index e7cbb5da9a..fcc763db30 100644
--- a/libraries/textcomposer/impl/src/main/res/values/localazy.xml
+++ b/libraries/textcomposer/impl/src/main/res/values/localazy.xml
@@ -4,7 +4,7 @@
"Toggle bullet list"
"Close formatting options"
"Toggle code block"
- "Optional caption…"
+ "Add a caption"
"Message…"
"Create a link"
"Edit link"
diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml
index b2a879cd82..826730030d 100644
--- a/libraries/ui-strings/src/main/res/values-de/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-de/translations.xml
@@ -32,6 +32,7 @@
"Sprachnachricht aufnehmen."
"Aufnahme beenden"
"Akzeptieren"
+ "Bildunterschrift hinzufügen"
"Zum Nachrichtenverlauf hinzufügen"
"Zurück"
"Anruf"
@@ -42,18 +43,24 @@
"Schließen"
"Verifizierung abschließen"
"Bestätigen"
+ "Passwort bestätigen"
"Weiter"
"Kopieren"
+ "Bildunterschrift kopieren"
"Link kopieren"
"Link zur Nachricht kopieren"
+ "Text kopieren"
"Erstellen"
"Raum erstellen"
+ "Deaktivieren"
+ "Benutzerkonto deaktivieren"
"Ablehnen"
"Umfrage löschen"
"Deaktivieren"
"Verwerfen"
"Erledigt"
"Bearbeiten"
+ "Bildunterschrift bearbeiten"
"Umfrage bearbeiten"
"Aktivieren"
"Umfrage beenden"
@@ -61,6 +68,7 @@
"Passwort vergessen?"
"Weiterleiten"
"Zurück"
+ "Ignorieren"
"Einladen"
"Personen einladen"
"Zu %1$s einladen"
@@ -87,6 +95,8 @@
"Reagieren"
"Ablehnen"
"Entfernen"
+ "Bildunterschrift entfernen"
+ "Nachricht löschen"
"Antworten"
"Im Thread antworten"
"Fehler melden"
@@ -101,6 +111,7 @@
"Nachricht senden"
"Teilen"
"Link teilen"
+ "Zeige"
"Erneut anmelden"
"Abmelden"
"Trotzdem abmelden"
@@ -118,6 +129,7 @@
"Ja"
"Über"
"Nutzungsrichtlinie"
+ "Hinzufügen einer Bildunterschrift"
"Erweiterte Einstellungen"
"Analysedaten"
"Erscheinungsbild"
@@ -126,17 +138,21 @@
"Sprechblasen"
"Aufruf gestartet"
"Chat-Backup"
+ "In die Zwischenablage kopiert"
"Copyright"
"Raum wird erstellt…"
"Hat den Raum verlassen"
"Dunkel"
"Dekodierungsfehler"
"Entwickleroptionen"
+ "Geräte-ID"
"Direktnachricht"
"Nicht mehr anzeigen"
"(bearbeitet)"
"Bearbeitung"
+ "Bearbeitung der Bildunterschrift"
"* %1$s %2$s"
+ "Verschlüsselung"
"Verschlüsselung aktiviert"
"PIN eingeben"
"Fehler"
@@ -150,6 +166,7 @@ Grund: %1$s."
"Datei"
"Datei wurde unter Downloads gespeichert"
"Nachricht weiterleiten"
+ "Häufig verwendet"
"GIF"
"Bild"
"Als Antwort auf %1$s"
@@ -230,20 +247,30 @@ Grund: %1$s."
"Thema"
"Worum geht es in diesem Raum?"
"Entschlüsselung nicht möglich"
+ "Von einem ungesicherten Gerät gesendet"
"Du hast kein Recht diese Nachricht zu lesen."
+ "Die verifizierte Identität des Senders hat sich geändert"
"Einladungen konnten nicht an einen oder mehrere Benutzer gesendet werden."
"Einladung(en) konnte(n) nicht gesendet werden"
"Entsperren"
"Stummschaltung aufheben"
+ "Anruf nicht unterstützt"
"Nicht unterstütztes Ereignis"
"Benutzername"
"Verifizierung abgebrochen"
"Verifizierung abgeschlossen"
+ "Verifizierung fehlgeschlagen"
+ "Verifiziert"
"Gerät verifizieren"
+ "Identität überprüfen"
"Video"
"Sprachnachricht"
"Warten…"
"Warte auf diese Nachricht"
+ "Sie"
+ "%1$s\'s Identität has sich offenbar geändert. %2$s"
+ "%1$s\'s %2$s Identität hat sich offenbar geändert. %3$s"
+ "(%1$s)"
"Bestätigung"
"Fehler"
"Erfolg"
@@ -272,7 +299,22 @@ Grund: %1$s."
"Hey, sprich mit mir auf %1$s: %2$s"
"%1$s Android"
"Schüttel heftig zum Melden von Fehlern"
+ "Ja, akzeptiere alle"
+ "Sind Sie sicher, dass Sie alle Beitrittsanfragen akzeptieren möchten?"
+ "Akzeptiere alle Anfragen"
+ "Alle akzeptieren"
+ "Ja, ablehnen und sperren"
+ "Sind Sie sicher, dass Sie %1$s ablehnen und sperren möchten ? Dieser Benutzer kann keinen erneuten Zugriff auf diesen Raum anfordern."
+ "Ablehnen und Zugriff verbieten"
+ "Ja, ablehnen"
+ "Sind Sie sicher, dass Sie die %1$s Anfrage, diesem Chatroom beizutreten, ablehnen möchten ?"
+ "Zugriff verweigern"
+ "Ablehnen und sperren"
+ "Falls jemand um Aufnahme in den Raum bittet, können Sie dessen Anfrage hier sehen."
+ "Keine ausstehende Beitrittsanfrage"
+ "Beitrittsanfragen"
"Medienauswahl fehlgeschlagen, bitte versuche es erneut."
+ "Bildunterschriften sind für Nutzer älterer Apps möglicherweise nicht sichtbar."
"Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut."
"Das Hochladen der Medien ist fehlgeschlagen. Bitte versuche es erneut."
"Drücke auf eine Nachricht und wähle “%1$s”, um sie hier einzufügen."
@@ -290,14 +332,26 @@ Grund: %1$s."
"Nachricht trotzdem senden"
"%1$s verwendet wenigstens ein nicht verifiziertes Gerät. Du kannst die Nachricht trotzdem verschicken, oder vorerst abbrechen und später erneut versuchen, nachdem %2$s alle Geräte verifiziert hat."
"Deine Nachricht wurde nicht gesendet, weil %1$s nicht alle Geräte verifiziert hat"
+ "Mindestens eines Ihrer Geräte ist nicht verifiziert worden. Sie können die Nachricht trotzdem senden, oder den Vorgang zunächst abbrechen und es später erneut versuchen, nachdem Sie alle Ihrer Geräte verifiziert haben."
+ "Ihre Nachricht wurde nicht geschickt, da Sie eines oder mehrere Ihrer Geräte nicht verifiziert haben."
"Fixierte Nachrichten"
+ "Beitrittsanfragen"
"Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut."
"Benutzerdetails konnten nicht abgerufen werden"
+
+ - "%1$s+ %2$d andere wollen diesem Chatroom beitreten"
+ - "%1$s+ %2$d andere wollen diesem Chatroom beitreten"
+
+ "Alles ansehen"
"%1$s von %2$s"
"%1$s fixierte Nachrichten"
"Nachricht wird geladen…"
"Alle anzeigen"
+ "Akzeptieren"
+ "%1$s möchte diesem Chatroom beitreten"
+ "Ansicht"
"Chat"
+ "Beitrittsanfrage gesendet"
"Standort teilen"
"Meinen Standort teilen"
"In Apple Maps öffnen"
@@ -306,6 +360,7 @@ Grund: %1$s."
"Diesen Standort teilen"
"Nachricht nicht gesendet, weil sich die verifizierte Identität von %1$s geändert hat."
"Nachricht wurde nicht gesendet, weil %1$s nicht alle Geräte verifiziert hat"
+ "Die Nachricht wurde nicht gesendet, weil Sie eines oder mehrere Ihrer Geräte nicht verifiziert haben."
"Standort"
"Version: %1$s (%2$s)"
"en"
diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml
index b24be97394..39b8bc5b9a 100644
--- a/libraries/ui-strings/src/main/res/values-el/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-el/translations.xml
@@ -46,8 +46,10 @@
"Επιβεβαίωση κωδικού πρόσβασης"
"Συνέχεια"
"Αντιγραφή"
+ "Αντιγραφή λεζάντας"
"Αντιγραφή συνδέσμου"
"Αντιγραφή συνδέσμου στο μήνυμα"
+ "Αντιγραφή κειμένου"
"Δημιουργία"
"Δημιούργησε ένα δωμάτιο"
"Απενεργοποίηση"
@@ -94,6 +96,7 @@
"Απόρριψη"
"Αφαίρεση"
"Αφαίρεση λεζάντας"
+ "Αφαίρεση μηνύματος"
"Απάντηση"
"Απάντηση στο θέμα"
"Αναφορά σφάλματος"
@@ -296,12 +299,22 @@
"Γεια, μίλα μου στην εφαρμογή %1$s :%2$s"
"%1$s Android"
"Κούνησε δυνατά τη συσκευή σου για να αναφέρεις κάποιο σφάλμα"
+ "Ναι, αποδοχή όλων"
+ "Σίγουρα θες να αποδεχτείς όλα τα αιτήματα συμμετοχής;"
+ "Αποδοχή όλων των αιτημάτων"
"Αποδοχή όλων"
+ "Ναι, απόρριψη και αποκλεισμός"
+ "Σίγουρα θες να απορρίψειε και να αποκλείσεις τον χρήστη %1$s; Αυτός ο χρήστης δεν θα μπορεί να ζητήσει πρόσβαση για να συμμετάσχει ξανά σε αυτό το δωμάτιο."
+ "Απόρριψη και αποκλεισμός πρόσβασης"
+ "Ναι, απόρριψη"
+ "Σίγουρα θες να απορρίψεις το αίτημα του χρήστη %1$s να συμμετάσχει στο δωμάτιο;"
+ "Απόρριψη πρόσβασης"
"Απόρριψη και αποκλεισμός"
"Όταν κάποιος θα ζητήσει να συμμετάσχει στο δωμάτιο, θα μπορείς να δεις το αίτημά του εδώ."
"Δεν υπάρχει εκκρεμές αίτημα συμμετοχής"
"Αιτήματα συμμετοχής"
"Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά."
+ "Οι λεζάντες ενδέχεται να μην είναι ορατές σε άτομα που χρησιμοποιούν παλαιότερες εφαρμογές."
"Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά."
"Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά."
"Πάτα σε ένα μήνυμα και επέλεξε «%1$s» για να συμπεριληφθεί εδώ."
diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml
index cd94147870..3871a58914 100644
--- a/libraries/ui-strings/src/main/res/values-et/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-et/translations.xml
@@ -46,8 +46,10 @@
"Kinnita otsust oma salasõnaga"
"Jätka"
"Kopeeri"
+ "Kopeeri selgitus"
"Kopeeri link"
"Kopeeri sõnumi link"
+ "Kopeeri tekst"
"Loo"
"Loo jututuba"
"Eemalda konto"
@@ -94,6 +96,7 @@
"Keeldu"
"Eemalda"
"Eemalda selgitus"
+ "Eemalda sõnum"
"Vasta"
"Vasta jutulõngas"
"Teata veast"
@@ -296,12 +299,22 @@ Põhjus: %1$s."
"Hei, suhtle minuga %1$s võrgus: %2$s"
"%1$s Android"
"Veast teatamiseks raputa nutiseadet ägedalt"
+ "Jah, võta kõik vastu"
+ "Kas sa oled kindel, et soovid kõik vastu liitumist soovinud võtta?"
+ "Võta kõik vastu"
"Nõustu kõigiga"
+ "Jah, keeldu liitumisest ning keela ligipääs"
+ "Kas sa oled kindel, et soovid kasutajale %1$s keelata ligipääsu siia jututuppa ning seada talle suhtluskeelu? Seetõttu ta ei saa ka enam hiljem liitumispalvet saata."
+ "Keeldu liitumisest ja keela ligipääs"
+ "Jah, keeldu"
+ "Kas sa oled kindel, et soovid kasutajale %1$s keelata ligipääsu siia jututuppa?"
+ "Keela ligipääs"
"Keeldu ja määra suhtluskeeld"
"Kui keegi soovib jututoaga liituda, siis need päringud on kuvatud siin."
"Pole ühtegi liitumispalvet"
"Liitumispalved"
"Meediafaili valimine ei õnnestunud. Palun proovi uuesti."
+ "Selgitused ja alapealkirjad ei pruugi olla nähtavad vanemate rakenduste kasutajatele."
"Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti."
"Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti."
"Siia lisamiseks vajuta sõnumil ja vali „%1$s“."
diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml
index e4092bf388..24bd75cf46 100644
--- a/libraries/ui-strings/src/main/res/values-fr/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml
@@ -32,6 +32,7 @@
"Enregistrer un message vocal."
"Arrêter l’enregistrement"
"Accepter"
+ "Ajouter une légende"
"Ajouter à la discussion"
"Retour"
"Appel"
@@ -45,8 +46,10 @@
"Confirmez le mot de passe"
"Continuer"
"Copier"
+ "Copier la légende"
"Copier le lien"
"Copier le lien vers le message"
+ "Copier le texte"
"Créer"
"Créer un salon"
"Désactiver"
@@ -57,6 +60,7 @@
"Annuler"
"Terminé"
"Modifier"
+ "Modifier la légende"
"Modifier le sondage"
"Activer"
"Terminer le sondage"
@@ -91,6 +95,8 @@
"Réagissez"
"Rejeter"
"Supprimer"
+ "Supprimer la légende"
+ "Supprimer le message"
"Répondre"
"Répondre dans le fil de discussion"
"Signaler un problème"
@@ -123,6 +129,7 @@
"Oui"
"À propos"
"Politique d’utilisation acceptable"
+ "Ajout d’une légende"
"Paramètres avancés"
"Statistiques d’utilisation"
"Apparence"
@@ -143,6 +150,7 @@
"Ne plus afficher"
"(modifié)"
"Édition"
+ "Modification de la légende"
"* %1$s %2$s"
"Chiffrement"
"Chiffrement activé"
@@ -246,6 +254,7 @@ Raison: %1$s."
"Impossible d’envoyer une ou plusieurs invitations"
"Déverrouillage"
"Retirer la sourdine"
+ "Appel non pris en charge"
"Événement non pris en charge"
"Nom d’utilisateur"
"Vérification annulée"
@@ -290,7 +299,22 @@ Raison: %1$s."
"Salut, parle-moi sur %1$s : %2$s"
"%1$s Android"
"Rageshake pour signaler un problème"
+ "Oui, tout accepter"
+ "Êtes-vous sûr de vouloir accepter toutes les demandes pour rejoindre le salon ?"
+ "Tout accepter"
+ "Tout accepter"
+ "Oui, rejeter et bannir"
+ "Êtes-vous sûr de vouloir rejeter la demande et bannir %1$s? Cet utilisateur ne pourra pas demander à nouveau à rejoindre ce salon."
+ "Refuser et interdire l’accès"
+ "Oui, refuser"
+ "Êtes-vous sûr de vouloir refuser la demande de %1$s à rejoindre le salon?"
+ "Refuser l’accès"
+ "Refuser et bannir"
+ "Lorsque quelqu’un demandera à rejoindre le salon, vous pourrez voir sa demande ici."
+ "Personne ne demande à rejoindre le salon"
+ "Demandes en attente"
"Échec de la sélection du média, veuillez réessayer."
+ "Les légendes peuvent ne pas être visibles pour les utilisateurs d’anciennes applications."
"Échec du traitement des médias à télécharger, veuillez réessayer."
"Échec du téléchargement du média, veuillez réessayer."
"Cliquez (clic long) sur un message et choisissez « %1$s » pour qu‘il apparaisse ici."
@@ -311,12 +335,21 @@ Raison: %1$s."
"Un ou plusieurs de vos appareils ne sont pas vérifiés. Vous pouvez quand même envoyer le message, ou vous pouvez annuler et réessayer plus tard après avoir vérifié tous vos appareils."
"Votre message n’a pas été envoyé car vous n’avez pas vérifié tous vos appareils"
"Messages épinglés"
+ "Demandes en attente"
"Échec du traitement des médias à télécharger, veuillez réessayer."
"Impossible de récupérer les détails de l’utilisateur"
+
+ - "%1$s et %2$d autre personne souhaitent rejoindre ce salon"
+ - "%1$s et %2$d autres personnes souhaitent rejoindre ce salon"
+
+ "Tout afficher"
"%1$s sur %2$s"
"%1$s Messages épinglés"
"Chargement du message…"
"Voir tout"
+ "Accepter"
+ "%1$s souhaite rejoindre ce salon"
+ "Voir"
"Discussion"
"Demande d’adhésion envoyée"
"Partage de position"
diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml
index 72c7295109..35e9388ae7 100644
--- a/libraries/ui-strings/src/main/res/values-ru/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml
@@ -48,8 +48,10 @@
"Подтвердите пароль"
"Продолжить"
"Копировать"
+ "Скопировать подпись"
"Скопировать ссылку"
"Скопировать ссылку в сообщение"
+ "Копировать текст"
"Создать"
"Создать комнату"
"Отключить"
@@ -96,6 +98,7 @@
"Отклонить"
"Удалить"
"Удалить подпись"
+ "Удалить сообщение"
"Ответить"
"Ответить в теме"
"Сообщить об ошибке"
@@ -300,12 +303,22 @@
"Привет, поговори со мной по %1$s: %2$s"
"%1$s Android"
"Встряхните устройство, чтобы сообщить об ошибке"
+ "Да, принять все"
+ "Вы действительно хотите принять все заявки на присоединение?"
+ "Принять все запросы"
"Принять всё"
+ "Да, отклонить и запретить"
+ "Вы уверен, что хочешь отклонить и запретить %1$s? Этот пользователь больше не сможет запросить доступ к этой комнате."
+ "Отклонить и запретить доступ"
+ "Да, отклонить"
+ "Вы уверены, что хотите отклонить %1$s запрос на присоединение к этой комнате?"
+ "Отклонить доступ"
"Отклонить и запретить"
"Вы сможете увидеть запрос, когда кто-то попросит присоединиться к комнате."
"Нет ожидающих запросов на присоединение"
"Запросы на присоединение"
"Не удалось выбрать носитель, попробуйте еще раз."
+ "Подпись может быть не видна пользователям старых приложений."
"Не удалось обработать медиафайл для загрузки, попробуйте еще раз."
"Не удалось загрузить медиафайлы, попробуйте еще раз."
"Нажмите на сообщение и выберите “%1$s”, чтобы добавить его сюда."
diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml
index f52b53564b..8ab9695844 100644
--- a/libraries/ui-strings/src/main/res/values/localazy.xml
+++ b/libraries/ui-strings/src/main/res/values/localazy.xml
@@ -46,8 +46,10 @@
"Confirm password"
"Continue"
"Copy"
+ "Copy caption"
"Copy link"
"Copy link to message"
+ "Copy text"
"Create"
"Create a room"
"Deactivate"
@@ -94,6 +96,7 @@
"Reject"
"Remove"
"Remove caption"
+ "Remove message"
"Reply"
"Reply in thread"
"Report bug"
@@ -297,6 +300,7 @@ Reason: %1$s."
"%1$s Android"
"Rageshake to report bug"
"Failed selecting media, please try again."
+ "Captions might not be visible to people using older apps."
"Failed processing media to upload, please try again."
"Failed uploading media, please try again."
"Press on a message and choose “%1$s” to include here."
@@ -347,4 +351,7 @@ Reason: %1$s."
"Version: %1$s (%2$s)"
"en"
"en"
+ "Historical messages are not available on this device"
+ "Unable to decrypt message"
+ "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."
diff --git a/plugins/src/main/kotlin/extension/KoverExtension.kt b/plugins/src/main/kotlin/extension/KoverExtension.kt
index ccc077b0a3..b690dd492c 100644
--- a/plugins/src/main/kotlin/extension/KoverExtension.kt
+++ b/plugins/src/main/kotlin/extension/KoverExtension.kt
@@ -98,6 +98,8 @@ fun Project.setupKover() {
"io.element.android.libraries.designsystem.theme.components.bottomsheet.*",
// Test presenters
"io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter",
+ // Konsist code to make test fails
+ "io.element.android.tests.konsist.failures",
)
annotatedBy(
"androidx.compose.ui.tooling.preview.Preview",
@@ -167,26 +169,20 @@ fun Project.setupKover() {
filters {
excludes.classes(
"*State$*", // Exclude inner classes
- "io.element.android.appnav.root.RootNavState*",
- "io.element.android.libraries.matrix.api.timeline.item.event.OtherState$*",
- "io.element.android.libraries.matrix.api.timeline.item.event.EventSendState$*",
- "io.element.android.libraries.matrix.api.room.RoomMembershipState*",
- "io.element.android.libraries.matrix.api.room.MatrixRoomMembersState*",
- "io.element.android.libraries.push.impl.notifications.NotificationState*",
- "io.element.android.features.messages.impl.media.local.pdf.PdfViewerState",
- "io.element.android.features.messages.impl.media.local.LocalMediaViewState",
- "io.element.android.features.location.impl.map.MapState*",
- "io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState*",
- "io.element.android.libraries.designsystem.swipe.SwipeableActionsState*",
- "io.element.android.features.messages.impl.timeline.components.ExpandableState*",
- "io.element.android.features.messages.impl.timeline.model.bubble.BubbleState*",
- "io.element.android.libraries.maplibre.compose.CameraPositionState*",
- "io.element.android.libraries.maplibre.compose.SaveableCameraPositionState",
- "io.element.android.libraries.maplibre.compose.SymbolState*",
+ "io.element.android.appnav.root.RootNavState",
"io.element.android.features.ftue.api.state.*",
"io.element.android.features.ftue.impl.welcome.state.*",
+ "io.element.android.features.messages.impl.timeline.model.bubble.BubbleState",
+ "io.element.android.libraries.designsystem.swipe.SwipeableActionsState",
"io.element.android.libraries.designsystem.theme.components.bottomsheet.CustomSheetState",
- "io.element.android.libraries.mediaviewer.api.local.pdf.PdfViewerState",
+ "io.element.android.libraries.maplibre.compose.CameraPositionState",
+ "io.element.android.libraries.maplibre.compose.SaveableCameraPositionState",
+ "io.element.android.libraries.maplibre.compose.SymbolState",
+ "io.element.android.libraries.matrix.api.room.RoomMembershipState",
+ "io.element.android.libraries.matrix.api.room.MatrixRoomMembersState",
+ "io.element.android.libraries.matrix.api.timeline.item.event.OtherState$*",
+ "io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState*",
+ "io.element.android.libraries.mediaviewer.impl.local.pdf.PdfViewerState",
"io.element.android.libraries.textcomposer.model.TextEditorState",
)
includes.classes("*State")
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png
index 2e33cce11b..00bec43e13 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a15fb67f825270cd99686b6ccc41ba96300cd66cd9037a142ca22ea0c97e34b8
-size 39325
+oid sha256:457363c25841925076aaad53d728e631427f699cfb7545b8e1abb94fb6a2e774
+size 36741
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png
index a72a126cda..e09d9d4951 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dd301613bba0388dda860f1b9bf17199242b4b2b100306204ce62aa8a8d18475
-size 49352
+oid sha256:baf2c57107cd2f639535fc6fdf5b9885224c0f839d78fdbc85e14398f7439cd2
+size 49576
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png
index 46b12584d8..ba26587c92 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8bdac3f5bab1b95d1ece1891d8f8eed5280189a4df245f7ed428659b070abfc1
-size 60977
+oid sha256:eba277a783d50012cf4a51ec93c4cf02394befc9c5d04edd27ac8113e9257539
+size 63564
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png
index 301811e23d..09b64115e1 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3e128c7c58e19420128773da3e7493d23b29318754f16701f15c62b881e0605f
-size 60682
+oid sha256:c1f26d21ba37d244fcc5adb5b7580856f8e1a7670fd2defcd4befa3e2d07b8b6
+size 63685
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png
index 10500ad830..81b004f86b 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4d3c949a4619265b60081283be9f27eecac606da28efe0802709b2737fee0de0
-size 60782
+oid sha256:52f75d9234a0eace30ec10cbdeda6314cea0634d0ccbd2b8f453ec184a35cd13
+size 63592
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png
index 5d46b370bd..5308d79c1e 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f437ac8ebbb8a07498cfdb79ae559d6c26ef0df7f69ceadf3517a2240df21adf
-size 60272
+oid sha256:6c28710d2afe583078a26c8b56c331a942c250cb599d4c00f9dc4cf04286c811
+size 63082
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png
index 324e5c0e7c..1f6bca734e 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a5b45f72a7fc93c57abf3d660fe90681e5dd4d97f6e85fb13930b778275314bc
-size 40243
+oid sha256:9b449faf40487c6f34253b0157ae14c3df6a8a782b2af18fcd2b6f80198fa7d2
+size 37688
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png
index fa87cb4580..ba57e7b40b 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ca979acec5b69c530dd7df8f096bb3ed0155e98adb175c3720c51bf8887101d3
-size 50133
+oid sha256:09596614dfe191f7eb046aff9d44642e6ecbbf3fbdcb89181bae75c16d6ba72d
+size 50492
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png
index 04379c41f0..08823300da 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b3d67f0c62fd3118b5e0dd973e0704ab59e728042103830f4bd3dde3a69ade59
-size 62037
+oid sha256:ae642483fc05fb50555e2fa5b83ac12d84a064c4b840a53a4ebf53d419f87242
+size 65036
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png
index 6cf5c6f142..3b9922cb36 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:63f49c49ed3c99866a9c383e5fa6ff944a936f2050001be4d5868fbb47b702b8
-size 62506
+oid sha256:28606cedfc76d8600f8e935a42c4e98dc13c0b1d1733856bc20d064f99a39c5b
+size 65826
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png
index 167b944d4a..837e2badf7 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:678468615a0df5c1ba8add0ec3046e6ce11ab13adf9439635569806ffd29614e
-size 62622
+oid sha256:3128a8b8ca419b6862d1e5a3e8713f4aefd6fccd494babf006ccbbe15391c956
+size 65747
diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png
index 121f527da6..7acd884662 100644
--- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png
+++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1e72f476868673ddceab4449eb1d64554ccb48be8dcc96f45e4fa3137a4345bd
-size 62077
+oid sha256:54396bda85421376b596d885a43f67a19b06e9d7980d01112b90849ae08568e1
+size 65181
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_10_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_10_de.png
new file mode 100644
index 0000000000..5cd0ea0b22
--- /dev/null
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_10_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:de336859078455943d159d4d5d7fe710ecbce95baff983c4b74fab67ba6c16df
+size 109581
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_11_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_11_de.png
new file mode 100644
index 0000000000..1f682b74ff
--- /dev/null
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_11_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:19de55a1492cdbb55219720334ac6f5432518462e5a19c4783a32828d7fac899
+size 110605
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_12_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_12_de.png
new file mode 100644
index 0000000000..afb6b33005
--- /dev/null
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_12_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:32c5e9a456ea8a2718e50eea5a90f719eff659ed9ada2ab2a9f8da23b2344644
+size 123199
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_4_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_4_de.png
index 1078ac8765..a0cee32c3d 100644
--- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_4_de.png
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d8ec5e94258a92dea64d381284eca656980065cf2b9d1da89a7ec0833c77e263
-size 109815
+oid sha256:45d925186a619b7fbe19211ddfc8c052a3571b53ea6fbc914d819473aed9328f
+size 112045
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png
index a0cee32c3d..623dada791 100644
--- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:45d925186a619b7fbe19211ddfc8c052a3571b53ea6fbc914d819473aed9328f
-size 112045
+oid sha256:2cbf98f8a0c6208379c64f62c2c49a858d67a60469f0001e496c248736a2e82f
+size 120862
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png
index 623dada791..73ad652a38 100644
--- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2cbf98f8a0c6208379c64f62c2c49a858d67a60469f0001e496c248736a2e82f
-size 120862
+oid sha256:e79835f689801de55e6c0b0db98b642d58e235d205f23e76c8eca383cbcfa1f4
+size 97392
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_7_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_7_de.png
index 73ad652a38..afba2b6c29 100644
--- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_7_de.png
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_7_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e79835f689801de55e6c0b0db98b642d58e235d205f23e76c8eca383cbcfa1f4
-size 97392
+oid sha256:fb15d62e0dd87f76ce8c9f8e2909c4f4a5711cfcae89a81cef2bab0468db5054
+size 101310
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png
index afba2b6c29..a3aaef1824 100644
--- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png
+++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_8_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fb15d62e0dd87f76ce8c9f8e2909c4f4a5711cfcae89a81cef2bab0468db5054
-size 101310
+oid sha256:5a975e41d142e75969ca6e4148c5a87acc57c3fc78c1a1bac65207b09ce3fe38
+size 113797
diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png
deleted file mode 100644
index a3aaef1824..0000000000
--- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5a975e41d142e75969ca6e4148c5a87acc57c3fc78c1a1bac65207b09ce3fe38
-size 113797
diff --git a/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png b/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png
index dc9aece926..641499630a 100644
--- a/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png
+++ b/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0d2fadedcac33e4dbc013c9f441ec80a5a60d39e84c3e5aacf9eba0e9f6813f9
-size 56582
+oid sha256:54767f370bf50ae7c8f6d0cc27943b2832777e69d97fce3a3fe87ba4a54144a7
+size 58506
diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png
index 5318fc864f..96b5954e8c 100644
--- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png
+++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f7e32f9afa7fcec67740bc0dc541ed9b37655d08e2d4a851d4195480e277616d
-size 77420
+oid sha256:53ff3da2a5496f8df3166ad21e8bf65a9d5d25e408ca7c45c11a65e1bc25b08a
+size 89302
diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png
new file mode 100644
index 0000000000..cd650136f5
--- /dev/null
+++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1dd9b479ba45c82fce5d0dc80088232675671200f05131f39588aff1941c1341
+size 88983
diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png
index a4cac0b1c3..d19b60e2bd 100644
--- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png
+++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e554b8fd9bb9b3ddf81518a875588fb852cff3f525ae4a7cd9841bf7adedf8f0
-size 61915
+oid sha256:253cc5c68847a4878f6e9e9d7136f5d3d56157b29987398cc89f85ab4327a866
+size 81565
diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png
index 87eb704a54..277f207da8 100644
--- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png
+++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:932587c9c20b08576a20c88b06a6a768193d1f0cc342bac332fc72b6dd32ef13
-size 54871
+oid sha256:6f66e99b3632618df51d43688d57ebe152ab91058f4db52e9f33060c0e6b638b
+size 69452
diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png
index 20262d3338..d8b4b32434 100644
--- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png
+++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1c366667637a46850c80a875736bf79830e1cdde717878bee3087453d484c3dd
-size 54105
+oid sha256:49db8bd9f23eb98ef0e378a5b8b727a59715410017e2ab05bbc6a81ffe206a40
+size 72010
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png
index a323107f35..b0bf21949f 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3863896937835bad93aec454ea1ac84c0256abecbde4609bc217724e7707a990
-size 35422
+oid sha256:85b0a307f751b991e16ec61e27222fb3a51808c1ea81869eb3513925c18977ee
+size 27513
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png
index 6f08fbcffe..10051a39ee 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f614c45833e18e8aba011073006793824485114488e30e32548303ca55574a97
-size 51406
+oid sha256:0ab5fd552ac94ea96da1403099877e171751d8b4521f425041407c59f3d659cd
+size 52022
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png
index f4afa40ee1..fff94dc871 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c12ba12dca338d5722efc87ff7150d555d825dc2793e3263adb490135d696345
-size 51517
+oid sha256:dc3877eccf0d9fb26445089ead8d8b69ef836929735ca15354be68549690e555
+size 52146
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png
index 72d8f27d8c..7f7a3a82b8 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:93e7012184ddeadda396c78b1c70b713e58e96994b69471c26c413f940d4a5aa
-size 43500
+oid sha256:906b08c68d09d8c5ca41f518928c92239eb90ab30153e827c37f9d0036daca87
+size 43970
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png
index 02de885c5f..6ff70baa53 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:23bc2e3eaba71cb846544eb97e89b823f2648c425ae6f00c4d5e1d5498c0e6e2
-size 46829
+oid sha256:aa19b5cd2d27493f0f93820d80649681fda843cc87dab6adf5db6437cc7c1d67
+size 48970
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png
index b2bc53e507..a63acd006b 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:06f1353e8cf554102e1c9f778b26c7e07be5a192369d14bc99248509939e4fb8
-size 44540
+oid sha256:cac29a125e8ea11e65d6fdbe1282c0525f12f8aeaf251fa11103ca6abbe79222
+size 46501
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png
index f5c2a7c189..ec2c3e8463 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9835505f8e7675e2a78b82643d6b90baf927501ef14c9f75d39f2a11862b2217
-size 44170
+oid sha256:93f885fa860add5822c93522ff3a85c241f236f514007c9e6be4151842c39848
+size 41845
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png
index 48b221c319..8fbc79fcf3 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8b4587204de12c826dba2920cf04fe58fd6ce5a2e7a8f235dfc658bc2a6b8504
-size 44787
+oid sha256:989f76fb00e26b75827c9e28887db83d27eaa955a26fde20cc4a900f17cba0d8
+size 46727
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png
index 36ce780480..b56d48d004 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1f7940891b92cb8900994c98c9fb5eef7b60569c58fc01c3b204c3ab74283553
-size 45228
+oid sha256:6eb5f6d73426f470d55b81dc83f2b3148c57bd358299775910c2a882ae1a1825
+size 42920
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png
index d95a850300..8d10d0b0fb 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bd5d1ce6dde457a01f0c21a75c37a4ab84f74b0b0c0a5b06c821db88af8e055b
-size 45513
+oid sha256:5995b1b0090fcc93144f5305a75b8071e9a77610b9e6d2f2f69a392832386921
+size 45944
diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png
index 5330d62e56..0fda154e00 100644
--- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png
+++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f7671d88bab4949a79cb1e3fb342f1a9bd398f507bd25a5d08c918e26b588837
-size 35071
+oid sha256:2a71b6ebe1727f31bd147963247ed16c25ba18379e8f98c3ca8ef6ba3c119f9b
+size 35606
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_0_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_0_de.png
new file mode 100644
index 0000000000..5fa9d54233
--- /dev/null
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:432e20dbee2b01faebb0699d11b83dc08f3995b23db622b2645ebdcec1b9cdbc
+size 398406
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_1_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_1_de.png
new file mode 100644
index 0000000000..157f8f6272
--- /dev/null
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_1_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:db1ad6cc1ca2d83fd389b11eaf7554d3790ed9710e5af524d7c3dfe73987b0c3
+size 19892
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_2_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_2_de.png
new file mode 100644
index 0000000000..4202f8ccbf
--- /dev/null
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_2_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cd72e9a88a9aa3dcd012657e218a372e2e0078f2748b62df107b0dc9ae56ec75
+size 22245
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_3_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_3_de.png
new file mode 100644
index 0000000000..d5f291ce6a
--- /dev/null
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_3_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13765804d661727d44f40f53d8865183f94651f16d30831ee9ab8b90fd9a4efe
+size 23251
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_4_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_4_de.png
index 5b9749175c..0bf11f0975 100644
--- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_4_de.png
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0fccf0cc79fa0ff883def2fbda49b9b8a4c6bb3c390c75f5ebd7b779c27cf666
-size 53529
+oid sha256:1f7a22a39cd00987efa645df5626eec5e405f08ca046c23d53ce7e506f1654e5
+size 54411
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png
index 5bdcd84027..732ac86d77 100644
--- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:60a9c944110da6fd27fd6a5da2ceff7142f78ece3e40f17e4a27f3b3f9119862
-size 79814
+oid sha256:b415770af2855daf5cc2a09a38ec955ed5c80f958575ff2f5ddfb053df7d7870
+size 54385
diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png
new file mode 100644
index 0000000000..f5f28f06a1
--- /dev/null
+++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsView_6_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ff9a1d9f654b9c2cc5e21ffca1c2e85014f9b0b190b534de0667bc49c05e328f
+size 80690
diff --git a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png
index c72cb0ec4e..5104d537f3 100644
--- a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png
+++ b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0466a368266f2958a54307b34dc6d1152c50cded092811268c062c9f86f896e8
-size 25597
+oid sha256:e76cc4015eb6703f77498a0165a77564cbf55e1ee02aeece616270ea95c89c6a
+size 25907
diff --git a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png
index 2281d36854..6e883fb155 100644
--- a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png
+++ b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c530c4887b65128e9aceaf9c46196204e0a049386fb796cacfa30ee83d99084c
-size 25593
+oid sha256:4c13c7b6350d991737ad44d985c4ab4f1335de3291ced946915a38375ca46f91
+size 25901
diff --git a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png
index 76e6073ca9..69b647a584 100644
--- a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png
+++ b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ac676b093eb1b1afd33a546e64af7bf9cd21f3d71c6b0d6593ae30ca8cb73b00
-size 65474
+oid sha256:398376e9149bd3fd8903b0dc8f8859b58421eb0f600f8cc1a1054f8a87ffea07
+size 65810
diff --git a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png
index c53a7a3757..e028ad0038 100644
--- a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png
+++ b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c9ffc962a14719e6a265e7d48ad2bad7fa0cd1fd8dd1ea15b973b3266cf1c466
-size 65609
+oid sha256:cfe7b3d99fefa3b64080589a02741a23381ce03ae751d94a2b1575e63d4b2355
+size 65868
diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png
new file mode 100644
index 0000000000..3caf8ac57f
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8ceb7481fba9bc16a2b5aa75915f71100a6136804383854cace129d54871492e
+size 13673
diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_de.png
new file mode 100644
index 0000000000..5e1081e563
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:221a1d06bb60843e032235b6d67afe5db60aff6f842d4b256fac03e54ad36119
+size 11073
diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_de.png
new file mode 100644
index 0000000000..beeff0d4cd
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0a7259349f4b813a21692d498734342a7f038ec437026b96c21599f9470b10c7
+size 56353
diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_de.png
new file mode 100644
index 0000000000..99d11a266f
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dec121edb0e8e1aebae588f7d618b191849d9ad17fcef07120f978e0322d6a46
+size 17522
diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_de.png
new file mode 100644
index 0000000000..beeff0d4cd
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0a7259349f4b813a21692d498734342a7f038ec437026b96c21599f9470b10c7
+size 56353
diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png
index be189bf864..c577e8c111 100644
--- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png
+++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a85c3167adc0f63911759c6671871cb47d1b8384e9ab2ed04fadb014637137ea
-size 32215
+oid sha256:32eeac69c1c30c1df6252b38eaed414f2b316fb08e914778e544481ae79ace7f
+size 38115
diff --git a/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_0_de.png
new file mode 100644
index 0000000000..727c365114
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9f6c85c85a632763d077912c3a1a42d4c0096ff11df6a21fbcb2cabf91626d1b
+size 64566
diff --git a/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_1_de.png
new file mode 100644
index 0000000000..beeff0d4cd
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_1_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0a7259349f4b813a21692d498734342a7f038ec437026b96c21599f9470b10c7
+size 56353
diff --git a/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_2_de.png
new file mode 100644
index 0000000000..9c7f261915
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_2_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:36f05e56560d77a49610d8945e6e71734ae34ffda72e794ec10af5aea0f4fdd3
+size 79861
diff --git a/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_3_de.png
new file mode 100644
index 0000000000..31329afbb5
--- /dev/null
+++ b/screenshots/de/features.messages.impl.timeline.protection_ProtectedView_Day_3_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:31e4b9cbd0dd59ec269b9965ac9ec202b6443aa2a2621f479ec90fda8c8032a1
+size 37360
diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_0_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_0_de.png
index d27448c6d0..7aea7b47a7 100644
--- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_0_de.png
+++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:352fb53b25f4406dd015b751a638b95b6f62c867c78b4f143460a41a49f931dd
-size 64158
+oid sha256:e8ce478fe32b1fb8479efb86f5305611e5f1237a98f12392acb1a79bfe43af55
+size 68549
diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_1_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_1_de.png
index 922c3cd9ff..55c94e44cf 100644
--- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_1_de.png
+++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c1b44b5f03ec9fc35d70b7ea99f6d80a634ae0b0e054c43b8bbf7edd1bac29de
-size 63928
+oid sha256:5fdd3f6aff2518164dd958d3f4b3ff014e2c4c5f6714525ee9fc15eec6df76cb
+size 68305
diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_2_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_2_de.png
index 5c5334c17a..735c5939a7 100644
--- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_2_de.png
+++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8b62f107635c081db2941d1d9eb17be8e2c1ed9a09ba5d87328e3c5cf188eb76
-size 34110
+oid sha256:77258323ec2889688d40e6ea6e43c31b8d433a129ac5429a4234cc112763fb33
+size 34125
diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_3_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_3_de.png
index 0fa887a89b..50010c6205 100644
--- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_3_de.png
+++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4035d14464ba0260626c8bb01f2381f521bdc051e4fae9531b48e748c10d7a20
-size 63965
+oid sha256:80413c20e81da286a97ff62630426bb0700fd48e7fdbf2d039a89c77485c8b36
+size 68356
diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_4_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_4_de.png
index ca163fb0c8..b908d63738 100644
--- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_4_de.png
+++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:45123998d710d83e7bf1094493b16c3210a70e34e406b12ce227bd7cc78b3d87
-size 64020
+oid sha256:9182d5dbaad926abfaf55d80a4af3aa7da6e45054ed2a02fdaefdea081b66506
+size 68344
diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png
index 1a33248017..f3a33c216f 100644
--- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png
+++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:11fa8c3567744e5e9c7020ebdb2b9a6fa45ea5e970db337850a30c12d5eab37b
-size 38148
+oid sha256:6352cd3ad10f0f5c85323915efc8549aa6e1a45a722b594a0ddf3a055a29c20e
+size 39255
diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png
index 1c0c289730..7993c9035e 100644
--- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png
+++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8d24fdf8a38152d2e7800fef245fa62af144281faba4a66e692f9b2ab2e5bb49
-size 37911
+oid sha256:479cb8fd5b10c836691b05901b28c2bb3fd1557c5c9404e42551a8707610270c
+size 39008
diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png
index 2cb1e4fd51..612dfdde6b 100644
--- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png
+++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:7e436f63c5c966f52ea636fb8ce8899f2ec41af253a5c2452929bdf35cf8b7fc
-size 39075
+oid sha256:ae6ec5516e850143f886d79cc8b3ea89aa892c7e2cd28bdd613adc605446db57
+size 40263
diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png
index a3f6171365..e456d7199f 100644
--- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png
+++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3f98728c171887bb999ae38f0ca90aaaa932303dce159aeb35328a6a6bde9ef8
-size 39098
+oid sha256:6ae4cf626f2119a24ccdb459c398277e7f3ed9f0af6449e3c31c192a770f1a53
+size 40266
diff --git a/screenshots/de/features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_de.png b/screenshots/de/features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_de.png
index b049d02dfa..ff762510cd 100644
--- a/screenshots/de/features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_de.png
+++ b/screenshots/de/features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9ef48f6780db9379564395e728a693fec3ebc10e67a5c8026ccd9b0f82b0eed6
-size 34976
+oid sha256:7b8dd8db1c8726821961ddad6cadb6f5b93e09de680a53a21a7f8eba05dc2b02
+size 35624
diff --git a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_32_de.png b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_32_de.png
new file mode 100644
index 0000000000..8c19f4b18e
--- /dev/null
+++ b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_32_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2b19b09aca863e75b0bfbc404274f6ce3a2349fdbf2bf0c20c9b6bacdac79f08
+size 12682
diff --git a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_33_de.png b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_33_de.png
new file mode 100644
index 0000000000..08644eb138
--- /dev/null
+++ b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_33_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9817f47746af25e3815f8038de109e13641c5ef1c8d18f55585dff1c796ee92a
+size 18023
diff --git a/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png b/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png
index 1e81f1545e..893603d460 100644
--- a/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png
+++ b/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d7870bb4121a26d26ef0d74a0bb0cff86b80d0d47d82777279963dfe1a73a6e3
-size 106085
+oid sha256:592260b54144926121cab51c04507d52d02b0b26a105d3628a0be7c786311ef1
+size 106443
diff --git a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png
index dd0e572ffd..d25e0de53a 100644
--- a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png
+++ b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9779f1715cad0e14921e3a3e6a9bd681e604f3d4eba74bc3184a9b0a558a0051
-size 38538
+oid sha256:0e49141bdd0efb68227de5957cbc973e10552e4596786d4687a64256aadc82a1
+size 44720
diff --git a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_de.png b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_de.png
index 4ee3c0861a..e1b8666a47 100644
--- a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_de.png
+++ b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4892294712b7550c0e7eb281bd167f57f7494cd150e310773ce128a927bfc7d0
-size 48197
+oid sha256:6ff26d8fad93fd5c6c0abb70911bae92974ab1977f46104cef3babee23519811
+size 54013
diff --git a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_de.png b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_de.png
index b4dbdff9fd..6c9464c6b9 100644
--- a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_de.png
+++ b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b49405296483544738d2976b2e11475693a7c6929a9e29fef29675ce9a4d1e7c
-size 48418
+oid sha256:527c0361bb776783a7b776e5a6ecd61c84868b26aa9fe0da96f665ef17674bfa
+size 54078
diff --git a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png
index 4bd059258f..fc90557bf5 100644
--- a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png
+++ b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8e2a91b44b95d1e3b496338d779748e2bed96f28b49579e7b830b4ae386fd2e8
-size 38458
+oid sha256:0b6722105b7d2db210a97873b6c52902ba1ea3ec5fb318e79d90f96b4b43deb6
+size 51377
diff --git a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png
index 53b9314e99..eb84ffe273 100644
--- a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png
+++ b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c638686810e9c13046d0d84bf77bae9bb2858c4a0c189d0d090a5dae74667093
-size 76313
+oid sha256:9a9cdc1a43c73d3d59a6f45110e78a81e525cb07e6d3d90241f702331545f854
+size 80738
diff --git a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png
index d226904f50..0e301fc455 100644
--- a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png
+++ b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ff9b1178dc700652e6528c26ccbb3a1f81e07bbbc745302831c43d59ed6aea13
-size 64732
+oid sha256:b1f1aacf324499608f888cf31360d5305d6f28b4dabd04b404e8299b9a094046
+size 64741
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png
index 690f086352..616ccc4581 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c323c13474785b3dc08400a7bd408d549c964db66012d09132094526f5de7e4d
-size 25252
+oid sha256:815b0cd937d4a1cdd3ea44134146396e60df37d8d44bc2a44a19f07d4f738757
+size 45163
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png
index 690f086352..616ccc4581 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c323c13474785b3dc08400a7bd408d549c964db66012d09132094526f5de7e4d
-size 25252
+oid sha256:815b0cd937d4a1cdd3ea44134146396e60df37d8d44bc2a44a19f07d4f738757
+size 45163
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png
index 1c65f225b8..b80d9bd4af 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b0a5ca246bc6a1c2ad9e983e025dd02b9f205ec09293e1e676ee88491e017e37
-size 48712
+oid sha256:f7ecfb9c5ba42edaf1123f7d4fd1dae9d036b51b9a992401ccaefe512abd26b6
+size 74574
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png
index dc14b8dcbd..8670a3339f 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:11c25fc7c638ce5ab76981752109fc39aec07f1c3f1a90786b37af98e54233ac
-size 48962
+oid sha256:953284ce01229f35b10299ed63200cbb3f43d85cc9a44508651f79696feb3883
+size 68248
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png
index 564282a844..f195be7076 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3e596d6454d6edb86d6ec9da01b96f6dd46798d062614da75d27e2a4b5e14f83
-size 40260
+oid sha256:eedcee266e42accc3958a5c09b5abdcc493321e6da5455ceac43649c9f468d5a
+size 58773
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png
index 77f522ed2f..7be694d95b 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:35c99f0390cfe7dd87cbdd8cd4f931f3fa8aa6d41db578e9c7398c86a23f64e0
-size 46810
+oid sha256:2592bf3e90874c10506b127d3054a7ced3de2acac17f2b03906d9dae1a33d4c4
+size 72494
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png
index 66ffba64e5..c4277961c1 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:acad340964847803a06f3d0ea38c93b706d1b2e35369c122ffe0a1e77ce177ba
-size 36929
+oid sha256:40151413a5adabdb8440a8cc1dcd9049171e07502529fbfb1390a46fc452aa84
+size 49058
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png
index 4e68672dc4..6563d138b1 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:eee8ee71e1fdbec8b0872fa2b1fd9dfc3094c808a5923e0f4bb21fe565472d50
-size 26310
+oid sha256:5519b95d8ef1f1e58e3a1f212440f382e18d34cd5400da3dbdda0cbb2c125cf7
+size 46489
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png
index d06959de0d..c5633cd09b 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:206b2f37f6efa2b25bfc84a5a8b0b110703d06197b87676c46faf0daca24d4e3
-size 26688
+oid sha256:b431982e400c16c24b8e97ab4bcc70c8c5af25f929a2f7ae2679c32483cb142d
+size 47347
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png
index 690f086352..616ccc4581 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c323c13474785b3dc08400a7bd408d549c964db66012d09132094526f5de7e4d
-size 25252
+oid sha256:815b0cd937d4a1cdd3ea44134146396e60df37d8d44bc2a44a19f07d4f738757
+size 45163
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png
index 86b5a69e6a..3ca86ce78c 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:aa0f1d7099c533d80c6420b6e74db32acd9421cdc662873b6d5201dddeacf63d
-size 27767
+oid sha256:f4594a9e98992a8bc6367cd3d5ce516e7077c700d433d4b332dd69ecd054c932
+size 38795
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png
index 945bc6b0f0..2fa1e1091e 100644
--- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png
+++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5e90577ef426511ba1e63bc179a6acc34cdff38b712e32c4c4b9ab4f98f86783
-size 26037
+oid sha256:7a1d3cd113712fb92a16e5dba4ca654332de17ba9b8bf358c2822ecc15ab4f78
+size 46111
diff --git a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_de.png b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_de.png
index 49c0d7f6e8..3ca90a2b94 100644
--- a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_de.png
+++ b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8a7ea8c219d7d75cad52646affe980ae477dfa33ca065eb10df1b2da5615de45
-size 27463
+oid sha256:2e2a87a2163523d4f9b4a59d19955b3ebdcc6660c14131a4b983e0bf62f846ad
+size 20851
diff --git a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_de.png b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_de.png
index 8d4f6596fd..69874f12d8 100644
--- a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_de.png
+++ b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cb944176e84eb2b4938d0afd508ef0878ac1b1c75cf13f24d7eca71407c0be89
-size 24280
+oid sha256:bdaead12b54724228ec5c3d0193f2e0d13037825bd224e0f06b36abb1360c189
+size 17051
diff --git a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_de.png b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_de.png
index 49c0d7f6e8..3ca90a2b94 100644
--- a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_de.png
+++ b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8a7ea8c219d7d75cad52646affe980ae477dfa33ca065eb10df1b2da5615de45
-size 27463
+oid sha256:2e2a87a2163523d4f9b4a59d19955b3ebdcc6660c14131a4b983e0bf62f846ad
+size 20851
diff --git a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_de.png b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_de.png
index 8d4f6596fd..69874f12d8 100644
--- a/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_de.png
+++ b/screenshots/de/features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cb944176e84eb2b4938d0afd508ef0878ac1b1c75cf13f24d7eca71407c0be89
-size 24280
+oid sha256:bdaead12b54724228ec5c3d0193f2e0d13037825bd224e0f06b36abb1360c189
+size 17051
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png
index 50fe34193c..d18129135b 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ec1ce0a2ee199839e7a29f9ec41cf10c0c922c1516ecc5bffa2ec24abd55f62b
-size 65037
+oid sha256:6851b1d71546d2cdbbb063d49fe4ae2fe72338b46c88b1f502838c4b19b9d1a8
+size 57420
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png
index 2fa70f2c09..e187405077 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c9274f47c16777317e8218ffe74f6e084dfc7a9112d5b46f2be7c480ef41af88
-size 61516
+oid sha256:247cba8f887e87a29e1302f19ba0980b5b475d7e424db345417753dd1789f414
+size 53937
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_de.png
index 1d60e19040..8f57553098 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:91c28ce4fd47b06d4a20070ec364ce7bcd5b53d6364903eded573f72e07c0f71
-size 65630
+oid sha256:80c9e88ccbc95fc4ba7cd14f4077b07922666c2227401d6029928b3d37108ca0
+size 67131
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_de.png
index 1d60e19040..8f57553098 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:91c28ce4fd47b06d4a20070ec364ce7bcd5b53d6364903eded573f72e07c0f71
-size 65630
+oid sha256:80c9e88ccbc95fc4ba7cd14f4077b07922666c2227401d6029928b3d37108ca0
+size 67131
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png
index 6be838cbca..c483727895 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:be88a4b4c469dee0cad669ec92370f1f76aaea79a899fd38bb3c7277cfc03a31
-size 69951
+oid sha256:2144e09a7a3859cd53048aa93ad4614cb56a2a9686923b9862c7a7fc80d7bad2
+size 62530
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png
index f5ff7322b0..80740d8790 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:78e49c4ae78ec14430b2397b5bdde5d26bc97bec3f4705fc69c605c8eaa1ade5
-size 66631
+oid sha256:eb00965758191b4dc08dfd6ff5cf82af4165cd1f1cad08e5da7aab9a16284d2f
+size 59171
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_2_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_2_de.png
index 1d60e19040..8f57553098 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_2_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:91c28ce4fd47b06d4a20070ec364ce7bcd5b53d6364903eded573f72e07c0f71
-size 65630
+oid sha256:80c9e88ccbc95fc4ba7cd14f4077b07922666c2227401d6029928b3d37108ca0
+size 67131
diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_3_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_3_de.png
index 1d60e19040..8f57553098 100644
--- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_3_de.png
+++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:91c28ce4fd47b06d4a20070ec364ce7bcd5b53d6364903eded573f72e07c0f71
-size 65630
+oid sha256:80c9e88ccbc95fc4ba7cd14f4077b07922666c2227401d6029928b3d37108ca0
+size 67131
diff --git a/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png b/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png
new file mode 100644
index 0000000000..97877dcb47
--- /dev/null
+++ b/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d3a07ae4167cf29cfe165d3acc04e64b0c614d81bc542d57ed1d7a3b68605342
+size 15442
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png
index ff0981041c..f13d333149 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4d5708cb60a8d4b7a0d1c5c4b1621bc320dc0af3865ed79f17d9fa61ddcdf679
-size 29727
+oid sha256:116f716ad3bc6b519afbc3f6fcd5b019ef61e2846f4c20d516c68bbdce819895
+size 34316
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png
index 89f37b3886..b4a0a02716 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cf667fb981046b9e99c3cb689d5f23292471805b45d6aeefbe76ca876a4cca19
-size 27791
+oid sha256:3df860d4a1953ea868def4b83337dcd46b1e5922a4705739408f36432afd860c
+size 31952
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png
index 2179c311ce..18409948e0 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8967f48f6c93e957e93c0106f677ad570fdd601f064eb00f42d02f0b51dd9279
-size 25090
+oid sha256:a7a0515afdd3cb84d9eb3fee0e893c9070bedfc3d17590fc4b443f22af5060f0
+size 25230
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png
index bb6d162b41..7b4f2fb729 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ebef17540507cfefef165c21e644b3406cfe6cdb149598858b75ef73557edb4e
-size 44649
+oid sha256:37636f644edacd051fc73229790a4d91738498e4b11b2a7a262a05c81910da84
+size 44648
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png
index 37e9366a7c..32495b65fe 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4da8f02c7ea4823fb6978066acb901d192be7be2edd449fbf8e56c2e0e960829
-size 38948
+oid sha256:e9cc06c97c578e5d55c619bf022c5e9594aa5f07591e8e48c0e9662feb49e739
+size 38946
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png
index fe0d92427b..ac1e1a2eaf 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e735d995e2300af280d5533ad4f31ab4dc0d71d58ef5a73f6c597d815691f0ef
-size 28501
+oid sha256:e9bcc4faf5570bf743811b7a187a480049e4c859e9c2e827734cf50e85a969d9
+size 31297
diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png
index 27cfccb226..ff87178f4d 100644
--- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png
+++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:042b2541dbc95ef5eb6db6d42da826493e458326ba5a576975263e3774b2c4bd
-size 30805
+oid sha256:f0bbb74d86ed26f103141dd43838f6840d514902371d6d379bd1401357a8d155
+size 35357
diff --git a/screenshots/de/features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_de.png b/screenshots/de/features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_de.png
new file mode 100644
index 0000000000..030bf361b0
--- /dev/null
+++ b/screenshots/de/features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c36389a6ce4e57de1dc537cf005d1c0479d65b992c51a73fece0af6f437b3c23
+size 14593
diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_0_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_0_de.png
new file mode 100644
index 0000000000..c7477e89ab
--- /dev/null
+++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:69d0b4dd3db9575aa4663f78763c215594858afbabc549657d14050212ee8d27
+size 50042
diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_1_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_1_de.png
index 11bcf52ef7..1d8bd2b803 100644
--- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_1_de.png
+++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b210b2c570b1128c5b4992997fb3a64122572357796d19c005003e0e814e71d3
-size 41725
+oid sha256:781c009e36cc392fc1fe22e27b6354993e7a9b9bc47e3e0db8b6186e5e0ab6c8
+size 51102
diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_5_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_5_de.png
index 3e68cea981..1c1b31a57e 100644
--- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_5_de.png
+++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_5_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:038ff5080cdae88761104d16cd4e8183c0a48baec559bffe85d0b0a86735a884
-size 22229
+oid sha256:e528f5dc047db23984a78359b4997a83c8bdfed49403906fe4322bf2736ac202
+size 23866
diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_6_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_6_de.png
index 1bf33aa875..d7e91ecc8c 100644
--- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_6_de.png
+++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_6_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3079fb1d9f25f6ca86a7c41e7df95a7c1593019e3f27594e004e9be874e67669
-size 24474
+oid sha256:c02bd36e06f22e03032829e6bc3a291bf8706fda27e5cbd56138c3cd036e14ea
+size 34833
diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_7_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_7_de.png
index 1bf33aa875..d7e91ecc8c 100644
--- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_7_de.png
+++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_7_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3079fb1d9f25f6ca86a7c41e7df95a7c1593019e3f27594e004e9be874e67669
-size 24474
+oid sha256:c02bd36e06f22e03032829e6bc3a291bf8706fda27e5cbd56138c3cd036e14ea
+size 34833
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_0_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_0_de.png
index cead576dbe..35af29059e 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_0_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b90e375bca17e97adc72bdfa95c2d6b98cbe056973ea97751cff3718897d4c51
-size 42541
+oid sha256:23de0727192bb64e3ba28a2cd77685b764279e15eb76d35b166c7d7b2d623b68
+size 45057
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_10_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_10_de.png
index c209bc84bc..d20c22a879 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_10_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_10_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:34496ff29326e8414625f75dff0f9cfe59cb7d926d32d98abc2c3033342858a9
-size 39538
+oid sha256:cf14c725efbcab351df2fd6b81478c44b0d1f708e8d4c272c54f5d8886ceb0ac
+size 41630
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_13_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_13_de.png
index c0db6b7b62..f4b8360543 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_13_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_13_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2d570026d4981c7cd450ee79d6035eb6f421b3a8ad811f89fb204299d6eb393f
-size 31462
+oid sha256:609cdca094e16bdfca58df4b2d5493bc55755afd3ffbb0dbd5687677f6526e8f
+size 40087
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_1_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_1_de.png
index 1ddaf40a98..432c5d369e 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_1_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_1_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fa0fe810e2cbffb69fd9cb46c3e3040869064458f5a9291bf5164fb0cb4ddcd0
-size 30215
+oid sha256:80d2cf2d1558993992d8304d0dc83a04dbed8e6a72653ecbf309819095c13a40
+size 35820
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_4_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_4_de.png
index 5ba09ada53..edb0cf10f3 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_4_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_4_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9b55f2cb6999543cdd3cdc4f2bba2cb8cb238b94acbd05f889f25da8b43a8580
-size 24580
+oid sha256:8c49b74e9b38e3534d1c1bf9c8652f61f09ec3a1c3995886992c0825e4d6b683
+size 34784
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_7_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_7_de.png
index cead576dbe..35af29059e 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_7_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_7_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b90e375bca17e97adc72bdfa95c2d6b98cbe056973ea97751cff3718897d4c51
-size 42541
+oid sha256:23de0727192bb64e3ba28a2cd77685b764279e15eb76d35b166c7d7b2d623b68
+size 45057
diff --git a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_8_de.png b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_8_de.png
index f760980179..9821002f34 100644
--- a/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_8_de.png
+++ b/screenshots/de/features.verifysession.impl.outgoing_VerifySelfSessionView_Day_8_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:54654071726bec5f34f8ec90c4a9a8f88381feaf3861354488ecb833f032fce9
-size 36414
+oid sha256:b9b3d509178d5cebf46d5c03705d6f6f31cace4b9ff8a6951c594a4b64de5943
+size 38994
diff --git a/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png
index 0024021381..eb9d617feb 100644
--- a/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png
+++ b/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:91b0c3b998281662308866cf48d832a9e5bed739c4df52faaf9955d4b9377222
-size 59662
+oid sha256:72d90402ff38639d384be74db19bc8ee5e8dfc15def5e24839c404809e74829c
+size 65689
diff --git a/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png
new file mode 100644
index 0000000000..16aabac42d
--- /dev/null
+++ b/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:70681c983dd8027ef21a7cf7f1ce21b2aa49608026a2f265d4ea2b452f394cc0
+size 57592
diff --git a/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png
index dee50d7f3d..aaf06e57ab 100644
--- a/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png
+++ b/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:29ea8960948fd36a82248eca077b3d54804a2c1603989b30c39def7019699666
-size 59055
+oid sha256:ed323016c3aa4c61d248f7f515c4008bea91b5ab07513f1ad85c448b28a8e071
+size 66415
diff --git a/screenshots/html/data.js b/screenshots/html/data.js
index 46c6676dbc..ca26a3463f 100644
--- a/screenshots/html/data.js
+++ b/screenshots/html/data.js
@@ -1,59 +1,59 @@
// Generated file, do not edit
export const screenshots = [
["en","en-dark","de",],
-["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20049,],
+["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20056,],
["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,],
-["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",20049,],
-["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",20049,],
-["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",20049,],
-["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",20049,],
-["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20049,],
-["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",0,],
-["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20049,],
-["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20049,],
-["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20049,],
+["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",20056,],
+["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",20056,],
+["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",20056,],
+["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",20056,],
+["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20056,],
+["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20059,],
+["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20056,],
+["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20056,],
+["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20056,],
["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,],
["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,],
["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,],
["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,],
["features.messages.impl.actionlist_ActionListViewContent_Day_0_en","features.messages.impl.actionlist_ActionListViewContent_Night_0_en",0,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20049,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20056,],
["features.messages.impl.actionlist_ActionListViewContent_Day_1_en","features.messages.impl.actionlist_ActionListViewContent_Night_1_en",0,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20049,],
-["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20049,],
-["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20049,],
-["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20049,],
-["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20049,],
-["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20049,],
-["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",20049,],
-["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",20049,],
-["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",20049,],
-["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",20049,],
-["features.preferences.impl.advanced_AdvancedSettingsView_Day_4_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_4_en",20049,],
-["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20049,],
-["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20049,],
-["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20049,],
-["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20049,],
-["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20049,],
-["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20049,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20056,],
+["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20056,],
+["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20056,],
+["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20056,],
+["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20056,],
+["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20056,],
+["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",20056,],
+["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",20056,],
+["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",20056,],
+["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",20056,],
+["features.preferences.impl.advanced_AdvancedSettingsView_Day_4_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_4_en",20056,],
+["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20056,],
+["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20056,],
+["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20056,],
+["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20056,],
+["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20056,],
+["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20056,],
["libraries.designsystem.components.async_AsyncActionView_Day_0_en","libraries.designsystem.components.async_AsyncActionView_Night_0_en",0,],
-["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20049,],
+["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20056,],
["libraries.designsystem.components.async_AsyncActionView_Day_2_en","libraries.designsystem.components.async_AsyncActionView_Night_2_en",0,],
-["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20049,],
+["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20056,],
["libraries.designsystem.components.async_AsyncActionView_Day_4_en","libraries.designsystem.components.async_AsyncActionView_Night_4_en",0,],
-["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20049,],
+["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20056,],
["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,],
["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,],
["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,],
-["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20049,],
+["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20056,],
["libraries.matrix.ui.components_AttachmentThumbnail_Day_0_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_0_en",0,],
["libraries.matrix.ui.components_AttachmentThumbnail_Day_1_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_1_en",0,],
["libraries.matrix.ui.components_AttachmentThumbnail_Day_2_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_2_en",0,],
@@ -63,13 +63,15 @@ export const screenshots = [
["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,],
["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,],
["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,],
-["features.messages.impl.attachments.preview_AttachmentsView_0_en","",0,],
-["features.messages.impl.attachments.preview_AttachmentsView_1_en","",0,],
-["features.messages.impl.attachments.preview_AttachmentsView_2_en","",0,],
-["features.messages.impl.attachments.preview_AttachmentsView_3_en","",0,],
-["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20049,],
-["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20049,],
-["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20049,],
+["features.messages.impl.attachments.preview_AttachmentsView_0_en","",20059,],
+["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20059,],
+["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20059,],
+["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20059,],
+["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20056,],
+["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20056,],
+["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20059,],
+["features.messages.impl.attachments.preview_AttachmentsView_7_en","",0,],
+["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20056,],
["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,],
["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,],
["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,],
@@ -152,13 +154,13 @@ export const screenshots = [
["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,],
["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,],
["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20049,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20049,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20049,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20049,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20049,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20049,],
-["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20049,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20056,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20056,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20056,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20056,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20056,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20056,],
+["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20056,],
["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,],
["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,],
["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,],
@@ -169,115 +171,115 @@ export const screenshots = [
["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,],
["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,],
["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,],
-["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",20049,],
-["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",20049,],
-["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",20049,],
-["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",20049,],
-["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",20049,],
+["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",20056,],
+["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",20056,],
+["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",20056,],
+["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",20056,],
+["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",20056,],
["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,],
["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,],
["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,],
["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,],
-["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20049,],
-["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20049,],
+["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20056,],
+["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20056,],
["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",0,],
["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,],
["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,],
["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,],
-["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20049,],
-["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20049,],
-["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20049,],
-["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",20049,],
+["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20056,],
+["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20056,],
+["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20056,],
+["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",20056,],
["features.login.impl.changeserver_ChangeServerView_Day_0_en","features.login.impl.changeserver_ChangeServerView_Night_0_en",0,],
-["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20049,],
-["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20049,],
+["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20056,],
+["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20056,],
["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,],
-["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20049,],
+["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20056,],
["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,],
["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,],
["libraries.designsystem.components_ClickableLinkText_Text_en","",0,],
["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,],
-["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20049,],
-["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20049,],
-["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20049,],
+["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20056,],
+["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20056,],
+["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20056,],
["libraries.textcomposer_ComposerModeView_Day_1_en","libraries.textcomposer_ComposerModeView_Night_1_en",0,],
["libraries.textcomposer_ComposerModeView_Day_2_en","libraries.textcomposer_ComposerModeView_Night_2_en",0,],
["libraries.textcomposer_ComposerModeView_Day_3_en","libraries.textcomposer_ComposerModeView_Night_3_en",0,],
["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,],
["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,],
-["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20049,],
-["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20049,],
+["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20056,],
+["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20056,],
["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,],
-["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20049,],
-["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20049,],
-["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20049,],
-["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20049,],
+["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20056,],
+["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20056,],
+["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20056,],
+["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20056,],
["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,],
["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,],
["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,],
-["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20049,],
-["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20049,],
-["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20049,],
-["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20049,],
-["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20049,],
-["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20049,],
-["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",20049,],
-["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",20049,],
-["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",20049,],
-["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",20049,],
-["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20049,],
-["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20049,],
+["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20056,],
+["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20056,],
+["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20056,],
+["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20056,],
+["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20056,],
+["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20056,],
+["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",20056,],
+["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",20056,],
+["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",20056,],
+["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",20056,],
+["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20056,],
+["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20056,],
["features.logout.impl.direct_DefaultDirectLogoutView_Day_0_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_0_en",0,],
-["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20049,],
-["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20049,],
-["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20049,],
+["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20056,],
+["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20056,],
+["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20056,],
["features.logout.impl.direct_DefaultDirectLogoutView_Day_4_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_4_en",0,],
-["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20049,],
-["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",20049,],
-["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",20049,],
+["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20056,],
+["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",20056,],
+["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",20056,],
["features.licenses.impl.details_DependenciesDetailsView_Day_0_en","features.licenses.impl.details_DependenciesDetailsView_Night_0_en",0,],
-["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20049,],
-["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20049,],
-["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20049,],
-["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20049,],
-["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20049,],
-["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20049,],
-["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",20049,],
+["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20056,],
+["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20056,],
+["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20056,],
+["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20056,],
+["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20056,],
+["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20056,],
+["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",20056,],
["libraries.designsystem.theme.components_DialogWithDestructiveButton_Dialog_with_destructive_button_Dialogs_en","",0,],
["libraries.designsystem.theme.components_DialogWithOnlyMessageAndOkButton_Dialog_with_only_message_and_ok_button_Dialogs_en","",0,],
["libraries.designsystem.theme.components_DialogWithThirdButton_Dialog_with_third_button_Dialogs_en","",0,],
@@ -289,12 +291,12 @@ export const screenshots = [
["libraries.designsystem.text_DpScale_1_0f__en","",0,],
["libraries.designsystem.text_DpScale_1_5f__en","",0,],
["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,],
-["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20049,],
-["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20049,],
-["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20049,],
-["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20049,],
-["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20049,],
-["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20049,],
+["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20056,],
+["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20056,],
+["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20056,],
+["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20056,],
+["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20056,],
+["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20056,],
["libraries.matrix.ui.components_EditableAvatarView_Day_0_en","libraries.matrix.ui.components_EditableAvatarView_Night_0_en",0,],
["libraries.matrix.ui.components_EditableAvatarView_Day_1_en","libraries.matrix.ui.components_EditableAvatarView_Night_1_en",0,],
["libraries.matrix.ui.components_EditableAvatarView_Day_2_en","libraries.matrix.ui.components_EditableAvatarView_Night_2_en",0,],
@@ -304,9 +306,9 @@ export const screenshots = [
["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,],
["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,],
["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,],
-["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20049,],
-["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20049,],
-["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20049,],
+["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20056,],
+["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20056,],
+["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20056,],
["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,],
["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,],
["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,],
@@ -321,15 +323,15 @@ export const screenshots = [
["libraries.designsystem.theme.components_FloatingActionButton_Floating_Action_Buttons_en","",0,],
["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,],
["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,],
-["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20049,],
-["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20049,],
-["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20049,],
+["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20056,],
+["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20056,],
+["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20056,],
["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,],
["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,],
["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,],
["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,],
-["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",20049,],
-["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20049,],
+["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",20056,],
+["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20056,],
["libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Night_0_en",0,],
["libraries.designsystem.components.button_GradientFloatingActionButton_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButton_Night_0_en",0,],
["features.messages.impl.timeline.components.group_GroupHeaderView_Day_0_en","features.messages.impl.timeline.components.group_GroupHeaderView_Night_0_en",0,],
@@ -351,52 +353,53 @@ export const screenshots = [
["libraries.designsystem.icons_IconsCompound_Day_5_en","libraries.designsystem.icons_IconsCompound_Night_5_en",0,],
["libraries.designsystem.icons_IconsOther_Day_0_en","libraries.designsystem.icons_IconsOther_Night_0_en",0,],
["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_0_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_0_en",0,],
-["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20049,],
-["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20049,],
+["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20056,],
+["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20056,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_11_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_11_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en",0,],
-["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20049,],
+["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20056,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en",0,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en",0,],
-["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20049,],
+["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20056,],
["libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en",0,],
-["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",0,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20049,],
-["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20049,],
+["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20059,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20056,],
+["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20056,],
["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,],
["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,],
-["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20049,],
+["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20056,],
["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,],
-["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,],
-["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",0,],
-["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20049,],
-["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20049,],
+["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20059,],
+["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20059,],
+["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20059,],
+["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20056,],
+["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",0,],
["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,],
["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,],
-["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",20049,],
-["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",20049,],
-["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",20049,],
-["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",20049,],
-["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",20049,],
-["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",20049,],
+["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",20056,],
+["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",20056,],
+["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",20056,],
+["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",20056,],
+["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",20056,],
+["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",20056,],
["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,],
["libraries.designsystem.theme.components_LinearProgressIndicator_Progress_Indicators_en","",0,],
["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,],
@@ -453,29 +456,29 @@ export const screenshots = [
["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,],
["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,],
["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,],
-["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20049,],
-["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20049,],
-["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20049,],
-["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20049,],
+["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20056,],
+["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20056,],
+["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20056,],
+["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20056,],
["appnav.loggedin_LoggedInView_Day_0_en","appnav.loggedin_LoggedInView_Night_0_en",0,],
-["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20049,],
-["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20049,],
-["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20049,],
-["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20049,],
-["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20049,],
-["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20049,],
-["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20049,],
-["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20049,],
-["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20049,],
-["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20049,],
-["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20049,],
-["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20049,],
-["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20049,],
-["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20049,],
-["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20049,],
-["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20049,],
+["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20056,],
+["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20056,],
+["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20056,],
+["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20056,],
+["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20056,],
+["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20056,],
+["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20056,],
+["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20056,],
+["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20056,],
+["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20056,],
+["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20056,],
+["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20056,],
+["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20056,],
+["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20056,],
+["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20056,],
+["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20056,],
["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,],
-["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20049,],
+["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20056,],
["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,],
["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,],
["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en",0,],
@@ -485,10 +488,12 @@ export const screenshots = [
["libraries.matrix.ui.components_MatrixUserHeader_Day_1_en","libraries.matrix.ui.components_MatrixUserHeader_Night_1_en",0,],
["libraries.matrix.ui.components_MatrixUserRow_Day_0_en","libraries.matrix.ui.components_MatrixUserRow_Night_0_en",0,],
["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,],
+["libraries.mediaviewer.api.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.api.player_MediaPlayerControllerView_Night_0_en",0,],
+["libraries.mediaviewer.api.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.api.player_MediaPlayerControllerView_Night_1_en",0,],
["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,],
["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,],
["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,],
-["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",20049,],
+["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",20056,],
["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,],
["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,],
["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,],
@@ -500,7 +505,7 @@ export const screenshots = [
["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,],
["libraries.designsystem.theme.components.previews_Menu_Menus_en","",0,],
["features.messages.impl.messagecomposer_MessageComposerViewVoice_Day_0_en","features.messages.impl.messagecomposer_MessageComposerViewVoice_Night_0_en",0,],
-["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20049,],
+["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20056,],
["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,],
["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,],
["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,],
@@ -517,7 +522,7 @@ export const screenshots = [
["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,],
["features.messages.impl.timeline.components_MessageEventBubble_Day_8_en","features.messages.impl.timeline.components_MessageEventBubble_Night_8_en",0,],
["features.messages.impl.timeline.components_MessageEventBubble_Day_9_en","features.messages.impl.timeline.components_MessageEventBubble_Night_9_en",0,],
-["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20049,],
+["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20056,],
["features.messages.impl.timeline.components_MessageStateEventContainer_Day_0_en","features.messages.impl.timeline.components_MessageStateEventContainer_Night_0_en",0,],
["features.messages.impl.timeline.components_MessagesReactionButtonAdd_Day_0_en","features.messages.impl.timeline.components_MessagesReactionButtonAdd_Night_0_en",0,],
["features.messages.impl.timeline.components_MessagesReactionButtonExtra_Day_0_en","features.messages.impl.timeline.components_MessagesReactionButtonExtra_Night_0_en",0,],
@@ -525,23 +530,23 @@ export const screenshots = [
["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,],
["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,],
["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,],
-["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20049,],
-["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20049,],
-["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20049,],
-["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20049,],
-["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20049,],
-["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20049,],
-["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20049,],
-["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20049,],
-["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20049,],
-["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20049,],
-["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20049,],
-["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20049,],
-["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20049,],
-["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20049,],
-["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20049,],
+["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20056,],
+["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20056,],
+["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20056,],
+["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20056,],
+["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20056,],
+["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20056,],
+["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20056,],
+["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20056,],
+["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20056,],
+["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20056,],
+["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20056,],
+["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20056,],
+["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20056,],
+["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20056,],
+["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20056,],
["features.migration.impl_MigrationView_Day_0_en","features.migration.impl_MigrationView_Night_0_en",0,],
-["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20049,],
+["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20056,],
["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,],
["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,],
["appicon.element_MonochromeIcon_en","",0,],
@@ -550,29 +555,29 @@ export const screenshots = [
["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple_selection_List_item_-_selection_in_trailing_content_List_items_en","",0,],
["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,],
["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,],
-["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20049,],
-["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20049,],
-["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20049,],
+["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20056,],
+["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20056,],
+["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20056,],
["libraries.oidc.impl.webview_OidcView_Day_0_en","libraries.oidc.impl.webview_OidcView_Night_0_en",0,],
["libraries.oidc.impl.webview_OidcView_Day_1_en","libraries.oidc.impl.webview_OidcView_Night_1_en",0,],
["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,],
-["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",20049,],
-["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",20049,],
-["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",20049,],
-["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",20049,],
-["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",20049,],
+["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",20056,],
+["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",20056,],
+["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",20056,],
+["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",20056,],
+["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",20056,],
["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,],
["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,],
["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,],
@@ -585,65 +590,65 @@ export const screenshots = [
["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,],
["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,],
["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,],
-["libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Night_0_en",20049,],
-["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",20049,],
-["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20049,],
-["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20049,],
-["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20049,],
-["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20049,],
+["libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Night_0_en",20056,],
+["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",20056,],
+["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20056,],
+["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20056,],
+["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20056,],
+["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20056,],
["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,],
["libraries.designsystem.components_PinIcon_Day_0_en","libraries.designsystem.components_PinIcon_Night_0_en",0,],
["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20049,],
-["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20049,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20056,],
+["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20056,],
["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en",0,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20049,],
-["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20049,],
-["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20049,],
-["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20049,],
-["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20049,],
-["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20049,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20056,],
+["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20056,],
+["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20056,],
+["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20056,],
+["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20056,],
+["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20056,],
["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,],
-["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20049,],
+["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20056,],
["features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Night_0_en",0,],
["features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Night_0_en",0,],
-["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20049,],
-["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20049,],
-["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20049,],
-["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20049,],
-["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20049,],
-["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20049,],
-["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20049,],
+["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20056,],
+["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20056,],
+["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20056,],
+["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20056,],
+["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20056,],
+["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20056,],
+["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20056,],
["features.poll.api.pollcontent_PollTitleView_Day_0_en","features.poll.api.pollcontent_PollTitleView_Night_0_en",0,],
["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,],
["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,],
@@ -660,197 +665,197 @@ export const screenshots = [
["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,],
["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,],
["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,],
-["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20049,],
-["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20049,],
-["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20049,],
-["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20049,],
+["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20056,],
+["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20056,],
+["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20056,],
+["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20056,],
["features.messages.impl.timeline.components.event_ProgressButton_Day_0_en","features.messages.impl.timeline.components.event_ProgressButton_Night_0_en",0,],
-["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20049,],
-["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20049,],
-["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",0,],
-["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",0,],
-["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",0,],
-["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",0,],
-["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20049,],
-["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20049,],
-["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20049,],
-["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20049,],
-["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20049,],
-["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20049,],
-["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20049,],
-["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20049,],
-["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20049,],
-["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20049,],
+["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20056,],
+["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20056,],
+["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20059,],
+["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20059,],
+["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20059,],
+["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20059,],
+["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20056,],
+["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20056,],
+["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20056,],
+["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20056,],
+["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20056,],
+["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20056,],
+["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20056,],
+["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20056,],
+["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20056,],
+["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20056,],
["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,],
-["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20049,],
-["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20049,],
+["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20056,],
+["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20056,],
["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,],
["features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Night_0_en",0,],
-["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20049,],
-["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20049,],
-["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20049,],
-["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20049,],
-["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20049,],
-["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20049,],
-["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20049,],
+["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20056,],
+["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20056,],
+["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20056,],
+["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20056,],
+["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20056,],
+["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20056,],
+["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20056,],
["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,],
["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,],
-["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20049,],
-["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20049,],
-["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20049,],
-["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20049,],
-["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20049,],
-["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20049,],
-["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20049,],
-["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20049,],
-["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20049,],
-["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20049,],
-["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20049,],
-["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20049,],
+["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20056,],
+["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20056,],
+["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20056,],
+["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20056,],
+["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20056,],
+["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20056,],
+["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20056,],
+["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20056,],
+["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20056,],
+["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20056,],
+["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20056,],
+["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20056,],
["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en",0,],
-["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20049,],
-["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20049,],
-["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20049,],
-["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",20049,],
-["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",20049,],
+["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20056,],
+["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20056,],
+["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20056,],
+["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",20056,],
+["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",20056,],
["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,],
["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,],
-["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20049,],
-["features.roomdetails.impl_RoomDetailsDark_0_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_10_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_11_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_12_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_13_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_1_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_2_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_3_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_4_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_5_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_6_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_7_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_8_en","",20049,],
-["features.roomdetails.impl_RoomDetailsDark_9_en","",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20049,],
-["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20049,],
-["features.roomdetails.impl_RoomDetails_0_en","",20049,],
-["features.roomdetails.impl_RoomDetails_10_en","",20049,],
-["features.roomdetails.impl_RoomDetails_11_en","",20049,],
-["features.roomdetails.impl_RoomDetails_12_en","",20049,],
-["features.roomdetails.impl_RoomDetails_13_en","",20049,],
-["features.roomdetails.impl_RoomDetails_1_en","",20049,],
-["features.roomdetails.impl_RoomDetails_2_en","",20049,],
-["features.roomdetails.impl_RoomDetails_3_en","",20049,],
-["features.roomdetails.impl_RoomDetails_4_en","",20049,],
-["features.roomdetails.impl_RoomDetails_5_en","",20049,],
-["features.roomdetails.impl_RoomDetails_6_en","",20049,],
-["features.roomdetails.impl_RoomDetails_7_en","",20049,],
-["features.roomdetails.impl_RoomDetails_8_en","",20049,],
-["features.roomdetails.impl_RoomDetails_9_en","",20049,],
-["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20049,],
-["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20049,],
-["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",20049,],
-["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",20049,],
-["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",20049,],
-["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",20049,],
+["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20056,],
+["features.roomdetails.impl_RoomDetailsDark_0_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_10_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_11_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_12_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_13_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_1_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_2_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_3_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_4_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_5_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_6_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_7_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_8_en","",20056,],
+["features.roomdetails.impl_RoomDetailsDark_9_en","",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20056,],
+["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20056,],
+["features.roomdetails.impl_RoomDetails_0_en","",20056,],
+["features.roomdetails.impl_RoomDetails_10_en","",20056,],
+["features.roomdetails.impl_RoomDetails_11_en","",20056,],
+["features.roomdetails.impl_RoomDetails_12_en","",20056,],
+["features.roomdetails.impl_RoomDetails_13_en","",20056,],
+["features.roomdetails.impl_RoomDetails_1_en","",20056,],
+["features.roomdetails.impl_RoomDetails_2_en","",20056,],
+["features.roomdetails.impl_RoomDetails_3_en","",20056,],
+["features.roomdetails.impl_RoomDetails_4_en","",20056,],
+["features.roomdetails.impl_RoomDetails_5_en","",20056,],
+["features.roomdetails.impl_RoomDetails_6_en","",20056,],
+["features.roomdetails.impl_RoomDetails_7_en","",20056,],
+["features.roomdetails.impl_RoomDetails_8_en","",20056,],
+["features.roomdetails.impl_RoomDetails_9_en","",20056,],
+["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20056,],
+["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20056,],
+["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",20056,],
+["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",20056,],
+["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",20056,],
+["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",20056,],
["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,],
-["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",20049,],
-["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",20049,],
-["features.roomlist.impl.components_RoomListContentView_Day_5_en","features.roomlist.impl.components_RoomListContentView_Night_5_en",20052,],
-["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",20049,],
-["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",20049,],
-["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",20049,],
-["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",20049,],
-["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",20049,],
+["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",20056,],
+["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",20056,],
+["features.roomlist.impl.components_RoomListContentView_Day_5_en","features.roomlist.impl.components_RoomListContentView_Night_5_en",20056,],
+["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",20056,],
+["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",20056,],
+["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",20056,],
+["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",20056,],
+["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",20056,],
["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,],
-["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",20049,],
-["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",20049,],
-["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",20049,],
-["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",20049,],
-["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",20049,],
-["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",20049,],
-["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",20049,],
-["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",20049,],
-["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",20049,],
-["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",20049,],
-["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",20049,],
+["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",20056,],
+["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",20056,],
+["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",20056,],
+["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",20056,],
+["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",20056,],
+["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",20056,],
+["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",20056,],
+["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",20056,],
+["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",20056,],
+["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",20056,],
+["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",20056,],
["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,],
["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",0,],
-["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20049,],
+["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20056,],
["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",20049,],
-["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",20049,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",20056,],
+["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",20056,],
["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",20049,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",20049,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",20049,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",20049,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",20049,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",20056,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",20056,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",20056,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",20056,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",20056,],
["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",0,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",20049,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",20049,],
-["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",20049,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",20056,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",20056,],
+["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",20056,],
["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20049,],
-["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20049,],
-["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20049,],
-["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20049,],
-["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20049,],
-["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20049,],
-["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20049,],
-["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20049,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20056,],
+["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20056,],
+["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20056,],
+["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20056,],
+["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20056,],
+["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20056,],
+["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20056,],
+["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20056,],
["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,],
@@ -873,12 +878,12 @@ export const screenshots = [
["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,],
-["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",20049,],
-["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",20049,],
-["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",20049,],
-["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",20049,],
-["features.roomlist.impl.components_RoomSummaryRow_Day_32_en","features.roomlist.impl.components_RoomSummaryRow_Night_32_en",0,],
-["features.roomlist.impl.components_RoomSummaryRow_Day_33_en","features.roomlist.impl.components_RoomSummaryRow_Night_33_en",0,],
+["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",20056,],
+["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",20056,],
+["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",20056,],
+["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",20056,],
+["features.roomlist.impl.components_RoomSummaryRow_Day_32_en","features.roomlist.impl.components_RoomSummaryRow_Night_32_en",20059,],
+["features.roomlist.impl.components_RoomSummaryRow_Day_33_en","features.roomlist.impl.components_RoomSummaryRow_Night_33_en",20059,],
["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,],
@@ -886,59 +891,59 @@ export const screenshots = [
["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,],
["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,],
-["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20049,],
-["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20049,],
-["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20049,],
+["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20056,],
+["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20056,],
+["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20056,],
["appicon.enterprise_RoundIcon_en","",0,],
["appicon.element_RoundIcon_en","",0,],
["libraries.designsystem.atomic.atoms_RoundedIconAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoundedIconAtom_Night_0_en",0,],
-["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20049,],
-["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20049,],
-["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20049,],
+["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20056,],
+["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20056,],
+["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20056,],
["libraries.designsystem.theme.components_SearchBarActiveNoneQuery_Search_views_en","",0,],
["libraries.designsystem.theme.components_SearchBarActiveWithContent_Search_views_en","",0,],
-["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20049,],
+["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20056,],
["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search_views_en","",0,],
["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search_views_en","",0,],
["libraries.designsystem.theme.components_SearchBarInactive_Search_views_en","",0,],
-["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",20049,],
-["features.createroom.impl.components_SearchSingleUserResultItem_en","",20049,],
-["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20049,],
-["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20049,],
-["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20049,],
-["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20049,],
-["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20049,],
-["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20049,],
-["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20049,],
-["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20049,],
-["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20049,],
-["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20049,],
+["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",20056,],
+["features.createroom.impl.components_SearchSingleUserResultItem_en","",20056,],
+["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20056,],
+["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20056,],
+["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20056,],
+["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20056,],
+["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20056,],
+["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20056,],
+["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20056,],
+["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20056,],
+["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20056,],
+["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20056,],
["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,],
["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,],
["libraries.matrix.ui.components_SelectedRoom_Day_2_en","libraries.matrix.ui.components_SelectedRoom_Night_2_en",0,],
@@ -946,11 +951,11 @@ export const screenshots = [
["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,],
["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,],
["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,],
-["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20049,],
-["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20049,],
-["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20049,],
-["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20049,],
-["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20049,],
+["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20056,],
+["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20056,],
+["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20056,],
+["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20056,],
+["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20056,],
["libraries.matrix.ui.messages.sender_SenderName_Day_0_en","libraries.matrix.ui.messages.sender_SenderName_Night_0_en",0,],
["libraries.matrix.ui.messages.sender_SenderName_Day_1_en","libraries.matrix.ui.messages.sender_SenderName_Night_1_en",0,],
["libraries.matrix.ui.messages.sender_SenderName_Day_2_en","libraries.matrix.ui.messages.sender_SenderName_Night_2_en",0,],
@@ -960,27 +965,27 @@ export const screenshots = [
["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,],
["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,],
["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,],
-["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",0,],
-["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20049,],
-["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20049,],
-["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20049,],
-["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20049,],
-["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20049,],
-["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20049,],
-["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20049,],
+["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20059,],
+["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20056,],
+["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20056,],
+["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20056,],
+["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20056,],
+["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20056,],
+["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20056,],
+["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20056,],
["features.share.impl_ShareView_Day_0_en","features.share.impl_ShareView_Night_0_en",0,],
["features.share.impl_ShareView_Day_1_en","features.share.impl_ShareView_Night_1_en",0,],
["features.share.impl_ShareView_Day_2_en","features.share.impl_ShareView_Night_2_en",0,],
-["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20049,],
-["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20049,],
-["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20049,],
+["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20056,],
+["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20056,],
+["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20056,],
["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,],
["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,],
["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single_selection_List_item_-_custom_formatter_List_items_en","",0,],
@@ -989,7 +994,7 @@ export const screenshots = [
["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single_selection_List_item_-_no_selection,_supporting_text_List_items_en","",0,],
["libraries.designsystem.components.list_SingleSelectionListItem_Single_selection_List_item_-_no_selection_List_items_en","",0,],
["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,],
-["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20049,],
+["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20056,],
["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,],
["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,],
["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,],
@@ -999,40 +1004,40 @@ export const screenshots = [
["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,],
["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,],
["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,],
-["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",20049,],
+["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",20056,],
["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,],
-["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20049,],
+["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20056,],
["libraries.designsystem.atomic.pages_SunsetPage_Day_0_en","libraries.designsystem.atomic.pages_SunsetPage_Night_0_en",0,],
["libraries.designsystem.components.button_SuperButton_Day_0_en","libraries.designsystem.components.button_SuperButton_Night_0_en",0,],
["libraries.designsystem.theme.components_Surface_en","",0,],
["libraries.designsystem.theme.components_Switch_Toggles_en","",0,],
-["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20049,],
+["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20056,],
["libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en","",0,],
["libraries.designsystem.theme.components_TextButtonLarge_Buttons_en","",0,],
["libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en","",0,],
["libraries.designsystem.theme.components_TextButtonMedium_Buttons_en","",0,],
["libraries.designsystem.theme.components_TextButtonSmall_Buttons_en","",0,],
-["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20052,],
-["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",0,],
-["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20052,],
-["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20049,],
-["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20049,],
-["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20049,],
-["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20049,],
-["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20049,],
-["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20049,],
-["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20049,],
+["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20059,],
+["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20056,],
+["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20056,],
+["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20056,],
["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,],
["libraries.designsystem.theme.components_TextDark_Text_en","",0,],
["libraries.designsystem.components.list_TextFieldListItemEmpty_Text_field_List_item_-_empty_List_items_en","",0,],
@@ -1042,14 +1047,14 @@ export const screenshots = [
["libraries.designsystem.theme.components_TextFieldsLight_TextFields_en","",0,],
["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,],
["libraries.designsystem.theme.components_TextLight_Text_en","",0,],
-["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20049,],
-["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20049,],
-["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20049,],
+["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20056,],
+["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20056,],
+["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20056,],
["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_0_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_0_en",0,],
["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_1_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_1_en",0,],
["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_2_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_2_en",0,],
-["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20049,],
-["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20049,],
+["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20056,],
+["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20056,],
["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,],
["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,],
["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,],
@@ -1058,14 +1063,14 @@ export const screenshots = [
["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en",0,],
-["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20056,],
["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_0_en",0,],
["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_1_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_1_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20049,],
+["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20059,],
+["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20059,],
+["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20056,],
["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowLongSenderName_en","",0,],
@@ -1073,17 +1078,17 @@ export const screenshots = [
["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,],
-["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20049,],
-["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20056,],
+["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20056,],
["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en",0,],
-["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20049,],
-["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20056,],
+["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20056,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_0_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_1_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_2_en",0,],
-["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20049,],
-["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20056,],
+["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20056,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,],
@@ -1092,40 +1097,40 @@ export const screenshots = [
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,],
-["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20056,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,],
-["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20056,],
["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,],
["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,],
-["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20049,],
+["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20056,],
["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en",0,],
-["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20049,],
-["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",0,],
+["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20056,],
+["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20059,],
["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_1_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_2_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_3_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemInformativeView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemInformativeView_Night_0_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",0,],
+["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20059,],
["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20049,],
-["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20049,],
+["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20056,],
+["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20056,],
["features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Night_0_en",0,],
-["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20049,],
-["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20049,],
+["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20056,],
+["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20056,],
["features.messages.impl.timeline.components_TimelineItemReactionsView_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsView_Night_0_en",0,],
-["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20049,],
+["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20056,],
["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_0_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_0_en",0,],
["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_1_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_1_en",0,],
["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_2_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_2_en",0,],
@@ -1134,8 +1139,8 @@ export const screenshots = [
["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_5_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_5_en",0,],
["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_6_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_6_en",0,],
["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_7_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_7_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20049,],
-["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20049,],
+["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20056,],
+["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20056,],
["features.messages.impl.timeline.components_TimelineItemStateEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemStateEventRow_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemStateView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStateView_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemStickerView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStickerView_Night_0_en",0,],
@@ -1148,8 +1153,8 @@ export const screenshots = [
["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_3_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_4_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_5_en",0,],
-["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20049,],
-["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",0,],
+["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20056,],
+["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20059,],
["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_1_en",0,],
["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_2_en",0,],
@@ -1172,84 +1177,84 @@ export const screenshots = [
["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,],
["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,],
["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,],
-["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20049,],
+["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20056,],
["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",0,],
-["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20049,],
-["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20049,],
+["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20056,],
+["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20056,],
["features.messages.impl.timeline_TimelineView_Day_2_en","features.messages.impl.timeline_TimelineView_Night_2_en",0,],
["features.messages.impl.timeline_TimelineView_Day_3_en","features.messages.impl.timeline_TimelineView_Night_3_en",0,],
-["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20049,],
+["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20056,],
["features.messages.impl.timeline_TimelineView_Day_5_en","features.messages.impl.timeline_TimelineView_Night_5_en",0,],
-["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20049,],
+["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20056,],
["features.messages.impl.timeline_TimelineView_Day_7_en","features.messages.impl.timeline_TimelineView_Night_7_en",0,],
-["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",20049,],
+["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",20056,],
["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,],
["libraries.designsystem.theme.components_TopAppBar_App_Bars_en","",0,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20049,],
-["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20049,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20056,],
+["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20056,],
["features.messages.impl.typing_TypingNotificationView_Day_0_en","features.messages.impl.typing_TypingNotificationView_Night_0_en",0,],
-["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20049,],
-["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20049,],
-["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20049,],
-["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20049,],
-["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20049,],
-["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20049,],
+["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20056,],
+["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20056,],
+["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20056,],
+["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20056,],
+["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20056,],
+["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20056,],
["features.messages.impl.typing_TypingNotificationView_Day_7_en","features.messages.impl.typing_TypingNotificationView_Night_7_en",0,],
["features.messages.impl.typing_TypingNotificationView_Day_8_en","features.messages.impl.typing_TypingNotificationView_Night_8_en",0,],
["libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Night_0_en",0,],
-["libraries.matrix.ui.components_UnresolvedUserRow_en","",20049,],
+["libraries.matrix.ui.components_UnresolvedUserRow_en","",20056,],
["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,],
["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,],
-["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20049,],
-["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",20049,],
-["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",20049,],
-["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",20049,],
+["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20056,],
+["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",20056,],
+["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",20056,],
+["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",20056,],
["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,],
["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,],
["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,],
["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,],
-["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",20049,],
+["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",20056,],
["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,],
-["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",20049,],
+["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",20056,],
["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,],
["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,],
["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,],
-["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,],
-["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20049,],
-["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_0_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_0_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_10_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_10_en",20049,],
+["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20059,],
+["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20056,],
+["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_0_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_0_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_10_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_10_en",20056,],
["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_11_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_11_en",0,],
["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_12_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_12_en",0,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_13_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_13_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_1_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_1_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_2_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_2_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_3_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_3_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_4_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_4_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_5_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_5_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_6_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_6_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_7_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_7_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_8_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_8_en",20049,],
-["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_9_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_9_en",20049,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_13_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_13_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_1_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_1_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_2_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_2_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_3_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_3_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_4_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_4_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_5_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_5_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_6_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_6_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_7_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_7_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_8_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_8_en",20056,],
+["features.verifysession.impl.outgoing_VerifySelfSessionView_Day_9_en","features.verifysession.impl.outgoing_VerifySelfSessionView_Night_9_en",20056,],
["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,],
["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,],
["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,],
@@ -1264,6 +1269,6 @@ export const screenshots = [
["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,],
["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,],
["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,],
-["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",20049,],
+["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",20056,],
["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,],
];
diff --git a/tests/konsist/src/main/kotlin/io/element/android/tests/konsist/failures/FailingComposableWithNonImmutableSealedInterface.kt b/tests/konsist/src/main/kotlin/io/element/android/tests/konsist/failures/FailingComposableWithNonImmutableSealedInterface.kt
new file mode 100644
index 0000000000..1e90577ca6
--- /dev/null
+++ b/tests/konsist/src/main/kotlin/io/element/android/tests/konsist/failures/FailingComposableWithNonImmutableSealedInterface.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.tests.konsist.failures
+
+import androidx.compose.runtime.Composable
+
+// Make test `Sealed interface used in Composable MUST be Immutable or Stable` fails
+
+sealed interface SealedInterface
+
+@Composable
+fun FailingComposableWithNonImmutableSealedInterface(
+ sealedInterface: SealedInterface
+) {
+}
diff --git a/tests/konsist/src/main/kotlin/io/element/android/tests/konsist/failures/FakeWrongClassName.kt b/tests/konsist/src/main/kotlin/io/element/android/tests/konsist/failures/FakeWrongClassName.kt
new file mode 100644
index 0000000000..68ea557b53
--- /dev/null
+++ b/tests/konsist/src/main/kotlin/io/element/android/tests/konsist/failures/FakeWrongClassName.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 New Vector Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ * Please see LICENSE in the repository root for full details.
+ */
+
+package io.element.android.tests.konsist.failures
+
+// Make test `Fake classes must be named using Fake and the interface it fakes` fails
+
+interface MyInterface
+
+// This class should be named FakeMyInterface
+class FakeWrongClassName : MyInterface
+
+class MyClass {
+ interface MyFactory
+}
+
+// This class should be named FakeMyClassMyFactory
+class FakeWrongClassSubInterfaceName : MyClass.MyFactory
diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt
index 7cc848d825..d334d88b55 100644
--- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt
+++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt
@@ -22,6 +22,7 @@ import com.lemonappdev.konsist.api.ext.list.withoutName
import com.lemonappdev.konsist.api.ext.list.withoutParents
import com.lemonappdev.konsist.api.verify.assertEmpty
import com.lemonappdev.konsist.api.verify.assertTrue
+import org.junit.Assert.assertTrue
import org.junit.Test
class KonsistArchitectureTest {
@@ -66,34 +67,44 @@ class KonsistArchitectureTest {
@Test
fun `Sealed interface used in Composable MUST be Immutable or Stable`() {
+ var failingTestFound = false
// List all sealed interface without Immutable nor Stable annotation in the project
val forbiddenInterfacesForComposableParameter = Konsist.scopeFromProject()
.interfaces()
.withSealedModifier()
.withoutAnnotationOf(Immutable::class, Stable::class)
.map { it.fullyQualifiedName }
-
Konsist.scopeFromProject()
.functions()
.withAnnotationOf(Composable::class)
.assertTrue(additionalMessage = "Consider adding the @Immutable or @Stable annotation to the sealed interface") {
- it.parameters.all { param ->
+ val result = it.parameters.all { param ->
val type = param.type.text
- return@all if (type.startsWith("@") || type.startsWith("(") || type.startsWith("suspend")) {
+ return@all if (type.startsWith("@") || type.contains("->") || type.startsWith("suspend")) {
true
} else {
- var typePackage = param.type.declaration.packagee?.name
- if (typePackage == type) {
- // Workaround, now that packagee.fullyQualifiedName is not available anymore
- // It seems that when the type in in the same package as the function,
- // the package is equal to the type (which is wrong).
- // So in this case, use the package of the function
- typePackage = it.packagee?.name
+ val typePackage = param.type.sourceDeclaration?.let { declaration ->
+ declaration.asTypeParameterDeclaration()?.packagee
+ ?: declaration.asExternalDeclaration()?.packagee
+ ?: declaration.asClassOrInterfaceDeclaration()?.packagee
+ ?: declaration.asKotlinTypeDeclaration()?.packagee
+ ?: declaration.asObjectDeclaration()?.packagee
+ }?.name
+ if (typePackage == null) {
+ false
+ } else {
+ val fullyQualifiedName = "$typePackage.$type"
+ fullyQualifiedName !in forbiddenInterfacesForComposableParameter
}
- val fullyQualifiedName = "$typePackage.$type"
- fullyQualifiedName !in forbiddenInterfacesForComposableParameter
}
}
+ if (!result && !failingTestFound && it.name == "FailingComposableWithNonImmutableSealedInterface") {
+ failingTestFound = true
+ true
+ } else {
+ result
+ }
}
+ assertTrue("FailingComposableWithNonImmutableSealedInterface should make this test fail.", failingTestFound)
}
}
diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt
index adc2b9ceb7..9d8e23e7dc 100644
--- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt
+++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt
@@ -73,6 +73,11 @@ class KonsistClassNameTest {
@Test
fun `Fake classes must be named using Fake and the interface it fakes`() {
+ var failingCases = 0
+ val failingCasesList = listOf(
+ "FakeWrongClassName",
+ "FakeWrongClassSubInterfaceName",
+ )
Konsist.scopeFromProject()
.classes()
.withNameContaining("Fake")
@@ -84,16 +89,19 @@ class KonsistClassNameTest {
val interfaceName = it.name
.replace("FakeRust", "")
.replace("Fake", "")
- (it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) &&
+ val result = (it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) &&
it.parents().any { parent ->
- // Workaround to get the parent name. For instance:
- // parent.name used to return `UserListPresenter.Factory` but is now returning `Factory`.
- // So we need to retrieve the name of the parent class differently.
- val packageName = parent.packagee!!.name
- val parentName = parent.fullyQualifiedName!!.substringAfter("$packageName.").replace(".", "")
+ val parentName = parent.name.replace(".", "")
parentName == interfaceName
}
+ if (!result && it.name in failingCasesList) {
+ failingCases++
+ true
+ } else {
+ result
+ }
}
+ assertThat(failingCases).isEqualTo(failingCasesList.size)
}
@Test
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png
index 33a9d65ee4..249dd28649 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3b380df8a4e69e9e11337db374b682e01f96738948e69eb33886817894a049b0
-size 30716
+oid sha256:72855bb6717291b00777e21711c0a5c8a7049e7b09cac7684dee9ae28e5be9f8
+size 29925
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png
index cba7000f48..1adbbfa52a 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5053e8716e3bfe5703f6d00e304101bbbf6cdebaf5eb5088a6043171a1f34e47
-size 41328
+oid sha256:2fa0cc7a8cfa1e1726d0ec75186cfd99fd67e9d5b168b0c6be669e355af2a1d6
+size 43007
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png
index 9bcb3813ac..edb45bb304 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ffbdcd28c32808fba8ffb7071b6440578716d3ae89149eb319c22d3f3b78b1ff
-size 59499
+oid sha256:79c69f5ca1c04d4e6544decea4150eb5f43bdde58070d1dfe57d0a4c94022dd5
+size 58850
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png
index e9d68af4ee..9c82b81785 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ccbb514ad9bd6a95ecff2e278574ac5bff9bd8a63a5fc91fa35302dbaa9e71f2
-size 55276
+oid sha256:d99e10bf3d0322ed25d883aa80376b0f1bd92d8174a6623e099272b4002fbfc4
+size 56880
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png
index 43814bce07..3aa9167cfe 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a2ea9839e3dd1288d99c2115c37bc7fe72716af9785c4de3e328a77a57d12d70
-size 56633
+oid sha256:e6f28ae60d74769a903228a58ed97f5753ec6e9a054b8e94d39d6c83ecb363d5
+size 58260
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png
index b254eeceb3..5382ae80f4 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5b28da0e8ff5cbedf8777b5af8ff6bab2bd5c476df80878b2c28dd96a354d978
-size 54383
+oid sha256:2e987390f164dcacfafd455a3ccd3f4ae9af7d8e057d91772670d28c6f6e6310
+size 56056
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png
index 851051fa3d..d3c00e7c2f 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9dc23b7e9533aa94245efa2089956259b00882809157cf32decaaa22827aeb59
-size 31678
+oid sha256:5b420340d9471294fce2458149f14c55df979060b248dba7cdd8bacfe71a39da
+size 30808
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png
index 0371868836..234cf0b705 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:150b375f3fa9c180ec221b3fcc3ed0397b75920cb760e25e327fd6be46370618
-size 41954
+oid sha256:05e71ef5a6fa821961c2a78885bab91eeeb783bac1fdaa495f32fd4173ecc615
+size 43621
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png
index bd45e398b4..80d7d0808c 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9dc54d0a6c3cb3069482b1c27ed6d80fd63b0bcad1a550bf5c4edb09f69db3a7
-size 60749
+oid sha256:cca307360497a2a298bb9968678c35afb44cdc68e2dd46a350868833bf770464
+size 59968
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png
index ae54d119d7..0f5a5043b9 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:71c42c595070733ac8ac2c50da116e73ea6eea7dc120f6f0d28022b5a5f925bd
-size 57099
+oid sha256:9426c57dc59d8341087b3800a40847e63b8e6ee3c4e65cfe1712b3f5fa884618
+size 58696
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png
index 9229891a5f..a6393e62c0 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e10c1c3f2b4045d20c9513c70bc4ea041e091976df5385b93d45c2d03b8f6e5f
-size 58513
+oid sha256:6527ca9d39895038bf0fec9cb9c1426f95db9f4b9460eff699c34bb59d11aaf8
+size 60122
diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png
index a9ab02f20e..9215e348fd 100644
--- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cb54ae79de75af32e32642063d9dc9e0c24b0089f187a043f0fc330151c72c75
-size 56170
+oid sha256:c5d4014d2701847fadd4e163c26e7ba220577c4b1e10ebd35c95b1c6aa81507b
+size 57814
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png
index d28af79e36..6d0ff2554e 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_10_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:916516ede645eaff617b40e6cf50acf2ba1e583827d778d22e9a012fe367fe7a
-size 106146
+oid sha256:a9d0338485aabe5296754868ce2fcd5097d914eea28298ec11c16f7161ae2341
+size 111617
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png
index 15fef4a084..deabc9b36a 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_11_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a6eee1185065c82f90cf53d7b9fd62e6de72d907606099b0536b6305ea9537f2
-size 117250
+oid sha256:45040e44ee78a5103ebf1a3963c24f1a201485affa3f24d8f707e4f99be6cafd
+size 112406
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png
new file mode 100644
index 0000000000..15fef4a084
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_12_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a6eee1185065c82f90cf53d7b9fd62e6de72d907606099b0536b6305ea9537f2
+size 117250
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png
index 6d0ff2554e..3fcad9605e 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a9d0338485aabe5296754868ce2fcd5097d914eea28298ec11c16f7161ae2341
-size 111617
+oid sha256:3463e70cd08f4d884f8bfafe7d66c5b75ac1fc05bf70cf1478a9f11def071069
+size 111151
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png
index 3fcad9605e..da1fd14667 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3463e70cd08f4d884f8bfafe7d66c5b75ac1fc05bf70cf1478a9f11def071069
-size 111151
+oid sha256:70c33e148a040ec24287f9ca48353a76e8167015f24d8249bff405e9cc9f16ff
+size 118640
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png
index da1fd14667..aaab740c4f 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_6_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:70c33e148a040ec24287f9ca48353a76e8167015f24d8249bff405e9cc9f16ff
-size 118640
+oid sha256:9b3e666dc4693d7c096dd5c0168770f72be41c41797a93e7c728a20b587ddaba
+size 92658
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png
index aaab740c4f..28403e285e 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_7_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9b3e666dc4693d7c096dd5c0168770f72be41c41797a93e7c728a20b587ddaba
-size 92658
+oid sha256:9af5a8c8a529eb5f8ea40e9c8028ce2c0ca4b352ef80b2778fa5122cc6bfa937
+size 96826
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png
index 28403e285e..8cb6932f43 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_8_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9af5a8c8a529eb5f8ea40e9c8028ce2c0ca4b352ef80b2778fa5122cc6bfa937
-size 96826
+oid sha256:084e303ed61e399ddbefda7e54cadb69545eb0db9493185aa48a3db7ba69fb04
+size 112515
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png
index 8cb6932f43..d28af79e36 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Day_9_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:084e303ed61e399ddbefda7e54cadb69545eb0db9493185aa48a3db7ba69fb04
-size 112515
+oid sha256:916516ede645eaff617b40e6cf50acf2ba1e583827d778d22e9a012fe367fe7a
+size 106146
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png
index b1833d0459..17884e7282 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_10_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a9f9d59037ba084e60e6324e066736bc08c0b52319664d67eb84779df6806ce4
-size 91377
+oid sha256:88584b1d4a4876e68e2972f9bbd03156127ee9b552de1ec20a9057d8f6cb1828
+size 101296
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png
index 29dcd629aa..1f4cc5b616 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_11_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:07458d183bae7ecfb7ee61bb6f2e0abb9a4399dd373068002fec3722f575e754
-size 102438
+oid sha256:cafbd46dbff04191aeabb2ea403d99728972c1854116022e545b4ca6be7bc675
+size 102209
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png
new file mode 100644
index 0000000000..29dcd629aa
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_12_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:07458d183bae7ecfb7ee61bb6f2e0abb9a4399dd373068002fec3722f575e754
+size 102438
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png
index 17884e7282..9d57ee0ac2 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:88584b1d4a4876e68e2972f9bbd03156127ee9b552de1ec20a9057d8f6cb1828
-size 101296
+oid sha256:b1e7887e1120c852e5a9086dba35fd8e52485d0e285c2e3724687ffa71babd45
+size 96405
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png
index 9d57ee0ac2..e0062f755b 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b1e7887e1120c852e5a9086dba35fd8e52485d0e285c2e3724687ffa71babd45
-size 96405
+oid sha256:c3d75eca5904d605b91becebca60199f7e60e6f2bec6b9a945ce8d130cfd7e47
+size 104802
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png
index e0062f755b..c382416a8b 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_6_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c3d75eca5904d605b91becebca60199f7e60e6f2bec6b9a945ce8d130cfd7e47
-size 104802
+oid sha256:e97d78225215b0b5e13f369485e7503d020baa7d157cb1c6826d18759d580c6e
+size 78221
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png
index c382416a8b..65edf4ebd3 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_7_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e97d78225215b0b5e13f369485e7503d020baa7d157cb1c6826d18759d580c6e
-size 78221
+oid sha256:95f818f0426868414b0ef5cb525254ad67811ec777c31a435072fb2236914f22
+size 82448
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png
index 65edf4ebd3..d979aa4f0d 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_8_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:95f818f0426868414b0ef5cb525254ad67811ec777c31a435072fb2236914f22
-size 82448
+oid sha256:050785374d848e773941d858848e34f5d1753fcdada4dcef548a98eb5e78c31a
+size 99409
diff --git a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png
index d979aa4f0d..b1833d0459 100644
--- a/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.joinroom.impl_JoinRoomView_Night_9_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:050785374d848e773941d858848e34f5d1753fcdada4dcef548a98eb5e78c31a
-size 99409
+oid sha256:a9f9d59037ba084e60e6324e066736bc08c0b52319664d67eb84779df6806ce4
+size 91377
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png
index 102de3524f..0e0342e192 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ab41e6b8fe6c235a4915d88a3d42e29cc84678a2b41bafbe38f55111632d1eec
-size 31740
+oid sha256:e67a540966100272311381e87011149cdb15c8191a6f2bbc40d1febff999c431
+size 24067
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png
index 51af3e4480..f500ff60dd 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2fb57605dad290919daa4c331442d69651e26db88235f77e4912ffb9631a36c0
-size 45151
+oid sha256:65023f7233f112547ccd0850c321b2d6610cfb6a1371c494f68722e75874f871
+size 45915
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png
index 87c7906ea2..c80b8639e0 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:baadc64d3b4f9464bc6063cc9cc10adfa256d25308c83f647e508f42fd45ef1c
-size 46852
+oid sha256:e2c2e01bd133c7b84e381141b6baf22783cb585cb3af9f790785dbf8aeaeeed6
+size 47644
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png
index 0d058f0639..4088be4e1e 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1009af703a11348dac63dc071333e077f4bba76c73bd64bf9e532381c7607c1d
-size 39624
+oid sha256:9bd6fb63059cebc7dc7b850b5aa73549ab9846eda68b1b6d9a4f8e0716d42c3c
+size 40419
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png
index 07d4116d65..b3dbf77d1d 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0f5adfb435286a84587a66d6970b1a7f03a8cb53eac86956f61092d97ea16951
-size 43121
+oid sha256:6b4e4a075bcb4b95455c27ce2e5f9f1bdac4a1aca22ad944dd53fdbaeb6ca970
+size 44550
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png
index 74dc1f4978..87c07faab3 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d3843655f4b2f55b5eb2cdb014e1ca03f9570e312e725fe074a5191e0350c079
-size 40677
+oid sha256:1a2bc7e9098301d17e72a61a7baf01e52aa11566e1da4ffe3b43a66fa37652b2
+size 42103
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png
index 5a2491caa4..25da7b8bf1 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ce1c3d6c04316fd9f43b86edb04ba209eb6df450f40438f98b8503fb116d4ea4
-size 40271
+oid sha256:f097af2773ff2ecf70a69e4292dc118b4c8616f1c8f979e7d121e86a16ef3072
+size 38506
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png
index eb710cb8ef..2bf210d590 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4839112543c6ab57848c1dd30440b12703da1a35a6457bf9fa5f5aabd1dd08b9
-size 40963
+oid sha256:8f49870a5333cbaf1c6c3ac5ddcb85290d04efc79ffec93d8dc39b59f9712820
+size 42391
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png
index a4293ee744..6de43e00ee 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:41528c85820cbe666c719536022fb52ce510055c8c8ef3f1ce36da32731f0a0b
-size 41615
+oid sha256:883f160afa3fc3d2c0be5098205ea616875084ee0f122ebf994d0fee53a8ecd1
+size 39847
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png
index 8a828912e4..cf03f3c12f 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ac14f7921bedaf7135655775b524fde596120d6ea9b708ba5653b3805f567067
-size 41469
+oid sha256:7790c892daeee8910ce17caac2c957d09fffec0d41a51b3adc1d5bef8dcee1a1
+size 42261
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png
index 1adcf8bbaa..63da19cb01 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ce9244eb3b531a4c2816a32c8f806476cd0776f6394f32cebcb82f8a48cd64d7
-size 30837
+oid sha256:bc7b733680a0d86ee1231345e58641fb3a208da21de62a50f624d9ae04c6e140
+size 31661
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png
index 46e42eb390..7e43e760b2 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4aa886aa0f70c7c85fc25e9366792bd6e2c9e1a9b6c8864282834d9f72b3fcb2
-size 30809
+oid sha256:20504466241e36817557812f6b378aceab9c2e271a596bd3d037c6be41af7c54
+size 23624
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png
index 0c6ae9106a..1667fe5ff0 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:756255463c3747888878fef57ec4c3204075993d3fb5bdaf3d1bbe436648862c
-size 44345
+oid sha256:48028e4c3ca7e9b871683165f029430bcd4e0fc2411e4ffc83a93abb641d96a2
+size 45132
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png
index 30c644a80b..e44f324015 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2bdc999259dabe20157611f27925d6f0c8f9f77eebc1914fa8f793b62aa8c299
-size 45864
+oid sha256:b040fe47521f5d9d76d7892412bb2b5cf7e2b93b951f5de5f772503797fb6b24
+size 46548
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png
index bbf069a81c..5797dc5345 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ffb565c4d790e24a2f395b12d8dbbfa1ba4abadd7cf9951deae049696e04b206
-size 38843
+oid sha256:6db046a97f14f2df3db2415d71a02ffd6e706fe73def67c21f0d844be279da59
+size 39617
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png
index eed6d921be..9b837817e6 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:87d68af6f69c67de710145b3fabbff40bc6c9a767542e5a62be80d084972cb28
-size 42221
+oid sha256:7ee53243923d7b5adcc2094d3fe6bb87be00a179cae11966dcb230f2c3e8246e
+size 43681
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png
index 201ce10bc6..6d0c2a905b 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:08c6685bec4751c852ce2440c5b3dd006d46b80dfd0f5986a3392278f486e181
-size 39863
+oid sha256:b88e54ba4743e1e245b5a4c7d6b4045f816241f6cfc8716b8cede0b62666222b
+size 41286
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png
index d20ad88b3c..c479ebef74 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:04a1cbb1d1e98f87446ad911b61b002e34ceb2725ec24dfd884561d3585b9d83
-size 39518
+oid sha256:d88b4d82bb0d416aff7b32647479181ac9702c36c08370e7671d6e5ef80687c7
+size 37825
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png
index 4113521ddd..885d6afaed 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d5ba01dbb6e8d1d238fcfdecbd67ee74bf833a3592087ec5ffc24b8ddeb85178
-size 40124
+oid sha256:b3d4dd1766a3f46acd86bdd5ec920c56a5e5f897c81c1477df10ba59dcd3d5b7
+size 41554
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png
index cfb777592f..13b4a76016 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dd84e6907dc39e1ad7e6db95d8453aa51e18b14c881499c05a233678fa0e7094
-size 40762
+oid sha256:842fbea74e53c8804fd0a3e9fe96dcb21b5c91a099e1de33d8ec983fd9a8a80a
+size 39112
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png
index ec71956322..18e022f292 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b5c35af3e85d906c6ed24fbb454cf32c7b25f87471e631af8b6ccc1d8465de00
-size 40631
+oid sha256:1311ec5e008b44d81e6556164f780c57dea3e4721cc47caccdbf337dd4027eb7
+size 41402
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png
index 6d28d9d799..99c6f765a5 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:486f9e142212d3864dfb936905feb37421fd4e8c9b5734c5f9ee4f29ec1166f6
-size 29964
+oid sha256:d2cf27d2f053f33c67d944a8f45e0206165b2db2f3b959eb9e0bb943f84fe6a1
+size 30657
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png
index 1a48fb35cf..71d0679471 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2399ee4cd37cbafec07e87bfab90e66ee3df5b6aba602d5cd9bd1114c7365642
-size 397379
+oid sha256:17aa655ef22beec5cef50f5d44cb2ecd8ad3a1979bc072a33079a49a8c4495c5
+size 397284
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png
index 3982a58c4c..9df61f791e 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d18f7e2c169f7e4b9e435584d868454ae5f765a32d29bbbfe48d65b45f4161d6
-size 18845
+oid sha256:8a0e722772be6b9d38c5f0ef3198502ca6e6ebb2599e3a4ebb4cc95cde907095
+size 52012
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png
index 2cb5dc89f8..40926d90b9 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3250fa9767aec264308719c6fdf6cea94d5ccea21bfa8a735d7df5d79b572555
-size 21214
+oid sha256:aa4cae0da657162117538b6839032ebf467542a043f18e308eeaf5ae28ca14e8
+size 51984
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png
index e34eb6e69c..63c6848197 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4ba70221a149ce0f8abaa4e4f870011bea82630edf99ecacea560a737f56346f
-size 22215
+oid sha256:df6fc9bcb3636549fdfeacb4c9e19cc3c699b7519558bd14f409e7b0c6a84d80
+size 89846
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png
index e799726c52..a31bc036b5 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:361ff23fd2ff99aecfdffd10b45e9235d86183d4856cb2a3e99f85b9e04c2d59
-size 51376
+oid sha256:aedd5d3a01457b8ed06b16cd63d08f24ae34568e2b912b82fb892b154c94e6df
+size 392780
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png
index df965394aa..71d0679471 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:efbfed755b29293009f45fca33f58863b612772de9a1d55593c979dbb04ff6f2
-size 88981
+oid sha256:17aa655ef22beec5cef50f5d44cb2ecd8ad3a1979bc072a33079a49a8c4495c5
+size 397284
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en.png
index afa1dd9b61..ffb879e770 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fee2af8462597d58274b7168c5cfe1f6d6b0909b048adc0f4fc5b3c12a90b859
-size 8861
+oid sha256:397d76d3fe47c61d112b09355097f103ef3ab38caaa99d838d44498a85969289
+size 12419
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en.png
new file mode 100644
index 0000000000..8f51f4d170
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aba63b0f223f8480d40e6c9c48ce44a1ae1a8bdcc3d101030b9a0bd5f1e9ebee
+size 23773
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en.png
new file mode 100644
index 0000000000..cff8f7e35f
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d5c8494ebb4ceaf3a31b661aec47f8a33afeb7aab1457483b7009099a6b56f86
+size 8960
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en.png
new file mode 100644
index 0000000000..afa1dd9b61
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fee2af8462597d58274b7168c5cfe1f6d6b0909b048adc0f4fc5b3c12a90b859
+size 8861
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en.png
index 212726df37..3809d0c0d5 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d4f48cd7dc7e2bbf7363d1127e46721c25bb8dd887927dbcffe525f5bb5bae01
-size 8781
+oid sha256:252efa710f80f4ea57c909cfd5cfee2beef982a209367138f10972dd5aa49db2
+size 12264
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en.png
new file mode 100644
index 0000000000..8561e18151
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5d0a687a259fafe830560b762a915e478d680dd7c34a295d72e82fc7c427a815
+size 23403
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en.png
new file mode 100644
index 0000000000..a851ce84e5
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dda55a19381d9f51a270afa644894f909d8c479be0a5e57b977393c9f1253683
+size 8960
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en.png
new file mode 100644
index 0000000000..212726df37
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d4f48cd7dc7e2bbf7363d1127e46721c25bb8dd887927dbcffe525f5bb5bae01
+size 8781
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en.png
index 7877602031..e847cd3292 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b1f04171ef894f299b58cc15158daf9655cc04f9ab2418973e7e6e78e22884e8
-size 31693
+oid sha256:f1c226a36c42d4aa725a941ed58036dc5e75c9547720e00b75c64c7fe33491af
+size 31647
diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en.png
index 57f18ac15c..562bcf09f2 100644
--- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8ce15bbbb3bc562f92a7d07a0f2f907d4e351e0b7133a61b7ef49540ef622c15
-size 30613
+oid sha256:47afdecd896bef06623b81ca53e0b60a0deeb01014903906fbd3fbf15ea4a5f6
+size 30592
diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_Sliders_Sliders_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_Sliders_Sliders_en.png
index 432ee9660e..cdd5065f25 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_Sliders_Sliders_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_Sliders_Sliders_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:99102e56ca747eb69e03543032915e9a6a608d6013843889ad0dcd3e1953141c
-size 11451
+oid sha256:05c37f69de81b26ce0083047cb18120300cc0e76aa7e3c0d3c24ba5de39681bd
+size 14134
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_0_en.png
deleted file mode 100644
index c6d641ba08..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_0_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:a6fe771fa6492768239d0caf7a9c10613efb95ff9c2c1b786ee0a6974392af9f
-size 389635
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_10_en.png
deleted file mode 100644
index 6a81f3f129..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_10_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:2b286342ff4d46637beac1f980294f77b3e2eb6824d56448cdbdce7b41c911ab
-size 388612
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_1_en.png
deleted file mode 100644
index 909f84c081..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_1_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:7b023a77242de9cab647e87b18edcd86a48a7843aa8fa51c84b443e3e8b41bcb
-size 389669
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_2_en.png
deleted file mode 100644
index fb24aa81f3..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_2_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:75ff0cd0cfe594a217d2b58b48c2bb4aedad692a270c2cee8aa3d4bdf6758e1e
-size 94797
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_3_en.png
deleted file mode 100644
index 3b71589b75..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_3_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:0dc5fdbd7d0b3980ad19bf74640067e8bb294def913e3d13d7bc4ad9c822382d
-size 389921
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_4_en.png
deleted file mode 100644
index 67b4bf5eae..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_4_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:be67078d37af27ed532a6ae3a6194c154ca72b7c87319eed3f0e982cbc677acc
-size 10908
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_5_en.png
deleted file mode 100644
index b56bd6454a..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_5_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:e6113747e1677c2f28c2a109bc2c7075a753917068c1bbc3a46d5bdef4db4e23
-size 5756
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_6_en.png
deleted file mode 100644
index 4cf13a8381..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_6_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f5a6ec7984ceab5acf44431a9bff89c29c9ac27c95804d29b800124addd6e910
-size 14800
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_7_en.png
deleted file mode 100644
index 27b6fb0c1b..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_7_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d03b94e2b502b9857b9b4c2527df86d1aa0a194abed794cbe601ec4172422dcc
-size 14987
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_8_en.png
deleted file mode 100644
index f4d2b37db6..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_8_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:56b9d11058f06732364668a5833f52fa4e62541fa8ee48f13996ae0a11e11100
-size 13609
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_9_en.png
deleted file mode 100644
index b0693b38c5..0000000000
--- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.viewer_MediaViewerView_9_en.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:25c1e3cb51b13bb65b281180862ac8fb6faa1e8bd0ce26d8d0e07321c03c116c
-size 13742
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png
new file mode 100644
index 0000000000..50f49e2d0b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2907ba5f75a40e30a37ad4d302797cea4e3d2b77cb1c66a9432319242b8f1995
+size 12188
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png
new file mode 100644
index 0000000000..c4d024965e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5307e90428957819812269b9b3e0c6e9d59238141d54cd959aa5506290797a35
+size 11587
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png
new file mode 100644
index 0000000000..37bc205626
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:59e981e51595a368745c92f355793b2c0301a9e4929430733876a02f3ac75e2e
+size 11881
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png
new file mode 100644
index 0000000000..37f1c2ed22
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:52354bcf471b14e38e582cc29f73407c8ca65026b2b7c6db3d3b28ec94950679
+size 11413
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en.png
new file mode 100644
index 0000000000..0d80d15a73
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2a3e650bde2df79bebfc110eb46998ab21b1e5dba471fd5a755371e5027a27a5
+size 388634
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en.png
new file mode 100644
index 0000000000..c8e897025b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:193190902275db6ffd03dcc41b190e8fc3bba60dda9678274481fbbefe89567d
+size 387830
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en.png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Day_0_en.png
rename to tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en.png
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en.png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/libraries.mediaviewer.api.local.pdf_PdfPagesErrorView_Night_0_en.png
rename to tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en.png
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png
new file mode 100644
index 0000000000..93d2782dbb
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:333a21a41a7d5f8d47946648a7381dadeccf213a1176696b3512c08ae929d4d6
+size 7819
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png
new file mode 100644
index 0000000000..a40e83dc48
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cba8f49caf65856569266a561206437840a43da2d41ed5f08321ecda99204329
+size 8236
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png
new file mode 100644
index 0000000000..d6bb46d5c2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:773785bb234c0719c0f27ee91a970c63d7f971518dc0c83298a4b6adb9acc4cf
+size 8066
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png
new file mode 100644
index 0000000000..64ec4ae5d4
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5424e7ce4a5259aab297a7911741352f0fba01e5fdac972768441db9edf41171
+size 7675
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png
new file mode 100644
index 0000000000..6ab81fd4de
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:267d4be8b727a0ecb5af1e5f1e69adfd68f50f32f1de78f4f9fde60f635244b5
+size 13045
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png
new file mode 100644
index 0000000000..48a87ab6ae
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:412476e819f688b5314651fd3d59439fc0e4f53ee777e3a070b82fd19d51700e
+size 13272
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png
new file mode 100644
index 0000000000..ae44f16e97
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9df1a0ff2b3aaab2d1a346cb134b560d65c462286575ffc6124099529562eac1
+size 389594
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png
new file mode 100644
index 0000000000..347f2dd6c2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4fde3cef34d23c894ae480a1b4c961065f244d845584f8607c4bb21e0a7e5f10
+size 388615
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png
new file mode 100644
index 0000000000..a9ae9d7999
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cf07ed00618c0552205b1e726050382369041bb7f2d9742b754a5652eca48265
+size 389631
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png
new file mode 100644
index 0000000000..173f440a84
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:143285221dd5a1e714a9897293f13c45ca567635e60350738033b315f44f742a
+size 94735
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png
new file mode 100644
index 0000000000..a63c5a2230
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a4e1b6a7a3dcc1627aec1767ac8edac95bec483ebdc98d71d65342084e08a4dc
+size 396792
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png
new file mode 100644
index 0000000000..585ab58d5e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6c3c2b7b1d64387ec1109ab21304df50de5bd4fac0317c27a2799e7405da3843
+size 22219
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png
new file mode 100644
index 0000000000..94ba7bede2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:364fce9e921a21dcaae9ef1d7c98efe47c4c9118d23958550ee9eafaf202e2fa
+size 5751
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png
new file mode 100644
index 0000000000..72bdd87b18
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:769a00d9e84cb2da43d790158f35e66bc5ed6538fdcb7f5e316f5de13d9bd9ad
+size 14768
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png
new file mode 100644
index 0000000000..7658ec5375
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bf1804b21f3d383c94e28714746ac61987643c8ec0480d2850b19eb01991aa4e
+size 15043
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png
new file mode 100644
index 0000000000..f927629007
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ec58fa08f3c160e1b7d462b580f79b1c05a5644b9f807a79cfeebbeea417ed10
+size 13502
diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png
new file mode 100644
index 0000000000..4394560d46
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:689081427ece8bc009266a50b9d2a80def581f51f00bf65b35d295b0ea7dcab3
+size 13736
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en.png
new file mode 100644
index 0000000000..c8aedb734a
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9bcb98d543eba3d43a58b9d17f753c65ccbae2df6f6ebf444c2eccae482a7466
+size 18474
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en.png
new file mode 100644
index 0000000000..2053e6fa75
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e77770bc5d582ad53fc1ad7d3d86b8df85e2c0f8fb997145a1c695ca14cf1e93
+size 17258
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png
index fadf662965..5f3d66edea 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:97d9c333fdc5684971e22593b246ca2751657691dad90ec89d891379e7a0b47f
-size 60161
+oid sha256:8c4220a5d9401d42a905dcf204bd273e8039d77a889209d4eb35de7c384ed05c
+size 61113
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png
index 068ccea0fd..80e866f801 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c08a7e954c11ff61a9130c54c0b273a5b8996c9095a4dae07cb4b5bc357fc15f
-size 58458
+oid sha256:009a1fc06c9a2e2bc112c4483002b43e9710c5ced3b2668c40c91b7c54d43b30
+size 59382
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png
index b5330db5c9..d284369893 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1b9b24eafbcaa2143c199a0522fa1aae98d9c7bddb80364602f0662567a2f1a1
-size 56485
+oid sha256:2eb0eaa26e48d182bd3dc78671cb43f02c24ef5f15fb4e6e8b47da2f3d37ce7b
+size 56567
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png
index dea84aaa40..101c090e86 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fc7a5491acff69b64ea73c1a62b7ae9e148ce57768697de2ec280327cd72298d
-size 55402
+oid sha256:fcfa2769e764b164375e6f6ef5194ce9ef686b6f76e16848270380a88beb175a
+size 55518
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png
index 82475e58db..17daeade89 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1967fa34ef6bd37c373f68badaed4e41b04efbbf929187e6ded4cfb903715325
-size 59539
+oid sha256:4f6f448d800b741e7e59a44b0f660f4702603e394df6223b1d968c862266083e
+size 59832
diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png
index db2e4e318d..270f2ab1d1 100644
--- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:430b30b65f5908fce562be613afa41131c4fbe8849db3d3f5a3fa424417469a4
-size 57827
+oid sha256:81bfbaf9030bc40ca6744dd6bf8170243243ebcd98fbc3de71fed85798d60412
+size 58150