From effddbb583ffba24df58b0393f371b6de72d1b75 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 14:21:35 +0000 Subject: [PATCH 01/64] fix(deps): update dependency io.nlopez.compose.rules:detekt to v0.5.1 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 19aaf78405..4d657a5c72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,7 +46,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.4.28") + detektPlugins("io.nlopez.compose.rules:detekt:0.5.1") detektPlugins(project(":tests:detekt-rules")) } From 198f3f2a0b7ec34dbcba6e39bc0d611c844c8abb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:19:18 +0000 Subject: [PATCH 02/64] fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v25.12.4 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c5126345c..71a1a097dc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -177,7 +177,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.12.2" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.12.4" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From e814906ba1bcdc4f0b20a7491ab87ed2aa7513eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Dec 2025 16:55:22 +0100 Subject: [PATCH 03/64] Restore disabled tests with FFI fakes --- .../impl/RustMatrixClientFactoryTest.kt | 2 - .../matrix/impl/RustMatrixClientTest.kt | 2 - .../impl/auth/HomeserverDetailsKtTest.kt | 2 - ...HomeserverLoginCompatibilityCheckerTest.kt | 2 - .../RustMatrixAuthenticationServiceTest.kt | 4 +- .../auth/qrlogin/SdkQrCodeLoginDataTest.kt | 2 - .../RustNotificationServiceTest.kt | 13 ++----- .../RustNotificationSettingsServiceTest.kt | 4 +- .../impl/pushers/RustPushersServiceTest.kt | 2 - .../matrix/impl/room/RoomInfoExtTest.kt | 2 - .../matrix/impl/room/RoomInfoMapperTest.kt | 2 - .../matrix/impl/room/RustBaseRoomTest.kt | 2 - .../impl/room/join/DefaultJoinRoomTest.kt | 2 - .../room/member/RoomMemberListFetcherTest.kt | 2 - .../RustBaseRoomDirectoryListTest.kt | 2 - .../RustBaseRoomDirectoryServiceTest.kt | 4 +- .../impl/roomlist/RoomListFactoryTest.kt | 4 +- .../roomlist/RoomSummaryListProcessorTest.kt | 34 ++++++----------- .../roomlist/RustBaseRoomListServiceTest.kt | 2 - .../spaces/RoomSummaryListProcessorTest.kt | 37 ++++++------------- .../impl/spaces/RustSpaceRoomListTest.kt | 10 ++--- .../MatrixTimelineDiffProcessorTest.kt | 34 ++++++----------- .../matrix/impl/timeline/RustTimelineTest.kt | 2 - .../timeline/TimelineItemsSubscriberTest.kt | 13 ++----- 24 files changed, 49 insertions(+), 136 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt index 471efa30a8..b81ddd713d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt @@ -23,11 +23,9 @@ import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import java.io.File -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RustMatrixClientFactoryTest { @Test fun test() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 06bd91eb24..c81d9f1c15 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -31,13 +31,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.UserProfile import java.io.File -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RustMatrixClientTest { @Test fun `ensure that sessionId and deviceId can be retrieved from the client`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt index 82fa3dfbc7..a5c7b2dbc8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt @@ -11,10 +11,8 @@ package io.element.android.libraries.matrix.impl.auth import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class HomeserverDetailsKtTest { @Test fun `map should be correct`() { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt index c0122b2a7c..50d1f3723b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt @@ -14,10 +14,8 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RustHomeserverLoginCompatibilityCheckerTest { @Test fun `check - is valid if it supports OIDC login`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index f620e942a9..f8f792557d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -23,13 +23,11 @@ import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import java.io.File class RustMatrixAuthenticationServiceTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `setHomeserver is successful`() = runTest { val sut = createRustMatrixAuthenticationService( clientBuilderProvider = FakeClientBuilderProvider( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/SdkQrCodeLoginDataTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/SdkQrCodeLoginDataTest.kt index d4c71f2a83..a0c8f4598f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/SdkQrCodeLoginDataTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/SdkQrCodeLoginDataTest.kt @@ -11,10 +11,8 @@ package io.element.android.libraries.matrix.impl.auth.qrlogin import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData import io.element.android.libraries.matrix.test.A_HOMESERVER_URL -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class SdkQrCodeLoginDataTest { @Test fun `getServer reads the value from the Rust side, null case`() { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt index e6fc802ed2..a1dffa7c64 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt @@ -29,15 +29,13 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationStatus import org.matrix.rustcomponents.sdk.TimelineEventType class RustNotificationServiceTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun test() = runTest { val notificationClient = FakeFfiNotificationClient( notificationItemResult = mapOf(AN_EVENT_ID.value to aRustBatchNotificationResult()), @@ -58,8 +56,7 @@ class RustNotificationServiceTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `test mapping invalid item only drops that item`() = runTest { val error = IllegalStateException("This event type is not supported") val faultyEvent = object : FakeFfiTimelineEvent() { @@ -86,8 +83,7 @@ class RustNotificationServiceTest { assertThat(successfulResult?.isSuccess).isTrue() } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `test unable to resolve event`() = runTest { val notificationClient = FakeFfiNotificationClient( notificationItemResult = emptyMap(), @@ -99,8 +95,7 @@ class RustNotificationServiceTest { assertThat(exception).isInstanceOf(NotificationResolverException::class.java) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `close should invoke the close method of the service`() = runTest { val closeResult = lambdaRecorder { } val notificationClient = FakeFfiNotificationClient( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt index 81d0a3307e..e9a121679b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt @@ -16,13 +16,11 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.NotificationSettings class RustNotificationSettingsServiceTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun test() = runTest { val sut = createRustNotificationSettingsService() val result = sut.getRoomNotificationSettings( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt index 1843bf4dd1..61b2965cdd 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt @@ -13,10 +13,8 @@ import io.element.android.libraries.matrix.api.pusher.UnsetHttpPusherData import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RustPushersServiceTest { @Test fun `setPusher should invoke the client method`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index dc4eba261b..86a50c3926 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -14,10 +14,8 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import io.element.android.libraries.matrix.test.A_USER_ID -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RoomInfoExtTest { @Test fun `get non empty element Heroes`() { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt index c964f02950..5c1c4a2aa3 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt @@ -32,7 +32,6 @@ import io.element.android.libraries.matrix.test.room.defaultRoomPowerLevelValues import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toImmutableList -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.Membership import uniffi.matrix_sdk_base.EncryptionState @@ -40,7 +39,6 @@ import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RoomInfoMapperTest { @Test fun `mapping of RustRoomInfo should map all the fields`() { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoomTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoomTest.kt index a98a222c1e..9c8feef2dc 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoomTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoomTest.kt @@ -31,11 +31,9 @@ import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.isActive import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import uniffi.matrix_sdk.RoomMemberRole -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RustBaseRoomTest { @Test fun `RustBaseRoom should cancel the room coroutine scope when it is destroyed`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoomTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoomTest.kt index e4f0b02e33..52aaa62b97 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoomTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/join/DefaultJoinRoomTest.kt @@ -25,10 +25,8 @@ import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class DefaultJoinRoomTest { @Test fun `when using roomId and there is no server names, the classic join room API is used`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 266a4eed7c..c1c436c405 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -24,10 +24,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_3 import io.element.android.libraries.matrix.test.A_USER_ID_4 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits cached members, if any`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryListTest.kt index cf3260b85c..cf3c746ec0 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryListTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryListTest.kt @@ -19,12 +19,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.RoomDirectorySearch import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntryUpdate -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") @OptIn(ExperimentalCoroutinesApi::class) class RustBaseRoomDirectoryListTest { @Test diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryServiceTest.kt index 04e6a9a3aa..a873298f3e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustBaseRoomDirectoryServiceTest.kt @@ -11,12 +11,10 @@ package io.element.android.libraries.matrix.impl.roomdirectory import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test class RustBaseRoomDirectoryServiceTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun test() = runTest { val client = FakeFfiClient() val sut = RustRoomDirectoryService( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt index ec8053e940..741ed93af8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt @@ -12,13 +12,11 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomList import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomListService import io.element.android.services.analytics.test.FakeAnalyticsService import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import kotlin.coroutines.EmptyCoroutineContext class RoomListFactoryTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `createRoomList should work`() = runTest { val sut = RoomListFactory( innerRoomListService = FakeFfiRoomListService(), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index eaa62abb65..bdc202d4fc 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -21,15 +21,13 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate class RoomSummaryListProcessorTest { private val summaries = MutableStateFlow>(emptyList()) - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Append adds new entries at the end of the list`() = runTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() @@ -41,8 +39,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue() } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PushBack adds a new entry at the end of the list`() = runTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() @@ -52,8 +49,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PushFront inserts a new entry at the start of the list`() = runTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() @@ -63,8 +59,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Set replaces an entry at some index`() = runTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() @@ -76,8 +71,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Insert inserts a new entry at the provided index`() = runTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() @@ -89,8 +83,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Remove removes an entry at some index`() = runTest { summaries.value = listOf( aRoomSummary(roomId = A_ROOM_ID), @@ -105,8 +98,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PopBack removes an entry at the end of the list`() = runTest { summaries.value = listOf( aRoomSummary(roomId = A_ROOM_ID), @@ -121,8 +113,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PopFront removes an entry at the start of the list`() = runTest { summaries.value = listOf( aRoomSummary(roomId = A_ROOM_ID), @@ -137,8 +128,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Clear removes all the entries`() = runTest { summaries.value = listOf( aRoomSummary(roomId = A_ROOM_ID), @@ -151,8 +141,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value).isEmpty() } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Truncate removes all entries after the provided length`() = runTest { summaries.value = listOf( aRoomSummary(roomId = A_ROOM_ID), @@ -167,8 +156,7 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Reset removes all entries and add the provided ones`() = runTest { summaries.value = listOf( aRoomSummary(roomId = A_ROOM_ID), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustBaseRoomListServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustBaseRoomListServiceTest.kt index 9c8c0ddb69..88b57035e8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustBaseRoomListServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustBaseRoomListServiceTest.kt @@ -19,12 +19,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator import org.matrix.rustcomponents.sdk.RoomListService as RustRoomListService -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") @OptIn(ExperimentalCoroutinesApi::class) class RustBaseRoomListServiceTest { @Test diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt index 116b98aaeb..253fd58dff 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RoomSummaryListProcessorTest.kt @@ -18,15 +18,13 @@ import io.element.android.libraries.previewutils.room.aSpaceRoom import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.SpaceListUpdate class RoomSummaryListProcessorTest { private val spaceRoomsFlow = MutableStateFlow>(emptyList()) - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Append adds new entries at the end of the list`() = runTest { spaceRoomsFlow.value = listOf(aSpaceRoom()) val processor = createProcessor() @@ -38,8 +36,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue() } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PushBack adds a new entry at the end of the list`() = runTest { spaceRoomsFlow.value = listOf(aSpaceRoom()) val processor = createProcessor() @@ -49,8 +46,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value.last().roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PushFront inserts a new entry at the start of the list`() = runTest { spaceRoomsFlow.value = listOf(aSpaceRoom()) val processor = createProcessor() @@ -60,8 +56,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value.first().roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Set replaces an entry at some index`() = runTest { spaceRoomsFlow.value = listOf(aSpaceRoom()) val processor = createProcessor() @@ -73,8 +68,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Insert inserts a new entry at the provided index`() = runTest { spaceRoomsFlow.value = listOf(aSpaceRoom()) val processor = createProcessor() @@ -86,8 +80,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Remove removes an entry at some index`() = runTest { spaceRoomsFlow.value = listOf( aSpaceRoom(roomId = A_ROOM_ID), @@ -102,8 +95,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PopBack removes an entry at the end of the list`() = runTest { spaceRoomsFlow.value = listOf( aSpaceRoom(roomId = A_ROOM_ID), @@ -118,8 +110,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PopFront removes an entry at the start of the list`() = runTest { spaceRoomsFlow.value = listOf( aSpaceRoom(roomId = A_ROOM_ID), @@ -134,8 +125,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Clear removes all the entries`() = runTest { spaceRoomsFlow.value = listOf( aSpaceRoom(roomId = A_ROOM_ID), @@ -148,8 +138,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value).isEmpty() } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Truncate removes all entries after the provided length`() = runTest { spaceRoomsFlow.value = listOf( aSpaceRoom(roomId = A_ROOM_ID), @@ -164,8 +153,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Reset removes all entries and add the provided ones`() = runTest { spaceRoomsFlow.value = listOf( aSpaceRoom(roomId = A_ROOM_ID), @@ -180,8 +168,7 @@ class RoomSummaryListProcessorTest { assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_3) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `When there is no replay cache SpaceListUpdateProcessor starts with an empty list`() = runTest { val spaceRoomsSharedFlow = MutableSharedFlow>(replay = 1) val processor = createProcessor( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt index 74cc97d66e..a0f8181c48 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/spaces/RustSpaceRoomListTest.kt @@ -23,15 +23,13 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.SpaceListUpdate import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList class RustSpaceRoomListTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `paginationStatusFlow emits values`() = runTest { val innerSpaceRoomList = FakeFfiSpaceRoomList( paginationStateResult = { SpaceRoomListPaginationState.Idle(false) } @@ -53,8 +51,7 @@ class RustSpaceRoomListTest { } } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `spaceRoomsFlow emits values`() = runTest { val innerSpaceRoomList = FakeFfiSpaceRoomList( paginationStateResult = { SpaceRoomListPaginationState.Idle(false) } @@ -76,8 +73,7 @@ class RustSpaceRoomListTest { } } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `paginate invokes paginate on the inner class`() = runTest { val paginateResult = lambdaRecorder { } val innerSpaceRoomList = FakeFfiSpaceRoomList( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt index ba7f640514..9b5af1ffb4 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt @@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.TimelineDiff @@ -31,8 +30,7 @@ class MatrixTimelineDiffProcessorTest { private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem()) - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Append adds new entries at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -44,8 +42,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PushBack adds a new entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -57,8 +54,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PushFront inserts a new entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -70,8 +66,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Set replaces an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -83,8 +78,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Insert inserts a new entry at the provided index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -97,8 +91,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Remove removes an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -110,8 +103,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PopBack removes an entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -122,8 +114,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `PopFront removes an entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -134,8 +125,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Clear removes all the entries`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -143,8 +133,7 @@ class MatrixTimelineDiffProcessorTest { assertThat(timelineItems.value).isEmpty() } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Truncate removes all entries after the provided length`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) @@ -155,8 +144,7 @@ class MatrixTimelineDiffProcessorTest { ) } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `Reset removes all entries and add the provided ones`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt index 1dde04575e..ab46e8aa5f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt @@ -30,13 +30,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.TimelineDiff import uniffi.matrix_sdk.RoomPaginationStatus import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline -@Ignore("JNA direct mapping has broken unit tests with FFI fakes") class RustTimelineTest { @Test fun `ensure that the timeline emits new loading item when pagination does not bring new events`() = runTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt index 4accf26e68..607f575a2d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt @@ -20,7 +20,6 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Ignore import org.junit.Test import org.matrix.rustcomponents.sdk.Timeline import org.matrix.rustcomponents.sdk.TimelineDiff @@ -28,8 +27,7 @@ import uniffi.matrix_sdk_ui.EventItemOrigin @OptIn(ExperimentalCoroutinesApi::class) class TimelineItemsSubscriberTest { - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `when timeline emits an empty list of items, the flow must emits an empty list`() = runTest { val timelineItems: MutableSharedFlow> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE) @@ -52,8 +50,7 @@ class TimelineItemsSubscriberTest { } } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `when timeline emits a non empty list of items, the flow must emits a non empty list`() = runTest { val timelineItems: MutableSharedFlow> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE) @@ -76,8 +73,7 @@ class TimelineItemsSubscriberTest { } } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `when timeline emits an item with SYNC origin`() = runTest { val timelineItems: MutableSharedFlow> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE) @@ -108,8 +104,7 @@ class TimelineItemsSubscriberTest { } } - @Ignore("JNA direct mapping has broken unit tests with FFI fakes") - @Test + @Test fun `multiple subscriptions does not have side effect`() = runTest { val timelineItemsSubscriber = createTimelineItemsSubscriber() timelineItemsSubscriber.subscribeIfNeeded() From 5d88a04ab0f5a194a45aa48014cafbb991e450cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Dec 2025 18:02:59 +0100 Subject: [PATCH 04/64] Add missing abstractions and fakes --- .../matrix/impl/RustMatrixClientFactory.kt | 14 ++++---- .../matrix/impl/storage/SqliteStoreBuilder.kt | 35 +++++++++++++++++++ .../storage/SqliteStoreBuilderProvider.kt | 23 ++++++++++++ .../matrix/impl/FakeFfiSqliteStoreBuilder.kt | 19 ++++++++++ .../impl/RustMatrixClientFactoryTest.kt | 2 ++ .../RustMatrixAuthenticationServiceTest.kt | 2 +- .../impl/fixtures/fakes/FakeFfiClient.kt | 3 ++ .../fixtures/fakes/FakeFfiClientBuilder.kt | 1 + .../matrix/impl/fixtures/fakes/FakeFfiRoom.kt | 6 ++++ .../roomlist/RoomSummaryListProcessorTest.kt | 2 ++ .../impl/storage/FakeSqliteStoreBuilder.kt | 18 ++++++++++ .../storage/FakeSqliteStoreBuilderProvider.kt | 16 +++++++++ 12 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilderProvider.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeFfiSqliteStoreBuilder.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilderProvider.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 4e335ae082..58e3485279 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.impl.paths.getSessionPaths import io.element.android.libraries.matrix.impl.proxy.ProxyProvider import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory +import io.element.android.libraries.matrix.impl.storage.SqliteStoreBuilderProvider import io.element.android.libraries.matrix.impl.util.anonymizedTokens import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionData @@ -36,7 +37,6 @@ import org.matrix.rustcomponents.sdk.RequestConfig import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.SlidingSyncVersion import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder -import org.matrix.rustcomponents.sdk.SqliteStoreBuilder import org.matrix.rustcomponents.sdk.use import timber.log.Timber import uniffi.matrix_sdk_base.MediaRetentionPolicy @@ -62,6 +62,7 @@ class RustMatrixClientFactory( private val featureFlagService: FeatureFlagService, private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, private val clientBuilderProvider: ClientBuilderProvider, + private val sqliteStoreBuilderProvider: SqliteStoreBuilderProvider, ) { private val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers) @@ -126,12 +127,11 @@ class RustMatrixClientFactory( slidingSyncType: ClientBuilderSlidingSync, ): ClientBuilder { return clientBuilderProvider.provide() - .sqliteStore( - SqliteStoreBuilder( - dataPath = sessionPaths.fileDirectory.absolutePath, - cachePath = sessionPaths.cacheDirectory.absolutePath, - ).passphrase(passphrase) - ) + .run { + sqliteStoreBuilderProvider.provide(sessionPaths) + .passphrase(passphrase) + .setupClientBuilder(this) + } .setSessionDelegate(sessionDelegate) .userAgent(userAgentProvider.provide()) .addRootCertificates(userCertificatesProvider.provides()) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt new file mode 100644 index 0000000000..7b5d9fb31c --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.storage + +import io.element.android.libraries.matrix.impl.paths.SessionPaths +import org.matrix.rustcomponents.sdk.ClientBuilder +import org.matrix.rustcomponents.sdk.SqliteStoreBuilder as SdkSqliteStoreBuilder + +interface SqliteStoreBuilder { + fun passphrase(passphrase: String?): SqliteStoreBuilder + fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder +} + +class RustSqliteStoreBuilder( + private val sessionPaths: SessionPaths, +) : SqliteStoreBuilder { + private var inner = SdkSqliteStoreBuilder( + dataPath = sessionPaths.fileDirectory.absolutePath, + cachePath = sessionPaths.cacheDirectory.absolutePath, + ) + + override fun passphrase(passphrase: String?): SqliteStoreBuilder { + inner = inner.passphrase(passphrase) + return this + } + + override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder { + return clientBuilder.sqliteStore(this.inner) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilderProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilderProvider.kt new file mode 100644 index 0000000000..29a30f3c56 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilderProvider.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.storage + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.matrix.impl.paths.SessionPaths + +interface SqliteStoreBuilderProvider { + fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder +} + +@ContributesBinding(AppScope::class) +class RustSqliteStoreBuilderProvider : SqliteStoreBuilderProvider { + override fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder { + return RustSqliteStoreBuilder(sessionPaths) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeFfiSqliteStoreBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeFfiSqliteStoreBuilder.kt new file mode 100644 index 0000000000..8e3240f5be --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeFfiSqliteStoreBuilder.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl + +import org.matrix.rustcomponents.sdk.NoHandle +import org.matrix.rustcomponents.sdk.SqliteStoreBuilder + +class FakeFfiSqliteStoreBuilder : SqliteStoreBuilder(NoHandle) { + override fun cacheSize(cacheSize: UInt?): SqliteStoreBuilder = this + override fun journalSizeLimit(limit: UInt?): SqliteStoreBuilder = this + override fun passphrase(passphrase: String?): SqliteStoreBuilder = this + override fun poolMaxSize(poolMaxSize: UInt?): SqliteStoreBuilder = this + override fun systemIsMemoryConstrained(): SqliteStoreBuilder = this +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt index b81ddd713d..a1b52d430a 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvider import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory +import io.element.android.libraries.matrix.impl.storage.FakeSqliteStoreBuilderProvider import io.element.android.libraries.network.useragent.SimpleUserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore @@ -55,4 +56,5 @@ fun TestScope.createRustMatrixClientFactory( featureFlagService = FakeFeatureFlagService(), timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), clientBuilderProvider = clientBuilderProvider, + sqliteStoreBuilderProvider = FakeSqliteStoreBuilderProvider(), ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index f8f792557d..f4ce7b1fdd 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -27,7 +27,7 @@ import org.junit.Test import java.io.File class RustMatrixAuthenticationServiceTest { - @Test + @Test fun `setHomeserver is successful`() = runTest { val sut = createRustMatrixAuthenticationService( clientBuilderProvider = FakeClientBuilderProvider( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt index a2227ab63a..3196cd1173 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt @@ -33,6 +33,7 @@ import org.matrix.rustcomponents.sdk.SyncServiceBuilder import org.matrix.rustcomponents.sdk.TaskHandle import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate import org.matrix.rustcomponents.sdk.UserProfile +import uniffi.matrix_sdk_base.MediaRetentionPolicy class FakeFfiClient( private val userId: String = A_USER_ID.value, @@ -88,5 +89,7 @@ class FakeFfiClient( return homeserverLoginDetailsResult() } + override suspend fun setMediaRetentionPolicy(policy: MediaRetentionPolicy) {} + override fun close() = closeResult() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt index 3ac1fefd7e..fa10a63e42 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt @@ -44,5 +44,6 @@ class FakeFfiClientBuilder( override fun enableShareHistoryOnInvite(enableShareHistoryOnInvite: Boolean): ClientBuilder = this override fun threadsEnabled(enabled: Boolean, threadSubscriptions: Boolean): ClientBuilder = this override fun sqliteStore(config: SqliteStoreBuilder): ClientBuilder = this + override fun inMemoryStore(): ClientBuilder = this override suspend fun build() = buildResult() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt index 86625c9737..7b60a9f4c2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.tests.testutils.lambda.lambdaError import org.matrix.rustcomponents.sdk.EventTimelineItem +import org.matrix.rustcomponents.sdk.LatestEventValue import org.matrix.rustcomponents.sdk.NoHandle import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomInfo @@ -25,6 +26,7 @@ class FakeFfiRoom( private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() }, private val leaveLambda: () -> Unit = { lambdaError() }, private val latestEventLambda: () -> EventTimelineItem? = { lambdaError() }, + private val newLatestEventLambda: () -> LatestEventValue = { lambdaError() }, private val suggestedRoleForUserLambda: (String) -> RoomMemberRole = { lambdaError() }, private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value), ) : Room(NoHandle) { @@ -56,6 +58,10 @@ class FakeFfiRoom( return suggestedRoleForUserLambda(userId) } + override suspend fun newLatestEvent(): LatestEventValue { + return newLatestEventLambda() + } + override fun close() { // No-op } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index bdc202d4fc..36d5b81f42 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -22,6 +22,7 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test +import org.matrix.rustcomponents.sdk.LatestEventValue import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate class RoomSummaryListProcessorTest { @@ -174,6 +175,7 @@ class RoomSummaryListProcessorTest { private fun aRustRoom(roomId: RoomId = A_ROOM_ID) = FakeFfiRoom( roomId = roomId, latestEventLambda = { null }, + newLatestEventLambda = { LatestEventValue.None } ) private fun TestScope.createProcessor() = RoomSummaryListProcessor( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt new file mode 100644 index 0000000000..2f12587f5a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.storage + +import org.matrix.rustcomponents.sdk.ClientBuilder + +class FakeSqliteStoreBuilder : SqliteStoreBuilder { + override fun passphrase(passphrase: String?): SqliteStoreBuilder = this + + override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder { + return clientBuilder + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilderProvider.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilderProvider.kt new file mode 100644 index 0000000000..b196604ca4 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilderProvider.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.storage + +import io.element.android.libraries.matrix.impl.paths.SessionPaths + +class FakeSqliteStoreBuilderProvider : SqliteStoreBuilderProvider { + override fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder { + return FakeSqliteStoreBuilder() + } +} From 0f66fa9ee47469c7b8ba78ef6861eda60e0c0b0b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:44:27 +0000 Subject: [PATCH 05/64] fix(deps): update camera to v1.5.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c5126345c..50a2804492 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ constraintlayout_compose = "1.1.1" lifecycle = "2.9.2" activity = "1.11.0" media3 = "1.8.0" -camera = "1.5.1" +camera = "1.5.2" work = "2.11.0" # Compose From a9afa5905346bb70dbbfa9bb8c379232ae0f5046 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 5 Dec 2025 09:33:21 +0100 Subject: [PATCH 06/64] Update detekt rules after updating compose.rules to version 0.5.1. --- tools/detekt/detekt.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml index cc99ecab5a..578e02ee33 100644 --- a/tools/detekt/detekt.yml +++ b/tools/detekt/detekt.yml @@ -224,27 +224,12 @@ comments: Compose: CompositionLocalAllowlist: active: true - # You can optionally define a list of CompositionLocals that are allowed here - allowedCompositionLocals: - - LocalCompoundColors - - LocalSnackbarDispatcher - - LocalCameraPositionState - - LocalMediaItemPresenterFactories - - LocalTimelineItemPresenterFactories - - LocalRoomMemberProfilesCache - - LocalMentionSpanUpdater - - LocalAnalyticsService - - LocalBuildMeta - - LocalUiTestMode - - LocalSdkIntVersionProvider CompositionLocalNaming: active: true ContentEmitterReturningValues: active: true # You can optionally add your own composables here # contentEmitters: MyComposable,MyOtherComposable - ModifierComposable: - active: true ModifierMissing: active: true ModifierReused: @@ -267,8 +252,6 @@ Compose: active: true PreviewPublic: active: true - # You can optionally disable that only previews with @PreviewParameter are flagged - previewPublicOnlyIfParams: false RememberMissing: active: true UnstableCollections: From 72b3decf4cb9da4ee18af5146068f8156008d3d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 5 Dec 2025 09:45:23 +0100 Subject: [PATCH 07/64] Detekt: enable rule `exceptions.SwallowedException` and fix existing issue. --- .../lockscreen/impl/pin/DefaultPinCodeManager.kt | 2 +- .../messages/impl/timeline/debug/EventDebugInfoView.kt | 2 +- .../libraries/androidutils/browser/ChromeCustomTab.kt | 2 +- .../android/libraries/androidutils/hash/Hash.kt | 2 +- .../libraries/androidutils/system/SystemUtils.kt | 10 +++++----- .../io/element/android/libraries/core/hash/Hash.kt | 2 +- .../io/element/android/libraries/core/uri/UrlUtils.kt | 2 +- .../impl/FullScreenIntentPermissionsPresenter.kt | 2 +- .../android/libraries/matrix/api/roomlist/RoomList.kt | 2 +- .../libraries/matrix/impl/room/RoomSyncSubscriber.kt | 2 +- .../matrix/impl/roomlist/RoomListExtensions.kt | 2 +- .../libraries/matrix/impl/widget/RustWidgetDriver.kt | 2 +- .../push/impl/troubleshoot/PushLoopbackTest.kt | 2 +- .../libraries/pushproviders/firebase/FirebaseStore.kt | 2 +- .../io/element/android/tests/testutils/LongTask.kt | 2 +- tools/detekt/detekt.yml | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt index 1ebf00dd10..091432044a 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt @@ -71,7 +71,7 @@ class DefaultPinCodeManager( lockScreenStore.onWrongPin() } } - } catch (failure: Throwable) { + } catch (_: Throwable) { false } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/debug/EventDebugInfoView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/debug/EventDebugInfoView.kt index 8a19b88b26..3b0448ddb3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/debug/EventDebugInfoView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/debug/EventDebugInfoView.kt @@ -112,7 +112,7 @@ fun EventDebugInfoView( private fun prettyJSON(maybeJSON: String): String { return try { JSONObject(maybeJSON).toString(2) - } catch (e: JSONException) { + } catch (_: JSONException) { // Prefer not pretty-printing over crashing if the data is not actually JSON maybeJSON } diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ChromeCustomTab.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ChromeCustomTab.kt index 198518466b..6650f70ecb 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ChromeCustomTab.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ChromeCustomTab.kt @@ -60,7 +60,7 @@ fun Activity.openUrlInChromeCustomTab( }) } .launchUrl(this, url.toUri()) - } catch (activityNotFoundException: ActivityNotFoundException) { + } catch (_: ActivityNotFoundException) { openUrlInExternalApp(url) } } diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/hash/Hash.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/hash/Hash.kt index 211b60a602..b699054ff0 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/hash/Hash.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/hash/Hash.kt @@ -20,7 +20,7 @@ fun String.hash() = try { digest.digest() .joinToString("") { String.format(Locale.ROOT, "%02X", it) } .lowercase(Locale.ROOT) -} catch (exc: Exception) { +} catch (_: Exception) { // Should not happen, but just in case hashCode().toString() } diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt index 354b68a32b..861aca032d 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt @@ -32,7 +32,7 @@ fun Context.getApplicationLabel(packageName: String): String { return try { val ai = packageManager.getApplicationInfoCompat(packageName, 0) packageManager.getApplicationLabel(ai).toString() - } catch (e: PackageManager.NameNotFoundException) { + } catch (_: PackageManager.NameNotFoundException) { packageName } } @@ -96,7 +96,7 @@ fun Context.startNotificationSettingsIntent( } else { startActivity(intent) } - } catch (activityNotFoundException: ActivityNotFoundException) { + } catch (_: ActivityNotFoundException) { toast(noActivityFoundMessage) } } @@ -112,7 +112,7 @@ fun Context.openAppSettingsPage( data = Uri.fromParts("package", packageName, null) } ) - } catch (activityNotFoundException: ActivityNotFoundException) { + } catch (_: ActivityNotFoundException) { toast(noActivityFoundMessage) } } @@ -126,7 +126,7 @@ fun Context.startInstallFromSourceIntent( .setData("package:$packageName".toUri()) try { activityResultLauncher.launch(intent) - } catch (activityNotFoundException: ActivityNotFoundException) { + } catch (_: ActivityNotFoundException) { toast(noActivityFoundMessage) } } @@ -157,7 +157,7 @@ fun Context.startSharePlainTextIntent( } else { startActivity(intent) } - } catch (activityNotFoundException: ActivityNotFoundException) { + } catch (_: ActivityNotFoundException) { toast(noActivityFoundMessage) } } diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/hash/Hash.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/hash/Hash.kt index 944889bdcb..4a9af95bd1 100644 --- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/hash/Hash.kt +++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/hash/Hash.kt @@ -21,7 +21,7 @@ fun String.md5() = try { digest.digest() .joinToString("") { String.format(locale, "%02X", it) } .lowercase(locale) -} catch (exc: Exception) { +} catch (_: Exception) { // Should not happen, but just in case hashCode().toString() } diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/uri/UrlUtils.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/uri/UrlUtils.kt index a086a6fba5..666ee1d7ab 100644 --- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/uri/UrlUtils.kt +++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/uri/UrlUtils.kt @@ -14,7 +14,7 @@ fun String.isValidUrl(): Boolean { return try { URI(this).toURL() true - } catch (t: Throwable) { + } catch (_: Throwable) { false } } diff --git a/libraries/fullscreenintent/impl/src/main/kotlin/io/element/android/libraries/fullscreenintent/impl/FullScreenIntentPermissionsPresenter.kt b/libraries/fullscreenintent/impl/src/main/kotlin/io/element/android/libraries/fullscreenintent/impl/FullScreenIntentPermissionsPresenter.kt index ed406e75ff..d4a3e75d1a 100644 --- a/libraries/fullscreenintent/impl/src/main/kotlin/io/element/android/libraries/fullscreenintent/impl/FullScreenIntentPermissionsPresenter.kt +++ b/libraries/fullscreenintent/impl/src/main/kotlin/io/element/android/libraries/fullscreenintent/impl/FullScreenIntentPermissionsPresenter.kt @@ -88,7 +88,7 @@ class FullScreenIntentPermissionsPresenter( "package:${buildMeta.applicationId}".toUri() ) externalIntentLauncher.launch(intent) - } catch (e: ActivityNotFoundException) { + } catch (_: ActivityNotFoundException) { val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) .putExtra(Settings.EXTRA_APP_PACKAGE, buildMeta.applicationId) externalIntentLauncher.launch(intent) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt index d03a9677e3..a0d092596a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt @@ -65,7 +65,7 @@ suspend fun RoomList.awaitLoaded(timeout: Duration = Duration.INFINITE) { it is RoomList.LoadingState.Loaded } } - } catch (timeoutException: TimeoutCancellationException) { + } catch (_: TimeoutCancellationException) { Timber.d("awaitAllRoomsAreLoaded: no response after $timeout") } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt index 6a6b45b7a7..724e3f62f0 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt @@ -34,7 +34,7 @@ class RoomSyncSubscriber( } subscribedRoomIds.add(roomId) } catch (exception: Exception) { - Timber.e("Failed to subscribe to room $roomId") + Timber.e(exception, "Failed to subscribe to room $roomId") } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt index 84e759040d..ae241e9c02 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt @@ -48,7 +48,7 @@ fun RoomListInterface.loadingStateFlow(): Flow = try { send(result.state) } catch (exception: Exception) { - Timber.d("loadingStateFlow() initialState failed.") + Timber.d(exception, "loadingStateFlow() initialState failed.") } result.stateStream }.catch { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt index 1d1824d240..b908082ab6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/RustWidgetDriver.kt @@ -62,7 +62,7 @@ class RustWidgetDriver( override suspend fun send(message: String) { try { driverAndHandle.handle.send(message) - } catch (e: IllegalStateException) { + } catch (_: IllegalStateException) { // The handle is closed, ignore } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt index 64b8f98f5b..91ac1ca0ee 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt @@ -56,7 +56,7 @@ class PushLoopbackTest( } val testPushResult = try { pushService.testPush(sessionId) - } catch (pusherRejected: PushGatewayFailure.PusherRejected) { + } catch (_: PushGatewayFailure.PusherRejected) { val hasQuickFix = pushService.getCurrentPushProvider(sessionId)?.canRotateToken() == true delegate.updateState( description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_1), diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt index 2d3f9dce39..1f6a4709cc 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt @@ -40,7 +40,7 @@ class SharedPreferencesFirebaseStore( if (k == PREFS_KEY_FCM_TOKEN) { try { flow.value = getFcmToken() - } catch (e: Exception) { + } catch (_: Exception) { flow.value = null } } diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/LongTask.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/LongTask.kt index 5e3367fcc4..bbaa1cf741 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/LongTask.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/LongTask.kt @@ -34,7 +34,7 @@ suspend fun awaitWithLatch(timeout: Duration = 300.milliseconds, block: (Complet withTimeout(timeout) { latch.also(block).await() } - } catch (exception: TimeoutCancellationException) { + } catch (_: TimeoutCancellationException) { latch.complete(Unit) } } diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml index 578e02ee33..552b46755e 100644 --- a/tools/detekt/detekt.yml +++ b/tools/detekt/detekt.yml @@ -150,7 +150,7 @@ exceptions: TooGenericExceptionCaught: active: false SwallowedException: - active: false + active: true ThrowingExceptionsWithoutMessageOrCause: active: true TooGenericExceptionThrown: From 096b8768ea9331850e27ddf28383bacdb6bfb6f9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 5 Dec 2025 09:48:26 +0100 Subject: [PATCH 08/64] Fix warning "Throwable should be first argument" --- .../io/element/android/libraries/matrix/impl/util/Error.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Error.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Error.kt index 0a1f45d1d1..70fea1287e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Error.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Error.kt @@ -14,10 +14,10 @@ import timber.log.Timber fun logError(throwable: Throwable) { when (throwable) { is ClientException.Generic -> { - Timber.e("Error ${throwable.msg}", throwable) + Timber.e(throwable, "Error ${throwable.msg}") } else -> { - Timber.e("Error", throwable) + Timber.e(throwable, "Error") } } } From f745f2ca1e1622f90a395f1e52063465929e9f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Dec 2025 11:05:19 +0100 Subject: [PATCH 09/64] Add `SessionRestorationException`, make sure `ClientException` can expose it through the `cause` property --- .../api/auth/SessionRestorationException.kt | 15 +++++++++++++++ .../matrix/api/exception/ClientException.kt | 8 ++++---- .../impl/auth/RustMatrixAuthenticationService.kt | 5 +++-- .../impl/encryption/RecoveryExceptionMapper.kt | 2 +- .../matrix/impl/exception/ClientException.kt | 5 +++-- 5 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/SessionRestorationException.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/SessionRestorationException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/SessionRestorationException.kt new file mode 100644 index 0000000000..bf6f50cab5 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/SessionRestorationException.kt @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.auth + +import io.element.android.libraries.matrix.api.core.SessionId + +sealed class SessionRestorationException(message: String, cause: Throwable? = null) : Exception(message, cause) { + data class MissingSession(val sessionId: SessionId) : SessionRestorationException("Session with id $sessionId not found") + class InvalidToken : SessionRestorationException("Access token is invalid or expired") +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt index 35acec43ca..30f77e7b5e 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt @@ -8,10 +8,10 @@ package io.element.android.libraries.matrix.api.exception -sealed class ClientException(message: String, val details: String?) : Exception(message) { - class Generic(message: String, details: String?) : ClientException(message, details) - class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?) : ClientException(message, details) - class Other(message: String) : ClientException(message, null) +sealed class ClientException(message: String, val details: String?, cause: Throwable? = null) : Exception(message, cause) { + class Generic(message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause) + class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause) + class Other(message: String, cause: Throwable? = null) : ClientException(message, null, cause) } fun ClientException.isNetworkError(): Boolean { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index df4333654b..97719bed36 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OidcPrompt +import io.element.android.libraries.matrix.api.auth.SessionRestorationException import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep @@ -91,10 +92,10 @@ class RustMatrixAuthenticationService( } rustMatrixClientFactory.create(sessionData) } else { - error("Token is not valid") + throw SessionRestorationException.InvalidToken() } } else { - error("No session to restore with id $sessionId") + throw SessionRestorationException.MissingSession(sessionId) } }.mapFailure { failure -> failure.mapClientException() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt index 76a72cd65b..f5d1a4253b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt @@ -30,7 +30,7 @@ fun Throwable.mapRecoveryException(): RecoveryException { } } else -> RecoveryException.Client( - ClientException.Other("Unknown error") + ClientException.Other("Unknown error", this) ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt index 668e55e9bf..eefa6d4986 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt @@ -15,15 +15,16 @@ fun Throwable.mapClientException(): ClientException { return when (this) { is RustClientException -> { when (this) { - is RustClientException.Generic -> ClientException.Generic(msg, details) + is RustClientException.Generic -> ClientException.Generic(message = msg, details = details, cause = this) is RustClientException.MatrixApi -> ClientException.MatrixApi( kind = kind.map(), code = code, message = msg, details = details, + cause = this, ) } } - else -> ClientException.Other(message ?: "Unknown error") + else -> ClientException.Other(message ?: "Unknown error", this) } } From 754c0781f9e01298866b3590bc47a5018678070d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Dec 2025 11:06:14 +0100 Subject: [PATCH 10/64] Don't re-schedule notification fetches if the cause of the failure is `SessionRestorationException`, since that means it'll most likely fail again --- .../matrix/api/exception/ClientException.kt | 6 +++++- .../DefaultNotifiableEventResolver.kt | 2 +- .../impl/workmanager/FetchNotificationsWorker.kt | 15 +++++++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt index 30f77e7b5e..52b1577bf0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt @@ -10,7 +10,11 @@ package io.element.android.libraries.matrix.api.exception sealed class ClientException(message: String, val details: String?, cause: Throwable? = null) : Exception(message, cause) { class Generic(message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause) - class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause) + class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?, cause: Throwable? = null) : ClientException( + message = message, + details = details, + cause = cause + ) class Other(message: String, cause: Throwable? = null) : ClientException(message, null, cause) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt index 763747d7ce..e3d0f21d03 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt @@ -99,7 +99,7 @@ class DefaultNotifiableEventResolver( ): ResolvePushEventsResult { Timber.d("Queueing notifications: $notificationEventRequests") val client = matrixClientProvider.getOrRestore(sessionId).getOrElse { - return Result.failure(IllegalStateException("Couldn't get or restore client for session $sessionId")) + return Result.failure(it) } val ids = notificationEventRequests.groupBy { it.roomId } .mapValues { (_, requests) -> diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt index be8db1a11e..ccc0a02749 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt @@ -22,6 +22,7 @@ import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.auth.SessionRestorationException import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.push.api.push.NotificationEventRequest import io.element.android.libraries.push.api.push.SyncOnNotifiableEvent @@ -63,9 +64,9 @@ class FetchNotificationsWorker( return@withContext Result.retry() } - val failedSyncForSessions = mutableSetOf() + val failedSyncForSessions = mutableMapOf() - val groupedRequests = requests.groupBy { it.sessionId } + val groupedRequests = requests.groupBy { it.sessionId }.toMutableMap() for ((sessionId, notificationRequests) in groupedRequests) { Timber.d("Processing notification requests for session $sessionId") eventResolver.resolveEvents(sessionId, notificationRequests) @@ -75,7 +76,7 @@ class FetchNotificationsWorker( (queue.results as MutableSharedFlow).emit(requests to result) }, onFailure = { - failedSyncForSessions += sessionId + failedSyncForSessions[sessionId] = it Timber.e(it, "Failed to resolve notification events for session $sessionId") } ) @@ -83,7 +84,13 @@ class FetchNotificationsWorker( // If there were failures for whole sessions, we retry all their requests if (failedSyncForSessions.isNotEmpty()) { - for (failedSessionId in failedSyncForSessions) { + @Suppress("LoopWithTooManyJumpStatements") + for ((failedSessionId, exception) in failedSyncForSessions) { + if (exception.cause is SessionRestorationException) { + Timber.e(exception, "Session $failedSessionId could not be restored, not retrying notification fetching") + groupedRequests.remove(failedSessionId) + continue + } val requestsToRetry = groupedRequests[failedSessionId] ?: continue Timber.d("Re-scheduling ${requestsToRetry.size} failed notification requests for session $failedSessionId") workManagerScheduler.submit( From 221e18d1399e48667ce7227f83c71bf295e001ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Dec 2025 12:07:08 +0100 Subject: [PATCH 11/64] Test `DefaultWorkManagerScheduler` --- .../test/InMemorySessionStore.kt | 4 +- libraries/workmanager/impl/build.gradle.kts | 4 + .../impl/DefaultWorkManagerScheduler.kt | 30 ++++- .../workmanager/impl/WorkManagerModule.kt | 29 +++++ .../impl/DefaultWorkManagerSchedulerTest.kt | 120 ++++++++++++++++++ 5 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/WorkManagerModule.kt create mode 100644 libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt index 6cab993da1..05e58ac623 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemorySessionStore.kt @@ -81,8 +81,6 @@ class InMemorySessionStore( } override suspend fun removeSession(sessionId: String) { - val currentList = sessionDataListFlow.value.toMutableList() - currentList.removeAll { it.userId == sessionId } - sessionDataListFlow.value = currentList + sessionDataListFlow.value = sessionDataListFlow.value.filter { it.userId != sessionId } } } diff --git a/libraries/workmanager/impl/build.gradle.kts b/libraries/workmanager/impl/build.gradle.kts index ebf0f906bc..878edb6fe2 100644 --- a/libraries/workmanager/impl/build.gradle.kts +++ b/libraries/workmanager/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright (c) 2025 Element Creations Ltd. @@ -22,4 +23,7 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.matrix.api) implementation(projects.libraries.di) + + testCommonDependencies(libs, false) + testImplementation(projects.libraries.sessionStorage.test) } diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index 6943c1432e..c80735c675 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -8,23 +8,45 @@ package io.element.android.libraries.workmanager.impl -import android.content.Context import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.core.coroutine.withPreviousValue +import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.workmanager.api.WorkManagerRequest import io.element.android.libraries.workmanager.api.WorkManagerRequestType import io.element.android.libraries.workmanager.api.WorkManagerScheduler import io.element.android.libraries.workmanager.api.workManagerTag +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import timber.log.Timber @ContributesBinding(AppScope::class) class DefaultWorkManagerScheduler( - @ApplicationContext private val context: Context, + lazyWorkManager: Lazy, + @AppCoroutineScope private val appCoroutineScope: CoroutineScope, + sessionStore: SessionStore, ) : WorkManagerScheduler { - private val workManager by lazy { WorkManager.getInstance(context) } + private val workManager by lazyWorkManager + + init { + // Observe session removals to cancel associated work automatically + sessionStore.sessionsFlow() + .map { sessions -> sessions.map { SessionId(it.userId) } } + .withPreviousValue() + .map { (prev, new) -> prev.orEmpty() - new.toSet() } + .onEach { removedSessions -> + for (sessionId in removedSessions) { + Timber.d("Session removed for userId: $sessionId, cancelling associated workmanager requests") + cancel(sessionId) + } + } + .launchIn(appCoroutineScope) + } override fun submit(workManagerRequest: WorkManagerRequest) { workManagerRequest.build().fold( diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/WorkManagerModule.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/WorkManagerModule.kt new file mode 100644 index 0000000000..7df9e7f431 --- /dev/null +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/WorkManagerModule.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.workmanager.impl + +import android.content.Context +import androidx.work.WorkManager +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.BindingContainer +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.di.annotations.ApplicationContext + +@BindingContainer +@ContributesTo(AppScope::class) +object WorkManagerModule { + @Provides + @SingleIn(AppScope::class) + fun providesWorkManager( + @ApplicationContext context: Context, + ): WorkManager { + return WorkManager.getInstance(context) + } +} diff --git a/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt b/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt new file mode 100644 index 0000000000..5ecf0c4a1f --- /dev/null +++ b/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.workmanager.impl + +import androidx.work.WorkManager +import androidx.work.WorkRequest +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.sessionstorage.test.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.libraries.workmanager.api.WorkManagerRequest +import io.element.android.libraries.workmanager.api.WorkManagerRequestType +import io.element.android.libraries.workmanager.api.workManagerTag +import io.mockk.every +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class DefaultWorkManagerSchedulerTest { + @Test + fun `starts observing sessions on init to remove work for logged out sessions`() = runTest { + val sessionId = "@session1:matrix.org" + val sessionStore = InMemorySessionStore(initialList = listOf(aSessionData(sessionId = sessionId))) + + val workManager = spyk() + + DefaultWorkManagerScheduler( + lazyWorkManager = lazy { workManager }, + appCoroutineScope = backgroundScope, + sessionStore = sessionStore, + ) + + // We have a single initial session + assertThat(sessionStore.numberOfSessions()).isEqualTo(1) + + runCurrent() + + // We remove the session + sessionStore.removeSession(sessionId) + + runCurrent() + + // The session is now gone and work associated with the session is cancelled + assertThat(sessionStore.numberOfSessions()).isEqualTo(0) + verify { workManager.cancelAllWorkByTag("notifications-$sessionId") } + } + + @Test + fun `submit builds the request and enqueues it`() = runTest { + val sessionStore = InMemorySessionStore() + val workManager = spyk() + + val scheduler = DefaultWorkManagerScheduler( + lazyWorkManager = lazy { workManager }, + appCoroutineScope = backgroundScope, + sessionStore = sessionStore, + ) + + scheduler.submit(FakeWorkManagerRequest()) + + verify { workManager.enqueue(any>()) } + } + + @Test + fun `submit won't do anything if building the work request fails`() = runTest { + val sessionStore = InMemorySessionStore() + val workManager = spyk() + + val scheduler = DefaultWorkManagerScheduler( + lazyWorkManager = lazy { workManager }, + appCoroutineScope = backgroundScope, + sessionStore = sessionStore, + ) + + scheduler.submit(FakeWorkManagerRequest(result = Result.failure(IllegalStateException("Test error")))) + + verify(exactly = 0) { workManager.enqueue(any>()) } + } + + @Test + fun `cancel will cancel all pending work for a session id`() = runTest { + val sessionStore = InMemorySessionStore() + val workManager = spyk() + + val scheduler = DefaultWorkManagerScheduler( + lazyWorkManager = lazy { workManager }, + appCoroutineScope = backgroundScope, + sessionStore = sessionStore, + ) + + val sessionId = SessionId("@alice:matrix.org") + val tagToRemove = workManagerTag(sessionId, WorkManagerRequestType.NOTIFICATION_SYNC) + val mockSessionA = mockk { + every { tags } returns setOf(tagToRemove) + } + scheduler.submit(FakeWorkManagerRequest(result = Result.success(listOf(mockSessionA)))) + + scheduler.cancel(sessionId) + + verify { workManager.cancelAllWorkByTag(tagToRemove) } + } +} + +private class FakeWorkManagerRequest( + private val result: Result> = Result.success(listOf()), +) : WorkManagerRequest { + override fun build(): Result> { + return result + } +} From 7eae3a16aec9c70690404d18ef079827d7689980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 5 Dec 2025 17:07:54 +0100 Subject: [PATCH 12/64] Use `SessionObserver` instead of `SessionStore` to observe sessions --- .../impl/DefaultWorkManagerScheduler.kt | 28 ++++++------------ .../impl/DefaultWorkManagerSchedulerTest.kt | 29 +++++-------------- 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index c80735c675..345604390b 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -11,41 +11,31 @@ package io.element.android.libraries.workmanager.impl import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.core.coroutine.withPreviousValue -import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.sessionstorage.api.observer.SessionListener +import io.element.android.libraries.sessionstorage.api.observer.SessionObserver import io.element.android.libraries.workmanager.api.WorkManagerRequest import io.element.android.libraries.workmanager.api.WorkManagerRequestType import io.element.android.libraries.workmanager.api.WorkManagerScheduler import io.element.android.libraries.workmanager.api.workManagerTag -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach import timber.log.Timber @ContributesBinding(AppScope::class) class DefaultWorkManagerScheduler( lazyWorkManager: Lazy, - @AppCoroutineScope private val appCoroutineScope: CoroutineScope, - sessionStore: SessionStore, + sessionObserver: SessionObserver, ) : WorkManagerScheduler { private val workManager by lazyWorkManager init { // Observe session removals to cancel associated work automatically - sessionStore.sessionsFlow() - .map { sessions -> sessions.map { SessionId(it.userId) } } - .withPreviousValue() - .map { (prev, new) -> prev.orEmpty() - new.toSet() } - .onEach { removedSessions -> - for (sessionId in removedSessions) { - Timber.d("Session removed for userId: $sessionId, cancelling associated workmanager requests") - cancel(sessionId) - } + sessionObserver.addListener(object : SessionListener { + override suspend fun onSessionDeleted(userId: String, wasLastSession: Boolean) { + val sessionId = SessionId(userId) + Timber.d("Session deleted for userId: $userId, cancelling associated workmanager requests") + cancel(sessionId) } - .launchIn(appCoroutineScope) + }) } override fun submit(workManagerRequest: WorkManagerRequest) { diff --git a/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt b/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt index 5ecf0c4a1f..b4f964ed12 100644 --- a/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt +++ b/libraries/workmanager/impl/src/test/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerSchedulerTest.kt @@ -9,10 +9,8 @@ package io.element.android.libraries.workmanager.impl import androidx.work.WorkManager import androidx.work.WorkRequest -import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.sessionstorage.test.InMemorySessionStore -import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.libraries.sessionstorage.test.observer.FakeSessionObserver import io.element.android.libraries.workmanager.api.WorkManagerRequest import io.element.android.libraries.workmanager.api.WorkManagerRequestType import io.element.android.libraries.workmanager.api.workManagerTag @@ -30,40 +28,31 @@ class DefaultWorkManagerSchedulerTest { @Test fun `starts observing sessions on init to remove work for logged out sessions`() = runTest { val sessionId = "@session1:matrix.org" - val sessionStore = InMemorySessionStore(initialList = listOf(aSessionData(sessionId = sessionId))) + val sessionObserver = FakeSessionObserver() val workManager = spyk() DefaultWorkManagerScheduler( lazyWorkManager = lazy { workManager }, - appCoroutineScope = backgroundScope, - sessionStore = sessionStore, + sessionObserver = sessionObserver, ) - // We have a single initial session - assertThat(sessionStore.numberOfSessions()).isEqualTo(1) - - runCurrent() - // We remove the session - sessionStore.removeSession(sessionId) + sessionObserver.onSessionDeleted(sessionId) runCurrent() // The session is now gone and work associated with the session is cancelled - assertThat(sessionStore.numberOfSessions()).isEqualTo(0) verify { workManager.cancelAllWorkByTag("notifications-$sessionId") } } @Test fun `submit builds the request and enqueues it`() = runTest { - val sessionStore = InMemorySessionStore() val workManager = spyk() val scheduler = DefaultWorkManagerScheduler( lazyWorkManager = lazy { workManager }, - appCoroutineScope = backgroundScope, - sessionStore = sessionStore, + sessionObserver = FakeSessionObserver(), ) scheduler.submit(FakeWorkManagerRequest()) @@ -73,13 +62,11 @@ class DefaultWorkManagerSchedulerTest { @Test fun `submit won't do anything if building the work request fails`() = runTest { - val sessionStore = InMemorySessionStore() val workManager = spyk() val scheduler = DefaultWorkManagerScheduler( lazyWorkManager = lazy { workManager }, - appCoroutineScope = backgroundScope, - sessionStore = sessionStore, + sessionObserver = FakeSessionObserver(), ) scheduler.submit(FakeWorkManagerRequest(result = Result.failure(IllegalStateException("Test error")))) @@ -89,13 +76,11 @@ class DefaultWorkManagerSchedulerTest { @Test fun `cancel will cancel all pending work for a session id`() = runTest { - val sessionStore = InMemorySessionStore() val workManager = spyk() val scheduler = DefaultWorkManagerScheduler( lazyWorkManager = lazy { workManager }, - appCoroutineScope = backgroundScope, - sessionStore = sessionStore, + sessionObserver = FakeSessionObserver(), ) val sessionId = SessionId("@alice:matrix.org") From f15a236c108465ba975d8869ea4032cc4253f302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 5 Dec 2025 17:08:53 +0100 Subject: [PATCH 13/64] Make `DefaultWorkManagerScheduler` a singleton sin it now has an observer that should be a singleton --- .../libraries/workmanager/impl/DefaultWorkManagerScheduler.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index 345604390b..e5bd67c604 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.workmanager.impl import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.observer.SessionListener import io.element.android.libraries.sessionstorage.api.observer.SessionObserver @@ -21,6 +22,7 @@ import io.element.android.libraries.workmanager.api.workManagerTag import timber.log.Timber @ContributesBinding(AppScope::class) +@SingleIn(AppScope::class) class DefaultWorkManagerScheduler( lazyWorkManager: Lazy, sessionObserver: SessionObserver, From f4c8bbd8adbc7863cfa32730c6fb9755a238a104 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:34:18 +0000 Subject: [PATCH 14/64] Sync Strings from Localazy --- .../src/main/res/values-et/translations.xml | 4 + .../src/main/res/values-sk/translations.xml | 30 +- .../src/main/res/values-et/translations.xml | 5 + .../src/main/res/values-fr/translations.xml | 4 + .../src/main/res/values-sk/translations.xml | 60 +- .../impl/src/main/res/values/localazy.xml | 4 +- .../impl/src/main/res/values/localazy.xml | 2 +- .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-fr/translations.xml | 4 + .../src/main/res/values-sk/translations.xml | 28 +- .../impl/src/main/res/values/localazy.xml | 2 + .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values-be/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-cy/translations.xml | 1 + .../src/main/res/values-da/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-es/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 10 + .../src/main/res/values-eu/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 1 + .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-fr/translations.xml | 8 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-in/translations.xml | 1 + .../src/main/res/values-it/translations.xml | 1 + .../src/main/res/values-ka/translations.xml | 1 + .../src/main/res/values-ko/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 1 + .../main/res/values-pt-rBR/translations.xml | 1 + .../src/main/res/values-pt/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-sk/translations.xml | 12 + .../src/main/res/values-sv/translations.xml | 1 + .../src/main/res/values-tr/translations.xml | 1 + .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-ur/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 1 + .../src/main/res/values/localazy.xml | 4 + ...ll.impl.create_CreatePollView_Day_2_de.png | 4 +- ...itprofile_EditUserProfileView_Day_0_de.png | 4 +- ...itprofile_EditUserProfileView_Day_1_de.png | 4 +- ...itprofile_EditUserProfileView_Day_2_de.png | 3 + ...s.impl.roles_ChangeRolesView_Day_10_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_1_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_2_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_3_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_4_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_6_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_7_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_8_de.png | 4 +- ...ns.impl.roles_ChangeRolesView_Day_9_de.png | 4 +- ..._PendingMemberRowWithLongName_Day_0_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_0_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_1_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_2_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_3_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_4_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_5_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_6_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_7_de.png | 3 - ...impl.edit_RoomDetailsEditView_Day_8_de.png | 3 - ...bers_RoomMemberListViewBanned_Day_0_de.png | 3 - ...bers_RoomMemberListViewBanned_Day_1_de.png | 3 - ...bers_RoomMemberListViewBanned_Day_2_de.png | 3 - ...pl.members_RoomMemberListView_Day_0_de.png | 4 +- ...pl.members_RoomMemberListView_Day_1_de.png | 4 +- ...pl.members_RoomMemberListView_Day_2_de.png | 4 +- ...pl.members_RoomMemberListView_Day_3_de.png | 4 +- ...pl.members_RoomMemberListView_Day_4_de.png | 4 +- ...pl.members_RoomMemberListView_Day_5_de.png | 4 +- ...pl.members_RoomMemberListView_Day_6_de.png | 3 + ...pl.members_RoomMemberListView_Day_7_de.png | 3 - ...pl.members_RoomMemberListView_Day_8_de.png | 3 - ...pl.members_RoomMemberListView_Day_9_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_0_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_1_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_2_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_3_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_4_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_5_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_6_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_7_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_8_de.png | 3 - ...rivacy_SecurityAndPrivacyViewDark_9_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_0_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_1_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_2_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_3_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_4_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_5_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_6_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_7_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_8_de.png | 3 - ...ivacy_SecurityAndPrivacyViewLight_9_de.png | 3 - ...edit.impl_RoomDetailsEditView_Day_0_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_1_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_2_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_3_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_4_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_5_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_6_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_7_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_8_de.png | 3 + ...edit.impl_RoomDetailsEditView_Day_9_de.png | 3 + ...impl_RoomMemberModerationView_Day_0_de.png | 4 +- ...impl_RoomMemberModerationView_Day_1_de.png | 4 +- ...impl_RoomMemberModerationView_Day_2_de.png | 4 +- ...impl_RoomMemberModerationView_Day_3_de.png | 4 +- ...maddress_EditRoomAddressView_Day_0_de.png} | 0 ...maddress_EditRoomAddressView_Day_1_de.png} | 0 ...maddress_EditRoomAddressView_Day_2_de.png} | 0 ...maddress_EditRoomAddressView_Day_3_de.png} | 0 ...maddress_EditRoomAddressView_Day_4_de.png} | 0 ...l.root_SecurityAndPrivacyViewDark_0_de.png | 3 + ....root_SecurityAndPrivacyViewDark_10_de.png | 3 + ....root_SecurityAndPrivacyViewDark_11_de.png | 3 + ....root_SecurityAndPrivacyViewDark_12_de.png | 3 + ....root_SecurityAndPrivacyViewDark_13_de.png | 3 + ....root_SecurityAndPrivacyViewDark_14_de.png | 3 + ....root_SecurityAndPrivacyViewDark_15_de.png | 3 + ....root_SecurityAndPrivacyViewDark_16_de.png | 3 + ....root_SecurityAndPrivacyViewDark_17_de.png | 3 + ....root_SecurityAndPrivacyViewDark_18_de.png | 3 + ....root_SecurityAndPrivacyViewDark_19_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_1_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_2_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_3_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_4_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_5_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_6_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_7_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_8_de.png | 3 + ...l.root_SecurityAndPrivacyViewDark_9_de.png | 3 + ....root_SecurityAndPrivacyViewLight_0_de.png | 3 + ...root_SecurityAndPrivacyViewLight_10_de.png | 3 + ...root_SecurityAndPrivacyViewLight_11_de.png | 3 + ...root_SecurityAndPrivacyViewLight_12_de.png | 3 + ...root_SecurityAndPrivacyViewLight_13_de.png | 3 + ...root_SecurityAndPrivacyViewLight_14_de.png | 3 + ...root_SecurityAndPrivacyViewLight_15_de.png | 3 + ...root_SecurityAndPrivacyViewLight_16_de.png | 3 + ...root_SecurityAndPrivacyViewLight_17_de.png | 3 + ...root_SecurityAndPrivacyViewLight_18_de.png | 3 + ...root_SecurityAndPrivacyViewLight_19_de.png | 3 + ....root_SecurityAndPrivacyViewLight_1_de.png | 3 + ....root_SecurityAndPrivacyViewLight_2_de.png | 3 + ....root_SecurityAndPrivacyViewLight_3_de.png | 3 + ....root_SecurityAndPrivacyViewLight_4_de.png | 3 + ....root_SecurityAndPrivacyViewLight_5_de.png | 3 + ....root_SecurityAndPrivacyViewLight_6_de.png | 3 + ....root_SecurityAndPrivacyViewLight_7_de.png | 3 + ....root_SecurityAndPrivacyViewLight_8_de.png | 3 + ....root_SecurityAndPrivacyViewLight_9_de.png | 3 + ...nts.dialogs_SaveChangesDialog_Day_0_de.png | 4 +- screenshots/html/data.js | 1891 +++++++++-------- ...edit.impl_RoomDetailsEditView_Day_7_en.png | 4 +- ...it.impl_RoomDetailsEditView_Night_7_en.png | 4 +- 164 files changed, 1322 insertions(+), 1141 deletions(-) create mode 100644 screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png delete mode 100644 screenshots/de/features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_8_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_de.png create mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_6_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_7_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_9_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_9_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_de.png delete mode 100644 screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_9_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png create mode 100644 screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png rename screenshots/de/{features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_de.png => features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_de.png} (100%) rename screenshots/de/{features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_de.png => features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_de.png} (100%) rename screenshots/de/{features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_de.png => features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_de.png} (100%) rename screenshots/de/{features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_de.png => features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_de.png} (100%) rename screenshots/de/{features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_de.png => features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_de.png} (100%) create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_de.png create mode 100644 screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_de.png diff --git a/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml index 7924e7ce7b..582109c717 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml @@ -47,6 +47,10 @@ "Eemalda suhtluskeeld jututoas" "Suhtluskeeluga kasutajad" "Liikmed" + + "%1$d saatis kutse" + "%1$d saatis kutse" + "Ootel" "Peakasutajad" "Moderaatorid" diff --git a/features/rolesandpermissions/impl/src/main/res/values-sk/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-sk/translations.xml index a707b48bc5..ad4832dfd0 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-sk/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-sk/translations.xml @@ -1,14 +1,16 @@ - "Iba správcovia" + "Správca" "Zakázať ľudí" "Odstrániť správy" - "Pozvite ľudí a prijmite žiadosti o pripojenie" + "Člen" + "Pozvať ľudí" + "Spravovať členov" "Správy a obsah" - "Správcovia a moderátori" - "Odstrániť ľudí a odmietnuť žiadosti o pripojenie" + "Moderátor" + "Odstrániť ľudí" "Zmeniť obrázok miestnosti" - "Upraviť miestnosť" + "Upraviť podrobnosti" "Zmeniť názov miestnosti" "Zmeniť tému miestnosti" "Odoslať správy" @@ -32,6 +34,13 @@ "Máte neuložené zmeny." "Uložiť zmeny?" "Neexistujú žiadni zablokovaní používatelia." + + "%1$d zakázaný" + "%1$d zakázaní" + "%1$d zakázaných" + + "Skontrolujte preklepy alebo skúste nové vyhľadávanie" + "Žiadne výsledky pre „%1$s“" "%1$d osoba" "%1$d osoby" @@ -44,8 +53,14 @@ "Zrušiť zákaz prístupu do miestnosti" "Zakázaní" "Členovia" - "Iba správcovia" - "Správcovia a moderátori" + + "%1$d pozvaný" + "%1$d pozvaní" + "%1$d pozvaných" + + "Čaká na schválenie" + "Správca" + "Moderátor" "Vlastník" "Členovia miestnosti" "Zrušenie zákazu %1$s" @@ -58,6 +73,7 @@ "Správy a obsah" "Moderátori" "Vlastníci" + "Povolenia" "Obnoviť povolenia" "Po obnovení oprávnení prídete o aktuálne nastavenia." "Obnoviť oprávnenia?" diff --git a/features/roomdetails/impl/src/main/res/values-et/translations.xml b/features/roomdetails/impl/src/main/res/values-et/translations.xml index 7a315de168..570991ff9e 100644 --- a/features/roomdetails/impl/src/main/res/values-et/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-et/translations.xml @@ -84,6 +84,10 @@ "Eemalda suhtluskeeld jututoas" "Suhtluskeeluga kasutajad" "Liikmed" + + "%1$d saatis kutse" + "%1$d saatis kutse" + "Ootel" "Peakasutajad" "Moderaatorid" @@ -133,6 +137,7 @@ Me ei soovita krüptimise kasutamist selliste avalike jututubade puhul, millega "Võta läbiv krüptimine kasutusele" "Kõik võivad jututoaga liituda" "Kõik" + "Halda kogukondi" "Liituda saab vaid kutse olemasolul" "Vaid kutsega" "Ligipääs" diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 79af58f0e3..75c8592d0e 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -141,9 +141,13 @@ Nous ne recommandons pas d’activer le chiffrement pour les salons que tout le "Activer le chiffrement de bout en bout" "Tout le monde peut rejoindre." "Tout le monde" + "Choisissez les espaces dont les membres peuvent rejoindre ce salon sans invitation. %1$s" + "Gérer les espaces" "Seules les personnes invitées peuvent rejoindre." "Sur invitation uniquement" "Accès" + "Toute personne se trouvant dans un espace autorisé peut joindre le salon." + "Toute personne de l’espace %1$s peut joindre le salon." "Membres de l’espace" "Les Espaces ne sont pas encore supportés" "Vous aurez besoin d’une adresse pour le rendre visible dans l’annuaire public." diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 477b419788..f61e3341bf 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -1,19 +1,21 @@ - "Budete potrebovať adresu miestnosti, aby bola viditeľná v adresári." - "Adresa miestnosti" + "Budete potrebovať adresu, aby sa zobrazovala vo verejnom adresári." + "Upraviť adresu" "Pri aktualizácii nastavenia oznámenia došlo k chybe." "Váš domovský server nepodporuje túto možnosť v šifrovaných miestnostiach, v niektorých miestnostiach nemusíte dostať upozornenie." "Ankety" - "Iba správcovia" + "Správca" "Zakázať ľudí" "Odstrániť správy" - "Pozvite ľudí a prijmite žiadosti o pripojenie" + "Člen" + "Pozvať ľudí" + "Spravovať členov" "Správy a obsah" - "Správcovia a moderátori" - "Odstrániť ľudí a odmietnuť žiadosti o pripojenie" + "Moderátor" + "Odstrániť ľudí" "Zmeniť obrázok miestnosti" - "Upraviť miestnosť" + "Upraviť podrobnosti" "Zmeniť názov miestnosti" "Zmeniť tému miestnosti" "Odoslať správy" @@ -40,7 +42,7 @@ "Zašifrované" "Nešifrované" "Verejná miestnosť" - "Upraviť miestnosť" + "Upraviť podrobnosti" "Vyskytla sa neznáma chyba a informácie nebolo možné zmeniť." "Nepodarilo sa aktualizovať miestnosť" "Správy sú zabezpečené zámkami. Jedine vy a príjemcovia máte jedinečné kľúče na ich odomknutie." @@ -69,6 +71,13 @@ "Téma" "Aktualizácia miestnosti…" "Neexistujú žiadni zablokovaní používatelia." + + "%1$d zakázaný" + "%1$d zakázaní" + "%1$d zakázaných" + + "Skontrolujte preklepy alebo skúste nové vyhľadávanie" + "Žiadne výsledky pre „%1$s“" "%1$d osoba" "%1$d osoby" @@ -81,8 +90,14 @@ "Zrušiť zákaz prístupu do miestnosti" "Zakázaní" "Členovia" - "Iba správcovia" - "Správcovia a moderátori" + + "%1$d pozvaný" + "%1$d pozvaní" + "%1$d pozvaných" + + "Čaká na schválenie" + "Správca" + "Moderátor" "Vlastník" "Členovia miestnosti" "Zrušenie zákazu %1$s" @@ -109,14 +124,15 @@ "Správy a obsah" "Moderátori" "Vlastníci" + "Povolenia" "Obnoviť povolenia" "Po obnovení oprávnení prídete o aktuálne nastavenia." "Obnoviť oprávnenia?" "Roly" "Podrobnosti o miestnosti" "Roly a povolenia" - "Pridať adresu miestnosti" - "Ktokoľvek môže požiadať o pripojenie do miestnosti, ale správca alebo moderátor bude musieť žiadosť prijať." + "Pridať adresu" + "Všetci musia požiadať o prístup." "Požiadať o pripojenie" "Áno, povoliť šifrovanie" "Po aktivácii nie je možné zakázať šifrovanie pre miestnosť. História správ bude viditeľná len pre členov miestnosti, odkedy boli pozvaní alebo keď vstúpili do miestnosti. @@ -126,17 +142,22 @@ To môže brániť správnemu fungovaniu robotov a premostení. Neodporúčame p "Po zapnutí už šifrovanie nie je možné vypnúť." "Šifrovanie" "Povoliť end-to-end šifrovanie" - "Ktokoľvek môže nájsť a pripojiť sa" + "Pripojiť sa môže ktokoľvek." "Ktokoľvek" - "Ľudia sa môžu pripojiť len vtedy, ak sú pozvaní" + "Vyberte, ktorých členovia priestorov sa môžu pripojiť k tejto miestnosti bez pozvánky. %1$s" + "Spravovať priestory" + "Pripojiť sa môžu iba pozvaní ľudia." "Iba na pozvánku" - "Prístup do miestnosti" + "Prístup" + "Ktokoľvek v povolených priestoroch sa môže pripojiť." + "Ktokoľvek v %1$s sa môže pripojiť." "Členovia priestoru" "Priestory momentálne nie sú podporované" - "Budete potrebovať adresu miestnosti, aby bola viditeľná v adresári." - "Adresa miestnosti" + "Budete potrebovať adresu, aby sa zobrazovala vo verejnom adresári." + "Adresa" "Umožniť vyhľadanie tejto miestnosti v adresári verejných miestností %1$s" - "Viditeľné v adresári verejných miestností" + "Umožniť nájdenie vyhľadávaním vo verejnom adresári." + "Viditeľné vo verejnom adresári" "Ktokoľvek" "Kto môže čítať históriu" "Len pre členov, odkedy boli pozvaní" @@ -144,6 +165,7 @@ To môže brániť správnemu fungovaniu robotov a premostení. Neodporúčame p "Adresy miestností predstavujú spôsoby, ako nájsť a získať prístup k miestnostiam. To tiež zaisťuje, že môžete jednoducho zdieľať svoju miestnosť s ostatnými. Môžete sa rozhodnúť zverejniť svoju miestnosť v adresári verejných miestností vášho domovského servera." "Zverejnenie miestnosti" - "Viditeľnosť miestnosti" + "Adresy sú spôsob, ako nájsť a získať prístup do miestností a priestorov. To tiež zabezpečuje, že ich môžete jednoducho zdieľať s ostatnými." + "Viditeľnosť" "Bezpečnosť a súkromie" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index c582f6f6fb..deb2d62902 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -69,7 +69,7 @@ "Share room" "Room info" "Topic" - "Updating room…" + "Updating details…" "There are no banned users." "%1$d Banned" @@ -129,8 +129,10 @@ "Room details" "Roles & permissions" "Add address" + "Anyone in authorized spaces can join, but everyone else must request access." "Everyone must request access." "Ask to join" + "Anyone in %1$s can join, but everyone else must request access." "Yes, enable encryption" "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room. No one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly. diff --git a/features/roomdetailsedit/impl/src/main/res/values/localazy.xml b/features/roomdetailsedit/impl/src/main/res/values/localazy.xml index 7a70381a8b..c20e6f2b47 100644 --- a/features/roomdetailsedit/impl/src/main/res/values/localazy.xml +++ b/features/roomdetailsedit/impl/src/main/res/values/localazy.xml @@ -3,5 +3,5 @@ "Edit details" "There was an unknown error and the information couldn\'t be changed." "Unable to update room" - "Updating room…" + "Updating details…" diff --git a/features/securityandprivacy/impl/src/main/res/values-et/translations.xml b/features/securityandprivacy/impl/src/main/res/values-et/translations.xml index 7e6cdec9c6..c78857389f 100644 --- a/features/securityandprivacy/impl/src/main/res/values-et/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-et/translations.xml @@ -15,6 +15,7 @@ Me ei soovita krüptimise kasutamist selliste avalike jututubade puhul, millega "Võta läbiv krüptimine kasutusele" "Kõik võivad jututoaga liituda" "Kõik" + "Halda kogukondi" "Liituda saab vaid kutse olemasolul" "Vaid kutsega" "Ligipääs" diff --git a/features/securityandprivacy/impl/src/main/res/values-fr/translations.xml b/features/securityandprivacy/impl/src/main/res/values-fr/translations.xml index 754ef4cd1a..5426d71706 100644 --- a/features/securityandprivacy/impl/src/main/res/values-fr/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-fr/translations.xml @@ -15,9 +15,13 @@ Nous ne recommandons pas d’activer le chiffrement pour les salons que tout le "Activer le chiffrement de bout en bout" "Tout le monde peut rejoindre." "Tout le monde" + "Choisissez les espaces dont les membres peuvent rejoindre ce salon sans invitation. %1$s" + "Gérer les espaces" "Seules les personnes invitées peuvent rejoindre." "Sur invitation uniquement" "Accès" + "Toute personne se trouvant dans un espace autorisé peut joindre le salon." + "Toute personne de l’espace %1$s peut joindre le salon." "Membres de l’espace" "Les Espaces ne sont pas encore supportés" "Vous aurez besoin d’une adresse pour le rendre visible dans l’annuaire public." diff --git a/features/securityandprivacy/impl/src/main/res/values-sk/translations.xml b/features/securityandprivacy/impl/src/main/res/values-sk/translations.xml index a9e6b1dd1b..ee346dd5d0 100644 --- a/features/securityandprivacy/impl/src/main/res/values-sk/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-sk/translations.xml @@ -1,9 +1,9 @@ - "Budete potrebovať adresu miestnosti, aby bola viditeľná v adresári." - "Adresa miestnosti" - "Pridať adresu miestnosti" - "Ktokoľvek môže požiadať o pripojenie do miestnosti, ale správca alebo moderátor bude musieť žiadosť prijať." + "Budete potrebovať adresu, aby sa zobrazovala vo verejnom adresári." + "Upraviť adresu" + "Pridať adresu" + "Všetci musia požiadať o prístup." "Požiadať o pripojenie" "Áno, povoliť šifrovanie" "Po aktivácii nie je možné zakázať šifrovanie pre miestnosť. História správ bude viditeľná len pre členov miestnosti, odkedy boli pozvaní alebo keď vstúpili do miestnosti. @@ -13,17 +13,22 @@ To môže brániť správnemu fungovaniu robotov a premostení. Neodporúčame p "Po zapnutí už šifrovanie nie je možné vypnúť." "Šifrovanie" "Povoliť end-to-end šifrovanie" - "Ktokoľvek môže nájsť a pripojiť sa" + "Pripojiť sa môže ktokoľvek." "Ktokoľvek" - "Ľudia sa môžu pripojiť len vtedy, ak sú pozvaní" + "Vyberte, ktorých členovia priestorov sa môžu pripojiť k tejto miestnosti bez pozvánky. %1$s" + "Spravovať priestory" + "Pripojiť sa môžu iba pozvaní ľudia." "Iba na pozvánku" - "Prístup do miestnosti" + "Prístup" + "Ktokoľvek v povolených priestoroch sa môže pripojiť." + "Ktokoľvek v %1$s sa môže pripojiť." "Členovia priestoru" "Priestory momentálne nie sú podporované" - "Budete potrebovať adresu miestnosti, aby bola viditeľná v adresári." - "Adresa miestnosti" + "Budete potrebovať adresu, aby sa zobrazovala vo verejnom adresári." + "Adresa" "Umožniť vyhľadanie tejto miestnosti v adresári verejných miestností %1$s" - "Viditeľné v adresári verejných miestností" + "Umožniť nájdenie vyhľadávaním vo verejnom adresári." + "Viditeľné vo verejnom adresári" "Ktokoľvek" "Kto môže čítať históriu" "Len pre členov, odkedy boli pozvaní" @@ -31,6 +36,7 @@ To môže brániť správnemu fungovaniu robotov a premostení. Neodporúčame p "Adresy miestností predstavujú spôsoby, ako nájsť a získať prístup k miestnostiam. To tiež zaisťuje, že môžete jednoducho zdieľať svoju miestnosť s ostatnými. Môžete sa rozhodnúť zverejniť svoju miestnosť v adresári verejných miestností vášho domovského servera." "Zverejnenie miestnosti" - "Viditeľnosť miestnosti" + "Adresy sú spôsob, ako nájsť a získať prístup do miestností a priestorov. To tiež zabezpečuje, že ich môžete jednoducho zdieľať s ostatnými." + "Viditeľnosť" "Bezpečnosť a súkromie" diff --git a/features/securityandprivacy/impl/src/main/res/values/localazy.xml b/features/securityandprivacy/impl/src/main/res/values/localazy.xml index 859be7670b..f6236edb8b 100644 --- a/features/securityandprivacy/impl/src/main/res/values/localazy.xml +++ b/features/securityandprivacy/impl/src/main/res/values/localazy.xml @@ -3,8 +3,10 @@ "You’ll need an address in order to make it visible in the public directory." "Edit address" "Add address" + "Anyone in authorized spaces can join, but everyone else must request access." "Everyone must request access." "Ask to join" + "Anyone in %1$s can join, but everyone else must request access." "Yes, enable encryption" "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room. No one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly. diff --git a/libraries/push/impl/src/main/res/values-sk/translations.xml b/libraries/push/impl/src/main/res/values-sk/translations.xml index a4deefba78..764dbefa70 100644 --- a/libraries/push/impl/src/main/res/values-sk/translations.xml +++ b/libraries/push/impl/src/main/res/values-sk/translations.xml @@ -15,6 +15,7 @@ "%d oznámenia" "%d oznámení" + "Distribútora oznámení UnifiedPush sa nepodarilo zaregistrovať, takže už nebudete dostávať oznámenia. Skontrolujte nastavenia oznámení v aplikácii a stav distribútora push oznámení." "Máte nové správy." "📹 Prichádzajúci hovor" "** Nepodarilo sa odoslať - prosím otvorte miestnosť" diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 247dc9f026..39da09fb9d 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -272,6 +272,7 @@ "Памылка" "Поспех" "Папярэджанне" + "У вас ёсць незахаваныя змены." "Вашы змены не былі захаваны. Вы ўпэўнены, што хочаце вярнуцца?" "Захаваць змены?" "Ваш хатні сервер неабходна абнавіць для падтрымкі Matrix Authentication Service і стварэння ўліковага запісу." diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index d4f8550f7a..53429fb1df 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -394,6 +394,7 @@ Opravdu chcete pokračovat?" "Chyba" "Úspěch" "Upozornění" + "Máte neuložené změny." "Vaše změny nebyly uloženy. Opravdu se chcete vrátit?" "Uložit změny?" "Maximální povolená velikost souboru je: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-cy/translations.xml b/libraries/ui-strings/src/main/res/values-cy/translations.xml index 11b46cb85c..bfc00ddffb 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -414,6 +414,7 @@ Ydych chi\'n siŵr eich bod am barhau?" "Gwall" "Llwyddiant" "Rhybudd" + "Mae gennych newidiadau heb eu cadw." "Dyw eich newidiadau heb gael eu cadw. Ydych chi\'n siŵr eich bod am fynd nôl?" "Cadw\'r newidiadau?" "Y maint ffeil mwyaf sy\'n cael ei ganiatáu yw: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-da/translations.xml b/libraries/ui-strings/src/main/res/values-da/translations.xml index f8491d6f26..6de4dc7ebd 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -387,6 +387,7 @@ Er du sikker på, at du vil fortsætte?" "Fejl" "Succes" "Advarsel" + "Du har ændringer, der ikke er gemt." "Dine ændringer er ikke blevet gemt. Er du sikker på, at du vil gå tilbage?" "Gem ændringer?" "Den maksimalt tilladte filstørrelse er: %1$s" 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 f912fc4fc4..7467a59bd9 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -387,6 +387,7 @@ Möchtest du wirklich fortfahren?" "Fehler" "Erfolg" "Warnung" + "Du hast nicht gespeicherte Änderungen." "Deine Änderungen wurden nicht gespeichert. Bist du sicher, dass du zurückgehen willst?" "Änderungen speichern?" "Die maximal erlaubte Dateigröße ist: %1$s" 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 5085f404a1..f6bca76182 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -326,6 +326,7 @@ "Σφάλμα" "Επιτυχία" "Προειδοποίηση" + "Έχεις μη αποθηκευμένες αλλαγές." "Οι αλλαγές σου δεν έχουν αποθηκευτεί. Σίγουρα θες να πας πίσω;" "Αποθήκευση αλλαγών;" "Ο οικιακός διακομιστής σου πρέπει να αναβαθμιστεί για να υποστηρίζει το Matrix Authentication Service και τη δημιουργία λογαριασμού." diff --git a/libraries/ui-strings/src/main/res/values-es/translations.xml b/libraries/ui-strings/src/main/res/values-es/translations.xml index 4428e0b864..4fcc3fd9df 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -318,6 +318,7 @@ Motivo: %1$s." "Error" "Terminado" "Atención" + "Tienes cambios sin guardar." "Tus cambios no se han guardado. ¿Estás seguro de que quieres volver atrás?" "¿Guardar cambios?" "Tu servidor base debe actualizarse para admitir Matrix Authentication Service y la creación de cuentas." 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 4b8c38be6c..e729286ee5 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -234,6 +234,7 @@ Põhjus: %1$s." "Hele" "Rida on kopeeritud lõikelauale" "Link on kopeeritud lõikelauale" + "Seo uus seade" "Laadime…" "Laadime veel…" @@ -246,10 +247,12 @@ Põhjus: %1$s." "Sõnum" "Tegevused sõnumiga" + "Sõnumi saatmine ei õnnestunud" "Sõnumi paigutus" "Sõnum on eemaldatud" "Kaasaegne" "Summutatud" + "Nimi" "%1$s (%2$s)" "Otsingul pole tulemusi" "Jututoal puudub nimi" @@ -324,6 +327,7 @@ Põhjus: %1$s." "Midagi läks valesti" "Tekkis viga. Palun proovi uuesti." "Kogukond" + "Mida selles kogukonnas tehakse?" "%1$d kogukond" "%1$d kogukonda" @@ -388,6 +392,7 @@ Kas sa oled kindel, et soovid jätkata?" "Viga" "Õnnestus" "Hoiatus" + "Sul on salvestamata muudatusi" "Sinu tehtud muudatused pole veel salvestatud. Kas sa oled kindel, et soovid minna tagasi?" "Kas salvestame muudatused?" "Suurim lubatud failisuurus on: %1$s" @@ -427,6 +432,11 @@ Kas sa oled kindel, et soovid jätkata?" "Valikud" "Kustuta: %1$s" "Seadistused" + "Lauaarvuti" + "Nutiseade" + "Halda kogukondi" + "(Tundmatu kogukond)" + "Sinu kogukonnad" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Siia lisamiseks vajuta sõnumil ja vali „%1$s“." "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile" diff --git a/libraries/ui-strings/src/main/res/values-eu/translations.xml b/libraries/ui-strings/src/main/res/values-eu/translations.xml index 15bfa21fb5..10f914d0fd 100644 --- a/libraries/ui-strings/src/main/res/values-eu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-eu/translations.xml @@ -336,6 +336,7 @@ Ziur jarraitu nahi duzula?" "Errorea" "Arrakasta" "Abisua" + "Gorde gabeko aldaketak dituzu." "Zure aldaketak ez dira gorde. Ziur itzuli nahi duzula?" "Aldaketak gorde?" "Hautatu bideoaren igoera-kalitatea" diff --git a/libraries/ui-strings/src/main/res/values-fa/translations.xml b/libraries/ui-strings/src/main/res/values-fa/translations.xml index 1656bc3b0c..0522010510 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -345,6 +345,7 @@ "خطا" "موفّقیت" "هشدار" + "تغییراتی ذخیره نشده دارید." "تغییراتتان ذخیره نشده‌اند. مطمئنید که می‌خواهید برگردید؟" "ذخیرهٔ تغییرات؟" "حست‌وجوی شکلک‌ها" diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index bc23e78b05..8c725904d7 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -388,6 +388,7 @@ Haluatko varmasti jatkaa?" "Virhe" "Onnistui" "Varoitus" + "Sinulla on tallentamattomia muutoksia" "Muutoksiasi ei ole tallennettu. Haluatko varmasti palata takaisin?" "Tallennetaanko muutokset?" "Suurin sallittu tiedostokoko on: %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 11834a4d06..f4b55e8d80 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -246,6 +246,7 @@ Raison : %1$s." "Message" "Actions sur le message" + "Échec de l’envoi du message" "Mode d’affichage des messages" "Message supprimé" "Moderne" @@ -368,6 +369,7 @@ Raison : %1$s." "En attente…" "En attente de la clé de déchiffrement" "Vous" + "Les messages que vous enverrez seront partagés avec les nouveaux membres invités dans ce salon. %1$s" "L’identité de %1$s a été réinitialisée. %2$s" "L’identité de %1$s %2$s a été réinitialisée. %3$s" "(%1$s)" @@ -388,6 +390,7 @@ Raison : %1$s." "Erreur" "Succès" "Attention" + "Vous avez des modifications non-enregistrées." "Vos modifications n’ont pas été enregistrées. Êtes-vous certain de vouloir quitter ?" "Enregistrer les changements ?" "La taille maximale de fichier autorisée est: %1$s" @@ -427,6 +430,11 @@ Raison : %1$s." "Options" "Supprimer %1$s" "Paramètres" + "Espaces où les membres peuvent rejoindre le salon sans invitation." + "Gérer les espaces" + "(Espace inconnu)" + "Autres espaces dont vous n’êtes pas membre" + "Vos espaces" "Échec de la sélection du média, veuillez réessayer." "Cliquez (clic long) sur un message et choisissez « %1$s » pour qu‘il apparaisse ici." "Épinglez les messages importants pour leur donner plus de visibilité" diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index 4539d065a3..bc235cccd4 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -387,6 +387,7 @@ Biztos, hogy folytatja?" "Hiba" "Sikeres" "Figyelmeztetés" + "Mentetlen módosításai vannak." "A módosítások nem lettek mentve. Biztos, hogy visszalép?" "Menti a módosításokat?" "A legnagyobb megengedett fájlméret: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index bd7739d5ba..9735344818 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -332,6 +332,7 @@ Apakah Anda yakin ingin melanjutkan?" "Eror" "Berhasil" "Peringatan" + "Anda memiliki perubahan yang belum disimpan." "Perubahan Anda belum disimpan. Apakah Anda yakin ingin kembali?" "Simpan perubahan?" "Homeserver Anda perlu ditingkatkan untuk mendukung Matrix Authentication Service dan pembuatan akun." diff --git a/libraries/ui-strings/src/main/res/values-it/translations.xml b/libraries/ui-strings/src/main/res/values-it/translations.xml index 793b115917..1e2765a190 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -388,6 +388,7 @@ Sei sicuro di voler continuare?" "Errore" "Operazione riuscita" "Attenzione" + "Hai delle modifiche non salvate." "Le modifiche non sono state salvate. Vuoi davvero tornare indietro?" "Salvare le modifiche?" "La dimensione massima consentita per il file è: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-ka/translations.xml b/libraries/ui-strings/src/main/res/values-ka/translations.xml index dd67ca02c2..393b404f31 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -236,6 +236,7 @@ "შეცდომა" "წარმატება" "გაფრთხილება" + "თქვენ გაქვთ შეუნახავი ცვლილებები" "თქვენი ცვლილებები არაა შენახული. დარწმუნებული ხართ დაბრუნებაში?" "შენახვა?" "მუდმივი ბმულის შექმნა ვერ მოხერხდა" diff --git a/libraries/ui-strings/src/main/res/values-ko/translations.xml b/libraries/ui-strings/src/main/res/values-ko/translations.xml index 256e561db5..f00637dbe5 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -364,6 +364,7 @@ "오류" "성공" "경고" + "저장되지 않은 변경 사항이 있습니다." "변경 내용이 저장되지 않았습니다. 정말로 돌아가시겠습니까?" "변경 사항을 저장하시겠습니까?" "허용되는 최대 파일 크기: %1$s diff --git a/libraries/ui-strings/src/main/res/values-nb/translations.xml b/libraries/ui-strings/src/main/res/values-nb/translations.xml index e64a005577..2c62758e39 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -385,6 +385,7 @@ Er du sikker på at du vil fortsette?" "Feil" "Suksess" "Advarsel" + "Du har endringer som ikke er lagret." "Endringene dine er ikke lagret. Er du sikker på at du vil gå tilbake?" "Lagre endringer?" "Maksimal tillatt filstørrelse er: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml index 7c682233a6..cbd2d4d63b 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -300,6 +300,7 @@ Reden: %1$s." "Fout" "Geslaagd" "Waarschuwing" + "Je hebt niet-opgeslagen wijzigingen" "Je wijzigingen zijn niet opgeslagen. Weet je zeker dat je terug wilt gaan?" "Wijzigingen opslaan?" "Je homeserver moet worden geüpgraded om de Matrix Authentication Service en het aanmaken van accounts te ondersteunen." diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index e4186fd0f2..7b12125a3a 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -395,6 +395,7 @@ Czy na pewno chcesz kontynuować?" "Błąd" "Sukces" "Ostrzeżenie" + "Masz niezapisane zmiany." "Zmiany nie zostały zapisane. Czy na pewno chcesz wrócić?" "Zapisać zmiany?" "Maksymalny dozwolony rozmiar pliku to: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml index 2f9b4a13e8..d7fc53da97 100644 --- a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml @@ -388,6 +388,7 @@ Você tem certeza de que deseja continuar?" "Erro" "Sucesso" "Alerta" + "Você tem alterações não salvas." "Suas alterações não foram salvas. Tem certeza de que você quer voltar?" "Salvar alterações?" "O tamanho máximo permitido de arquivos é: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index 5e55f3a9de..5fbf7338f4 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -382,6 +382,7 @@ Tens a certeza de que queres continuar?" "Erro" "Sucesso" "Aviso" + "Tens alterações por guardar." "As tuas alterações não foram guardadas. Tens a certeza que queres voltar atrás?" "Guardar alterações?" "O tamanho máximo de ficheiro permitido é: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index 0cf1acf673..16b0e90b89 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -395,6 +395,7 @@ Sunteți sigur că doriți să continuați?" "Eroare" "Succes" "Avertisment" + "Aveți modificări nesalvate." "Modificările dumneavoastră nu au fost salvate. Sunteți sigur că doriți să vă întoarceți?" "Salvați modificările?" "Dimensiunea maximă permisă pentru fișiere este: %1$s" 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 1290cb36c8..d319fcc053 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -396,6 +396,7 @@ "Ошибка" "Успешно" "Предупреждение" + "У вас есть несохраненные изменения." "Изменения не сохранены. Вы действительно хотите вернуться?" "Сохранить изменения?" "Максимально допустимый размер файла: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index a94c5657cf..694b679f45 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -250,6 +250,7 @@ Dôvod: %1$s." "Správa" "Akcie správy" + "Správu sa nepodarilo odoslať" "Štýl správ" "Správa odstránená" "Moderné" @@ -376,6 +377,7 @@ Dôvod: %1$s." "Čaká sa…" "Čaká sa na dešifrovací kľúč" "Vy" + "Správy, ktoré odošlete, budú zdieľané s novými členmi pozvanými do tejto miestnosti. %1$s" "Totožnosť používateľa %1$s sa obnovila.%2$s" "Totožnosť používateľa %1$s %2$s bola obnovená. %3$s" "(%1$s)" @@ -396,6 +398,7 @@ Naozaj chcete pokračovať?" "Chyba" "Úspech" "Upozornenie" + "Máte neuložené zmeny." "Vaše zmeny neboli uložené. Naozaj sa chcete vrátiť?" "Uložiť zmeny?" "Maximálna povolená veľkosť súboru je: %1$s" @@ -435,6 +438,11 @@ Naozaj chcete pokračovať?" "Možnosti" "Odstrániť %1$s" "Nastavenia" + "Priestory, kde sa členovia môžu pripojiť k miestnosti bez pozvania." + "Spravovať priestory" + "(Neznámy priestor)" + "Iné priestory, ktorých nie ste členom" + "Vaše priestory" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Stlačte správu a vyberte možnosť „%1$s“, ktorú chcete zahrnúť sem." "Pripnite dôležité správy, aby sa dali ľahko nájsť" @@ -454,6 +462,10 @@ Naozaj chcete pokračovať?" "Vaša správa nebola odoslaná, pretože %1$s neoveril/a všetky zariadenia." "Jedno alebo viac vašich zariadení nie je overených. Správu môžete odoslať aj tak, alebo môžete zatiaľ zrušiť a skúsiť to znova neskôr po overení všetkých svojich zariadení." "Vaša správa nebola odoslaná, pretože ste neoverili jedno alebo viac svojich zariadení" + "Zmeniť nastavenia" + "Spravovať priestor" + "Spravovať miestnosti" + "Povolenia" "Upraviť správcov alebo vlastníkov" "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa získať údaje o používateľovi" diff --git a/libraries/ui-strings/src/main/res/values-sv/translations.xml b/libraries/ui-strings/src/main/res/values-sv/translations.xml index e3cf26193e..9d928a406f 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -369,6 +369,7 @@ Anledning:%1$s." "Fel" "Lyckades" "Varning" + "Du har osparade ändringar." "Dina ändringar har inte sparats. Är du säker på att du vill gå tillbaka?" "Spara ändringar?" "Den maximala tillåtna filstorleken är: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-tr/translations.xml b/libraries/ui-strings/src/main/res/values-tr/translations.xml index c72f5a6139..cabfc68e01 100644 --- a/libraries/ui-strings/src/main/res/values-tr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-tr/translations.xml @@ -307,6 +307,7 @@ Devam etmek istediğinizden emin misiniz?" "Hata" "Başarılı" "Uyarı" + "Kaydedilmemiş değişiklikleriniz var." "Değişiklikleriniz kaydedilmedi. Geri dönmek istediğinden emin misin?" "Değişiklikleri Kaydet?" "Ana sunucunuzun Matrix Authentication Service ve hesap oluşturmayı destekleyecek şekilde güncellenmesi gerekiyor." diff --git a/libraries/ui-strings/src/main/res/values-uk/translations.xml b/libraries/ui-strings/src/main/res/values-uk/translations.xml index a4c171a21b..03b3b6b3f2 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -382,6 +382,7 @@ "Помилка" "Успіх" "Попередження" + "У вас є не збережені зміни." "Внесені зміни не збережено. Ви впевнені, що хочете повернутися?" "Зберегти зміни?" "Максимально дозволений розмір файлу: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-ur/translations.xml b/libraries/ui-strings/src/main/res/values-ur/translations.xml index 5abd2e0894..ef53dc7843 100644 --- a/libraries/ui-strings/src/main/res/values-ur/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ur/translations.xml @@ -265,6 +265,7 @@ "خرابی" "کامیابی" "انتباہ" + "آپکے پاس غیر محفوظ تبدیلیاں ہیں" "آپ کی تبدیلیاں محفوظ نہیں کی گئیں۔ کیا آپ کو یقین ہے کہ آپ واپس جانا چاہتے ہیں؟" "تبدیلیاں محفوظ کریں؟" "‏Matrix Authentication Service اور اکاؤنٹ بنانے میں معاونت کے لیے آپ کے ہوم سرور کو اپ گریڈ کرنے کی ضرورت ہے۔" diff --git a/libraries/ui-strings/src/main/res/values-uz/translations.xml b/libraries/ui-strings/src/main/res/values-uz/translations.xml index 8f23ee0d9e..fb36f3658b 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -376,6 +376,7 @@ Davom etasizmi?" "Xato" "Muvaffaqiyat" "Ogohlantirish" + "Sizda saqlanmagan oʻzgarishlar bor" "Oʻzgarishlar saqlanmadi. Haqiqatan ham orqaga qaytmoqchimisiz?" "O‘zgartirishlarni saqlaysizmi?" "Ruxsat etilgan maksimal fayl hajmi: %1$s" diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index 1c88ac71df..6707ca7950 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -380,6 +380,7 @@ "錯誤" "成功" "警告" + "您有尚未儲存的變更" "變更尚未儲存,您確定要返回嗎?" "是否儲存變更?" "最大允許的檔案大小為:%1$s" diff --git a/libraries/ui-strings/src/main/res/values-zh/translations.xml b/libraries/ui-strings/src/main/res/values-zh/translations.xml index a743a5771b..402029cb2c 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -380,6 +380,7 @@ "错误" "成功" "警告" + "您有未保存的更改。" "更改尚未保存,确定要返回吗?" "保存更改?" "允许的最大文件大小为:%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 d422a4c35c..46a3559f3a 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -234,6 +234,7 @@ Reason: %1$s." "Light" "Line copied to clipboard" "Link copied to clipboard" + "Link new device" "Loading…" "Loading more…" @@ -432,6 +433,9 @@ Are you sure you want to continue?" "Options" "Remove %1$s" "Settings" + "Desktop computer" + "Mobile device" + "What type of device do you want to link?" "Spaces where members can join the room without an invitation." "Manage spaces" "(Unknown space)" diff --git a/screenshots/de/features.poll.impl.create_CreatePollView_Day_2_de.png b/screenshots/de/features.poll.impl.create_CreatePollView_Day_2_de.png index 5f7d39d4b1..41623d158d 100644 --- a/screenshots/de/features.poll.impl.create_CreatePollView_Day_2_de.png +++ b/screenshots/de/features.poll.impl.create_CreatePollView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bda355b4cc26ca3eb609ac11a06b1249c5be56340fbca6b526118c0588e53218 -size 45160 +oid sha256:537fb0eec587e1f9e7b5f4095e9aa09c687f47e2b45025efa7dbc8cb4e030fd3 +size 42366 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png index 03cd573859..6d1d7aba15 100644 --- a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:371cdd134e7991f65da9fa526b89b1562db79ec91ee12d9aac96b34e43a883f2 -size 22160 +oid sha256:98a2048354e01703cc5a3b63a273682176b45f39dc79432e75c5f2961e71e941 +size 22986 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png index d48a261081..e11e0938c6 100644 --- a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b67896e65b700af7c989250098de7dabc61ee97db5157c1afebd83640192575 -size 70519 +oid sha256:fbe3d66e2749b8af8e922fb75a723b5885d3909e7fdf94f913d9a73189f6cefa +size 69959 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png new file mode 100644 index 0000000000..8c3409315d --- /dev/null +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb4abd8d65e77aecba3d8fa4a4f5e0417b11b8b1b8e438da0b24e14fa5472bdf +size 34714 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_de.png index d17592a23b..5ce611d271 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c69a3dbfca46e010898fa574df4ca20e0ef2c92810b58413125c911bdb1f88ed -size 53040 +oid sha256:5531d2f264a7b6c0f543a4ffb9987d4c7d60caec8f2d0d260a8b1fd1aae8c2a8 +size 52265 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_de.png index 613fc7b48d..96a5fe50e1 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08f1af124411ce01ff24b6b47ccb3e8f02ba17ec6bc6aed98acd62f3dbd32bb7 -size 71876 +oid sha256:d71db8b8e66e0fcd0f82ad7356d3a9794bb4dc980dbfbf1545c00206776ddb90 +size 70427 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_de.png index 749c220c31..1c3d282116 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19845c2e90dd9a5c3bc13f5ba66b38c02ac0ec961d3dac8713d1db465d826f41 -size 65497 +oid sha256:175f2fcd689cd82461350b65db068202972182bda557895c403bbd93d6a73481 +size 64096 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_de.png index 92aa51f8f4..482a1270c5 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68887295c717d5a10e594bcfe4d6c84369bf2d468d7f998b2ccd82d27798d56d -size 65331 +oid sha256:b70911a26479225e26f4fa68e5629043a4e3d3fa7e2ef3c11682ac1fcf52c374 +size 63932 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_de.png index 2617a69130..c7a8938912 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b139e5a7a55132a5bbe260cf300a86f2437feacb62ddf5d4144ed0718545d6c6 -size 59210 +oid sha256:55b998f4f10f8aeb8b72a746b6f9645570b48b5b130f10e4e6d4bc239571b82f +size 57804 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_de.png index d536b91189..c4aeacefe1 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0bc99152df9a9fc1e8ae63bf1d40ded275d178555659981042649555db1c8be -size 65977 +oid sha256:58229d50524a34a5eba484ea7012876c6b90256fa0a293faadd8ebddc935db42 +size 61091 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_de.png index 20109519a7..5938604641 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee106780e3dea8be63a63e22c5c9d44e6402a40729f90fe47a2ca2959395ee07 -size 66214 +oid sha256:5741c7ed5079e1dfeb125ea2a5f3ab429b01966b70fef16ade5d83785f785a7e +size 65477 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_de.png index 6f446ed016..53ddd8d7d1 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2214de9f67c410ea11669fc9846286e6ad8ce6210a60fabcb8da3928a0ab6920 -size 55686 +oid sha256:261e28da918e11842e7d80449de98b861979aa6ee2d32f6f4d4662084a7bfb49 +size 54978 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_de.png index 92aa51f8f4..482a1270c5 100644 --- a/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_de.png +++ b/screenshots/de/features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68887295c717d5a10e594bcfe4d6c84369bf2d468d7f998b2ccd82d27798d56d -size 65331 +oid sha256:b70911a26479225e26f4fa68e5629043a4e3d3fa7e2ef3c11682ac1fcf52c374 +size 63932 diff --git a/screenshots/de/features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_de.png b/screenshots/de/features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_de.png deleted file mode 100644 index fc9c3e2365..0000000000 --- a/screenshots/de/features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:353deccaf44203d369a40c95032787afd5946b12b76c8fecde6a8b8028df7631 -size 15419 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_de.png deleted file mode 100644 index 760a4adfd0..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1250b03f29403bac32fac8fa6386e7897336f9812e66fc51ca971665b18c1fad -size 30009 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_de.png deleted file mode 100644 index 592f5e6efd..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:305ba31f911770af43df762d462c5c006d781f80f5ccdc63d7adcfd704fae13e -size 24578 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_de.png deleted file mode 100644 index 77c7e2e388..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c4edb86f9fef95dec9238388e0ddb045fa571ab57a8c0980b40d66cce8bf82e2 -size 31144 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_de.png deleted file mode 100644 index 3fc335c9b9..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c302044f568ac50a50161ffbd05cbb709d2bf198e87fdc75f81343242871676 -size 55607 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_de.png deleted file mode 100644 index e5d2c28620..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ddb4b7a2e5b473e8a4b75a65bf884360ed35edd93d7801c7c121d57878523620 -size 30052 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_de.png deleted file mode 100644 index 3f2924b10d..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:86115b3d58661c9c59d6ebeb815ac58ab215c25fd5655f98525bbc6f74c641f2 -size 30140 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_de.png deleted file mode 100644 index c66dec9444..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:12d0c536795bd5922e4af54e9c7bcab1ae3d6c0f61ecb9a5b68898c26c81aa6b -size 27621 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png deleted file mode 100644 index df697466c4..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e12d9f423c460a85a50297e9ddf99a061ee84e04ba36b0765074658807a30390 -size 29743 diff --git a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_8_de.png b/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_8_de.png deleted file mode 100644 index 02051a08da..0000000000 --- a/screenshots/de/features.roomdetails.impl.edit_RoomDetailsEditView_Day_8_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:12f8ce1dbeb1a16ab8351486310fdeabba566db4aad460fc4e1e1f7fdbe63bf7 -size 37209 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_de.png deleted file mode 100644 index e616c17ea9..0000000000 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66d5bac689bdb05818951e2e6faad9b4e313146bef4cdf99ce500d10b7717cd2 -size 12286 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_de.png deleted file mode 100644 index 9a5c54bfec..0000000000 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0bd483cd461e077f2c1a67eb3a2a6e865da7af0659e6786ca3252d189cd3f4f3 -size 12528 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_de.png deleted file mode 100644 index e616c17ea9..0000000000 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66d5bac689bdb05818951e2e6faad9b4e313146bef4cdf99ce500d10b7717cd2 -size 12286 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_0_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_0_de.png index da3a20f79f..17a0e0c2a1 100644 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_0_de.png +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d667737faee1070520e5dd4e62a1838eb37aa9080a993e33276188ca8ac2bdc9 -size 47880 +oid sha256:344c0d1c9ac8e0b15b396b9bae16136db85a1b81b0cb9f959e2f27a8d6e36c6f +size 13650 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_1_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_1_de.png index ac1a6b63d7..e6c3dab94a 100644 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_1_de.png +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67e7995d4a975a732223a9f248c8c9ac00173b2783fe05ceb2a8d0281f403e6a -size 54190 +oid sha256:a762a5501000d41b1407045482440beb78742a9b671bdd2400d5c23dfb15586f +size 22798 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_2_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_2_de.png index 9a5c54bfec..e916b74f83 100644 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_2_de.png +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bd483cd461e077f2c1a67eb3a2a6e865da7af0659e6786ca3252d189cd3f4f3 -size 12528 +oid sha256:817a9c7ab2ef22da1cedd89ba652696ca95fe623baa480f42b86a5e990e58e71 +size 58010 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_3_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_3_de.png index 58d5fd88bb..9cad7e89e3 100644 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_3_de.png +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d074ac8751c7f125534134d3bb06cc19c6f5ce17da390ddd633f264f9806ee8 -size 13860 +oid sha256:a721a146e8c91aee975941f1c58484de7bf7d28073ec3b31027df72d0a398788 +size 31317 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_4_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_4_de.png index 9a5c54bfec..d551980d61 100644 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_4_de.png +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bd483cd461e077f2c1a67eb3a2a6e865da7af0659e6786ca3252d189cd3f4f3 -size 12528 +oid sha256:40be9c1c2afaa5171b96a66adebf9c665324ff1cc323060b0998edad9f788e9c +size 59249 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_5_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_5_de.png index 79a25499ad..4e8c43e825 100644 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_5_de.png +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f3641f966fcf71259afeedc2c4b32d3e2c581af23c9c4220c9b80152501e77f -size 7949 +oid sha256:8174b00bbcae8f48833c10a474ddb26c2f003c23bb36b43c91b3a3c13485b23e +size 19444 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_6_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_6_de.png new file mode 100644 index 0000000000..27e87d2a1f --- /dev/null +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5989462acb327dea61c68b082349b9bba499bf98968563f8c144a04169e205e6 +size 29897 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_7_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_7_de.png deleted file mode 100644 index 7757f4b08a..0000000000 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_7_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:13c4c05dd4a7e93b9fbcd5c361fdda4c17cb1d5b9918511bf402cf49c0dc27db -size 25164 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png deleted file mode 100644 index 3ba65e7151..0000000000 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:251848f9afc246fb2ec6f36da893878360e24634efdcb3920aac174768f9ad6e -size 12298 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_9_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_9_de.png deleted file mode 100644 index dbc779e7a6..0000000000 --- a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_9_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7d518add734e55b81cbc35e77d059c2ef1777488f756b5da6cb8504f30c399dd -size 21660 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_de.png deleted file mode 100644 index cd516fe53b..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bce82fc99877bf4baf0f681ebfa1e424a653ee9d5d13d73345a9eb9d8e1a04c8 -size 49084 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_de.png deleted file mode 100644 index da6126ac25..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d26a66215dd6e4c5327603d962c484ecd237c0e39efa2526831548e4ba7d8a3c -size 66264 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_de.png deleted file mode 100644 index d45d21d129..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2146fc5949ddb6ec451c1d375696401c358cb24415351667786ef079516797e5 -size 66390 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_de.png deleted file mode 100644 index ea269fe4c9..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42cac3e2c1a32c170062e4933e0df0b4df56767b7b1ee9c70c6ba515e5fe9364 -size 66816 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_de.png deleted file mode 100644 index 6a2ec9b414..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_4_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e96600ec5b77af84ae80b334700b73a353e19895f97479afacb3ea6667b25c04 -size 66207 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_de.png deleted file mode 100644 index 6a254e1545..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd52fe9bdae5629cae86e251004bb77cf0a503869839fc78582a8db478fb29fd -size 48853 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_de.png deleted file mode 100644 index 6a254e1545..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_6_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd52fe9bdae5629cae86e251004bb77cf0a503869839fc78582a8db478fb29fd -size 48853 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png deleted file mode 100644 index ea72553cc6..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_7_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:400c4e4565f0278ec0ce464d78c05faf5bec81e69b27d0d74962c8b12e99b22d -size 50052 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_de.png deleted file mode 100644 index 032ce0414b..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_8_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aad25334fd43f36325106f39977eec19ffcc0695d752ecc226ef4705c2d073ce -size 42798 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_9_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_9_de.png deleted file mode 100644 index 10ff645a54..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewDark_9_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a6849deebbd1181d6fa359fd0a88171f53b032d234732d1823ebb2339f094174 -size 65846 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_de.png deleted file mode 100644 index 5c00e6287b..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3e881dee5efc987b70134fc688bb57755f8aab2dfcdee44a2a32caea09e91cee -size 51011 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_de.png deleted file mode 100644 index 6097402d23..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:de4e33e81d42e013e2a1a633d81ad410af38025cd007d0a5502316a3c73cf840 -size 68986 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_de.png deleted file mode 100644 index 0f3b0876cb..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:92413621be8733a417b97b56cb8d518f07eeec4791cba3ff6e3f19ae85719cf0 -size 69200 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_de.png deleted file mode 100644 index f0a81c9655..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:46fd40c5f6ef2a796503398468fed8cb945d20fb016c14d85409726e66a59078 -size 69721 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_de.png deleted file mode 100644 index e57def30b7..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_4_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:378bcab0bc462571f1b80489b40cdd03b977b17b8864a684423dfe84f1fd1cf2 -size 68857 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_de.png deleted file mode 100644 index efddf6337d..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2678096406dec316cc4e961102ba38b30de6a3b128fa279db1228225f7cf60fa -size 50974 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_de.png deleted file mode 100644 index efddf6337d..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_6_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2678096406dec316cc4e961102ba38b30de6a3b128fa279db1228225f7cf60fa -size 50974 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png deleted file mode 100644 index 9a7c14f9cd..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_7_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6193d8ea073e83fe4e32ace278357f1ddf78bb48e0dfda54eb106421c88369e2 -size 52362 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_de.png deleted file mode 100644 index e8df593416..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_8_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30625120454624c48057d57dd2dd17a7e254cdfa2228cbc9776a7dc0be8ec07c -size 44360 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_9_de.png b/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_9_de.png deleted file mode 100644 index c6ebfd2112..0000000000 --- a/screenshots/de/features.roomdetails.impl.securityandprivacy_SecurityAndPrivacyViewLight_9_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9b26dd32028051acf1fa6d7b2d335a08efd80a0a0fbc0c729a3375b57ef072d8 -size 68465 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png new file mode 100644 index 0000000000..45d287b5ec --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7a8a805ff40cfc6194a414a2d1c1babc5dc2335fb5c96bb72f6f2f412c91346 +size 30052 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png new file mode 100644 index 0000000000..91845d6b8f --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6ccfe1ff08087bd75a8e0017f5d12540cc567423801050dc091005722f3d9b1 +size 24575 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png new file mode 100644 index 0000000000..16fde1067e --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55711397eb8fa3717a3891e56c078cca643520b2d0fefeede118b19db8676341 +size 31204 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png new file mode 100644 index 0000000000..b366ffe07c --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89bcd852bb60044ba429d5c0a884b05d3a28403d985f95bd1582f1f45baca003 +size 54044 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png new file mode 100644 index 0000000000..e8642f7bb8 --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f8fde96567da32ec9a97eecfb1224b5ae23aa0c7608792036f452eebbad466a +size 51217 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png new file mode 100644 index 0000000000..f38d37867b --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e343b3df1a386702c6163393ff05d342abbc9c245ba93129d24e7be5acdaa39 +size 30079 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png new file mode 100644 index 0000000000..60f40910a3 --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ffebfde2aa3d3f3a7e9f7a3dbf8b9e6b8044657815735d2d8c401d2caa8ab51 +size 30225 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png new file mode 100644 index 0000000000..faa2a0b84a --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4253142dd34410c924bfd0499042a05b9ad59afa7073957835a8d4afc6a7d5a6 +size 25470 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png new file mode 100644 index 0000000000..534874b570 --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4fae7c1d5e7bd4f10658bc1777af60ae110278e283a03ca52855e990448f8a4 +size 31022 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png new file mode 100644 index 0000000000..e95bd5c15d --- /dev/null +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da72832a3646008468a061de42964b7d98d563d3a2244f63d168c4a2f38247e6 +size 32513 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png index 90d52aa97c..a5638d89f3 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22352da5dc1213be58d28663f6696ca0c0588422576e0e018fae7887edbbd25c -size 18458 +oid sha256:90712ac1929c94927172c10a09ed8c9955e44aa4d87d02020f9bc8781d87f30c +size 18775 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png index a3fffe85d9..9c94b62b9c 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e23b88a9cbcbb626dc222660560a9e936b4f0060b6978296d42a7913d19d68bd -size 22298 +oid sha256:e2871173d98a9add3a41617e6033ce4a293e7ee683997a2ffe9e60f4ecc5513b +size 22477 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png index 2a137dda7d..207a840978 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b9761ab02b0421f77a4f9876482817d9be98553ef72291e5d7a4679a09b27c6 -size 27750 +oid sha256:25800bbb0ebf715f7d8977ecd466c545c7b603703e145ba8d87e5572f4bf5421 +size 28052 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png index 4ffe9e5c53..348bc07623 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa3fe7ed313bbfdaee18fc9b653008ab7e9bedbe806647b0e8842ed17fc450e3 -size 28168 +oid sha256:3e3c9507e122bf1e90a459ec0a772baaf3811f7f7d41e9e48f20bc2528aee5d1 +size 28467 diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_de.png b/screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_de.png similarity index 100% rename from screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_0_de.png rename to screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_de.png diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_de.png b/screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_de.png similarity index 100% rename from screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_1_de.png rename to screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_de.png diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_de.png b/screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_de.png similarity index 100% rename from screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_2_de.png rename to screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_de.png diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_de.png b/screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_de.png similarity index 100% rename from screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_3_de.png rename to screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_de.png diff --git a/screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_de.png b/screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_de.png similarity index 100% rename from screenshots/de/features.roomdetails.impl.securityandprivacy.editroomaddress_EditRoomAddressView_Day_4_de.png rename to screenshots/de/features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_de.png diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_de.png new file mode 100644 index 0000000000..631fd4634e --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76bbbeb0e07b75805decc4a25d815ec1b73f83947b861c71ef697463ff00d9be +size 50558 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_de.png new file mode 100644 index 0000000000..d8e327cec9 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7cc7260e1f01727bc96317f278158a36cdb0a6ee544937e1f7b2b2e5aee9b71f +size 51358 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_de.png new file mode 100644 index 0000000000..f584c028e1 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:407a338096b8e758eb4663016fc1448fffc7756b5055c5be015782d4f9d34de7 +size 51832 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_de.png new file mode 100644 index 0000000000..ff8e29ea59 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:044869f6f523e6ab43de53e7ff13a8c1771a929030f60a8191329f385be67835 +size 24752 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_de.png new file mode 100644 index 0000000000..eafb1f2805 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9027ed5e27a1d640ab50b4c544d622c718d3bef6df477bf66b99ee605ccec7c +size 51770 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png new file mode 100644 index 0000000000..f584c028e1 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:407a338096b8e758eb4663016fc1448fffc7756b5055c5be015782d4f9d34de7 +size 51832 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png new file mode 100644 index 0000000000..a7c70bf14d --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e771cd9a182dab3615661aebdeba6069cbf04218f60d709a529693e8ad6005e0 +size 52416 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png new file mode 100644 index 0000000000..ef5cc7a3d4 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:148d51c2ea8929c978065e5db9a531f4611559d230b73ac3fde013992c3d28fb +size 43911 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_de.png new file mode 100644 index 0000000000..71265a00fe --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afe4234500a2f3696e7e794bed9fb62477c3a6f1439d597a7df5cfd1a61fb73f +size 42978 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_de.png new file mode 100644 index 0000000000..56d7e39c4f --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d1963026fb35db84c4413a5c6e225657c95eabeee95b880afd8e7a59de9c28d +size 45475 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_de.png new file mode 100644 index 0000000000..eef53d5522 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49607772cae3cc9f9e6e8436369a9e84392e1fb0892c2f9f4dbe2834f67cbdc8 +size 50557 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_de.png new file mode 100644 index 0000000000..f7ed121780 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2cbad28899d0c9f55f4abcd04e5ea3fcd896d7d7e1649ce52eb9b23bbe7b6e91 +size 65600 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_de.png new file mode 100644 index 0000000000..a174686a2d --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f561351b6dbd13b6cd2f55f8df9f31c84453594acf511cdde27855639ba4ea7c +size 65148 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_de.png new file mode 100644 index 0000000000..44e0015abe --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d20dafcb3552d24835bbeec5a288cad29015ceaaee123d64fa32123a51c3cb4 +size 65727 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png new file mode 100644 index 0000000000..97921c3734 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b52d24166c4f30cef7e158016c7d799dab0836750f5193b2997dea90698260da +size 47067 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png new file mode 100644 index 0000000000..9a5f939b49 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92888d4d51a087f628d2c0604d0f02c3a58e2eca5c1e41d1dd01884afb1c1e6a +size 65549 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png new file mode 100644 index 0000000000..3a76a16c3e --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1998f0764fd6706169015fecbe7958f5ea88ccf6718c6fcc31b50259213eda69 +size 65612 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_de.png new file mode 100644 index 0000000000..b307d30172 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dce718324779855609745640fccecda621d121e61186915c626b4f8cd4e8693e +size 62663 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_de.png new file mode 100644 index 0000000000..6432c76e48 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffb5c13b625568456542d7405e9f8f05ebe986de32587c68fbcd7c356cd30cb3 +size 27683 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_de.png new file mode 100644 index 0000000000..5d8f1260f7 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57ba25b77977622a483522f5e360fb9763e4c089a8576d3b51b611a463e81d7c +size 51821 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_de.png new file mode 100644 index 0000000000..c005294209 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0c524cf2a0ebd4afd7cf3517b6a10a8d7aef0f3b5dfd9f83438ac7983e1ca18 +size 52459 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_de.png new file mode 100644 index 0000000000..510202c600 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8dc0ed7717de76041c6a5e9c32c3246039a8881ced121276b58b3012bbfb4096 +size 52718 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_de.png new file mode 100644 index 0000000000..fbbf3768e6 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4919373598bd77b7aa9e3aebad6abf4f8ddcf0123894507d76ce63157d347ea7 +size 53335 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_de.png new file mode 100644 index 0000000000..e0478af982 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b4a7e16a3c70933cc7f4ef68636df5d1669789500690f17a5a25f122f9f50b2 +size 25412 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_de.png new file mode 100644 index 0000000000..98d9beba84 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65020e3887540431951a3e99ce31e19dc401b4bbc232b16ded6e59d51f1712c9 +size 53206 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png new file mode 100644 index 0000000000..fbbf3768e6 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4919373598bd77b7aa9e3aebad6abf4f8ddcf0123894507d76ce63157d347ea7 +size 53335 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png new file mode 100644 index 0000000000..579756c731 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73fa1e4a25773720a0e9999b293488017c854576f40cc738fb3b67b59f2b1f05 +size 54167 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png new file mode 100644 index 0000000000..3f12de9672 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:739a7daec14bf01495a99e7e9584e3fdf4a26b1a7135cb0a109d32d275ab4344 +size 45484 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_de.png new file mode 100644 index 0000000000..d83fa83f95 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d80cbcafde684e8c85e36c1106f4cf3d945856c6df6c4455f6d8f1d2b1ffe459 +size 45172 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_de.png new file mode 100644 index 0000000000..5f861eda69 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ed8de485d7c5d33e08ed500600848b29c49d03c8f51de3484781c05963eb34f +size 47813 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_de.png new file mode 100644 index 0000000000..481cc91dee --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:658a968e9ca2d1f55766a45c6c101e136eafefe1c511d22f8368ae42cc5319eb +size 52820 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_de.png new file mode 100644 index 0000000000..d1ce6902de --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90db4ee471ec887f00a9e580ef839a4611216107ec615da90330b7d6be276b77 +size 68316 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_de.png new file mode 100644 index 0000000000..1d2eff636f --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9488bea7d8ea64ac2d2987dcf69b4a51bfb6b81e33b1035195860cc90ae9f291 +size 67707 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_de.png new file mode 100644 index 0000000000..6f1dca9c23 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbf7bda1bff05828fe71045a012b8bcc1f4c047256d8aea6f8f8579e08295dea +size 68546 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png new file mode 100644 index 0000000000..9632558d7b --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e905e5db59825bd332e89d69fc741c4146d0e6f8bdeab428dbc0e6eb27f3341 +size 49369 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png new file mode 100644 index 0000000000..3f1bf5f183 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d32e9542eb673f6e4f0f05ad017615f0c3274683e48f3ec13277e2d98d4db0f +size 68200 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png new file mode 100644 index 0000000000..1b18135ef5 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dd6427f42936ef21702492e5e96a7abaa6873edde04169603ed2124d76f4984 +size 68323 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_de.png new file mode 100644 index 0000000000..e04844391b --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88d3cb4770828935c271cc10fc436c85f0af19bf77a5f58a6abd6fde1af367ec +size 65168 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_de.png new file mode 100644 index 0000000000..1e24950be3 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99ae8ce6973aeacb8d1054722038b9840365b239569f6dbee5c2f234e84c14d3 +size 28626 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_de.png new file mode 100644 index 0000000000..fa87fbe737 --- /dev/null +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0c6701f9c4faa4495cd92e7414821f39f9adc3d3f755d21302a5c66cab6f5e3 +size 53331 diff --git a/screenshots/de/libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_de.png b/screenshots/de/libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_de.png index b8b796ace4..cd461a5e12 100644 --- a/screenshots/de/libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_de.png +++ b/screenshots/de/libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3632264ac1f406dfdd2d376c033741d2661ebf76b3b8f0ee150e108d6e85740 -size 27940 +oid sha256:0406efd19b2e8c9d83708af8669b8d2e8aaafef335eaef972e363e85589ccc56 +size 22171 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 758b77c7ee..a757e04ca0 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,80 +1,80 @@ // 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",20420,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20427,], ["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_0_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20420,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20420,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20420,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20420,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20420,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20420,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20420,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20420,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20420,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20420,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20420,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20427,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20427,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20427,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20427,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20427,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20427,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20427,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20427,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20427,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20427,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20427,], ["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,], -["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20420,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20420,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20427,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20427,], ["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",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20420,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20427,], ["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",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20420,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20420,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20420,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20420,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20420,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20420,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20420,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20420,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20420,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20427,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20427,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20427,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20427,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20427,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20427,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20427,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20427,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20427,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20420,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20420,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20420,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20420,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20420,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20427,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20427,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20427,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20427,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20427,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20420,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20427,], ["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",20420,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20427,], ["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",20420,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20427,], ["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",20420,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20427,], ["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",20420,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20427,], ["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,], @@ -84,19 +84,19 @@ 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","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_7_en","",20420,], -["features.messages.impl.attachments.preview_AttachmentsView_8_en","",20420,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_4_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_5_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_6_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_7_en","",20427,], +["features.messages.impl.attachments.preview_AttachmentsView_8_en","",20427,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en",0,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20420,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20427,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Day_0_en","libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Night_0_en",0,], ["libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Day_1_en","libraries.designsystem.components.avatar_AvatarRowLastOnTopRtl_Night_1_en",0,], @@ -123,22 +123,22 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20420,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20427,], ["libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en","libraries.designsystem.atomic.atoms_BetaLabel_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",20420,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20420,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20420,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20420,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20420,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20420,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20420,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20427,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20427,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20427,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20427,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20427,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20427,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20427,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20420,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20420,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20420,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20420,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20420,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20427,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20427,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20427,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20427,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20427,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -148,133 +148,133 @@ export const screenshots = [ ["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",20420,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20420,], +["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",20427,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20427,], ["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_5_en","features.messages.impl.timeline.components_CallMenuItem_Night_5_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",20420,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20420,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20420,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20420,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20420,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20420,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20427,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20427,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20427,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20427,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20427,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20427,], ["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_5_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_5_en",0,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20420,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20420,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20420,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20420,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20420,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20420,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20420,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20427,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20427,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20427,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20427,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20427,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20427,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20427,], ["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",20420,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20420,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20420,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20420,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20420,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20427,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20427,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20427,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20427,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20427,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20420,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20427,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20420,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20420,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20420,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20420,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20420,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20420,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20420,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20420,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20427,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20427,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20427,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20427,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20427,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20427,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20427,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20427,], ["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",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_6_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_6_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_7_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_7_en",20420,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_8_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_8_en",20420,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20420,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_6_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_6_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_7_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_7_en",20427,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_8_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_8_en",20427,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20427,], ["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,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20420,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20420,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20420,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20420,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20420,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20420,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20427,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20427,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20427,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20427,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20427,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20427,], ["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_ConnectivityIndicator_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicator_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_CounterAtom_Day_0_en","libraries.designsystem.atomic.atoms_CounterAtom_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20420,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20420,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20420,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20420,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20420,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20420,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20420,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20420,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20420,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20420,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20420,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20420,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20420,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20420,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20420,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20420,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20420,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20420,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20420,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20420,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20427,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20427,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20427,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20427,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20427,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20427,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20427,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20427,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20427,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20427,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20427,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20427,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20427,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20427,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20427,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20427,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20427,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20427,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20427,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20427,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_1_en",0,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20420,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20420,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20420,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20420,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20420,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20420,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20420,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20427,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20427,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20427,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20427,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20427,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20427,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20427,], ["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",20420,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20420,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20420,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20427,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20427,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20427,], ["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",20420,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20427,], ["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",20420,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20420,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20420,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20420,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20420,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20420,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20420,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20420,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20427,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20427,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20427,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20427,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20427,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20427,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20427,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20427,], ["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,19 +289,19 @@ 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",20420,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20420,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20420,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20420,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20420,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",0,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",0,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",0,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",0,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",0,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20420,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20420,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",0,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20427,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20427,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20427,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20427,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20427,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20430,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20430,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20430,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20430,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20430,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20427,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20427,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20430,], ["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,], @@ -312,14 +312,14 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["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.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20420,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20420,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20427,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20427,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_2_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_2_en",0,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_3_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_3_en",0,], ["libraries.ui.common.nodes_EmptyView_Day_0_en","libraries.ui.common.nodes_EmptyView_Night_0_en",0,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20420,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20420,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20420,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20427,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20427,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20427,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.designsystem.components_ExpandableBottomSheetLayout_en","",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], @@ -338,43 +338,43 @@ 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",20420,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20420,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20420,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20427,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20427,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20427,], ["features.messages.impl.timeline.components_FocusedEvent_Day_0_en","features.messages.impl.timeline.components_FocusedEvent_Night_0_en",0,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.forward.impl_ForwardMessagesView_Day_0_en","features.forward.impl_ForwardMessagesView_Night_0_en",0,], ["features.forward.impl_ForwardMessagesView_Day_1_en","features.forward.impl_ForwardMessagesView_Night_1_en",0,], ["features.forward.impl_ForwardMessagesView_Day_2_en","features.forward.impl_ForwardMessagesView_Night_2_en",0,], -["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20420,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20420,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20427,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20427,], ["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,], ["libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPage_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPage_Night_0_en",0,], -["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20420,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20420,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20420,], -["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20420,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20420,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20427,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20427,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20427,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20427,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20427,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20420,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20420,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20427,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20427,], ["features.home.impl_HomeView_Day_11_en","features.home.impl_HomeView_Night_11_en",0,], ["features.home.impl_HomeView_Day_12_en","features.home.impl_HomeView_Night_12_en",0,], -["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20420,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20420,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20420,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20420,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20420,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20420,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20420,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20420,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20420,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20420,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20420,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20420,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20427,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20427,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20427,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20427,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20427,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20427,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20427,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20427,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20427,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20427,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20427,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20427,], ["libraries.designsystem.theme.components_HorizontalDivider_Dividers_en","",0,], ["libraries.designsystem.ruler_HorizontalRuler_Day_0_en","libraries.designsystem.ruler_HorizontalRuler_Night_0_en",0,], ["libraries.designsystem.theme.components_IconButton_Buttons_en","",0,], @@ -387,8 +387,8 @@ export const screenshots = [ ["appicon.enterprise_Icon_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",20420,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20420,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20427,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20427,], ["libraries.mediaviewer.impl.gallery.ui_ImageItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_ImageItemView_Night_0_en",0,], ["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,], @@ -396,109 +396,109 @@ export const screenshots = [ ["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",20420,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20427,], ["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",20420,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20427,], ["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",20420,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20427,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20420,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20420,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20427,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20427,], ["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.media_InitialsAvatarBitmapGenerator_Day_0_en","libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Night_0_en",0,], -["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20420,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20420,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20420,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20427,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20427,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20427,], ["features.invitepeople.impl_InvitePeopleView_Day_2_en","features.invitepeople.impl_InvitePeopleView_Night_2_en",0,], ["features.invitepeople.impl_InvitePeopleView_Day_3_en","features.invitepeople.impl_InvitePeopleView_Night_3_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20420,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20420,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20420,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20420,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20427,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20427,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20427,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20427,], ["features.invitepeople.impl_InvitePeopleView_Day_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20420,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20420,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20420,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20420,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20420,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20420,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20420,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20420,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20427,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20427,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20427,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20427,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20427,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20427,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20427,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20427,], ["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",20420,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20420,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20420,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20420,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20420,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20427,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20427,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20427,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20427,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20420,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20420,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20427,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20427,], ["features.leaveroom.impl_LeaveRoomView_Day_0_en","features.leaveroom.impl_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20420,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20420,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20420,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20420,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20420,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20420,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20420,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20420,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20427,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20427,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20427,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20427,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20427,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20427,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20427,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20427,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress_Indicators_en","",0,], ["features.messages.impl.link_LinkView_Day_0_en","features.messages.impl.link_LinkView_Night_0_en",0,], -["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20420,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20427,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ListDialog_Day_0_en","libraries.designsystem.components.dialogs_ListDialog_Night_0_en",0,], ["libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en","",0,], @@ -553,38 +553,38 @@ 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",20420,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20420,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20420,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20420,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20427,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20427,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20427,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20427,], ["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",20420,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20420,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20420,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20420,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20420,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20420,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20420,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20420,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20420,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20420,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20420,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20420,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20420,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20420,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20420,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20420,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20420,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20420,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20420,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20420,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20420,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20420,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20420,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20420,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20420,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20427,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20427,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20427,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20427,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20427,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20427,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20427,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20427,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20427,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20427,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20427,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20427,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20427,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20427,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20427,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20427,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20427,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20427,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20427,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20427,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20427,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20427,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20427,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20427,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20427,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20420,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20427,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -597,22 +597,22 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20420,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20420,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20427,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20427,], ["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",0,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20420,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20420,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20427,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20427,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -620,14 +620,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20420,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20420,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20427,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20427,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20420,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20427,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20420,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20427,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -641,7 +641,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",20420,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20427,], ["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_1_en","features.messages.impl.timeline.components_MessageEventBubble_Night_1_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_2_en","features.messages.impl.timeline.components_MessageEventBubble_Night_2_en",0,], @@ -650,7 +650,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_5_en","features.messages.impl.timeline.components_MessageEventBubble_Night_5_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_6_en","features.messages.impl.timeline.components_MessageEventBubble_Night_6_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20420,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20427,], ["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,], @@ -658,137 +658,137 @@ 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.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20420,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20420,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20420,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20420,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20420,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20420,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20420,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20420,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20420,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20420,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20420,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20420,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20420,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20420,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20427,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20427,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20427,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20427,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20427,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20427,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20427,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20427,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20427,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20427,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20427,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20427,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20427,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20427,], ["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",20420,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20427,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], -["features.preferences.impl.root_MultiAccountSection_Day_0_en","features.preferences.impl.root_MultiAccountSection_Night_0_en",20420,], +["features.preferences.impl.root_MultiAccountSection_Day_0_en","features.preferences.impl.root_MultiAccountSection_Night_0_en",20427,], ["libraries.designsystem.components.dialogs_MultipleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_MultipleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_MultipleSelectionDialog_Night_0_en",0,], ["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,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20420,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20420,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20420,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20427,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20427,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20427,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20420,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20420,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20427,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20427,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], -["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20420,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20427,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_12_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_12_en",0,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_13_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_13_en",0,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20420,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20420,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20427,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20427,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonSmall_Buttons_en","",0,], -["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20420,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20420,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20420,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20420,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20420,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20420,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20427,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",0,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20427,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20427,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20427,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20427,], ["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",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20420,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20420,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20427,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20427,], ["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",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20420,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20420,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20420,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20420,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20420,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20420,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20427,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20427,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20427,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20427,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20427,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20427,], ["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",20420,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20420,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20420,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20420,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20420,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20427,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20427,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20427,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20427,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20427,], ["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",20420,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20420,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20420,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20420,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20420,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20420,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20420,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20420,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20420,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20420,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20420,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20427,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20427,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20427,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20427,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20427,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20427,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20427,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20427,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20427,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20427,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20427,], ["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,], @@ -802,205 +802,206 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20420,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20420,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20420,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20420,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20427,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20427,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20427,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20427,], ["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","",20420,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20420,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20427,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20427,], ["libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20420,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20420,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20420,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20420,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20420,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20420,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20420,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20420,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20420,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20420,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20420,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20420,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20420,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20420,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20420,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20420,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20420,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20420,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20420,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20420,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20420,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20427,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20427,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20427,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20427,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20427,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20427,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20427,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20427,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20427,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20427,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20427,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20427,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20427,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20427,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20427,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20427,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20427,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20427,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20427,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20427,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20427,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20420,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20420,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20427,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20427,], ["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",20420,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20420,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20420,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20420,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20420,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20420,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20420,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20427,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20427,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20427,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20427,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20427,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20427,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20427,], ["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",20420,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20420,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20420,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20420,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20420,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20420,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20420,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20420,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20420,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20420,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20420,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20420,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20420,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20420,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20420,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20420,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20420,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20427,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20427,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20427,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20427,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20427,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20427,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20427,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20427,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20427,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20427,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20427,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20427,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20427,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20427,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20427,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20427,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20427,], ["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",20420,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20420,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20420,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20420,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20420,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20427,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20427,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20427,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20427,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20427,], ["libraries.matrix.ui.room.address_RoomAddressField_Day_0_en","libraries.matrix.ui.room.address_RoomAddressField_Night_0_en",0,], ["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",20420,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20420,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20420,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",20420,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_8_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_8_en",20420,], -["features.roomdetails.impl_RoomDetails_0_en","",20420,], -["features.roomdetails.impl_RoomDetails_10_en","",20420,], -["features.roomdetails.impl_RoomDetails_11_en","",20420,], -["features.roomdetails.impl_RoomDetails_12_en","",20420,], -["features.roomdetails.impl_RoomDetails_13_en","",20420,], -["features.roomdetails.impl_RoomDetails_14_en","",20420,], -["features.roomdetails.impl_RoomDetails_15_en","",20420,], -["features.roomdetails.impl_RoomDetails_16_en","",20420,], -["features.roomdetails.impl_RoomDetails_17_en","",20420,], -["features.roomdetails.impl_RoomDetails_18_en","",20420,], -["features.roomdetails.impl_RoomDetails_19_en","",20420,], -["features.roomdetails.impl_RoomDetails_1_en","",20420,], -["features.roomdetails.impl_RoomDetails_2_en","",20420,], -["features.roomdetails.impl_RoomDetails_3_en","",20420,], -["features.roomdetails.impl_RoomDetails_4_en","",20420,], -["features.roomdetails.impl_RoomDetails_5_en","",20420,], -["features.roomdetails.impl_RoomDetails_6_en","",20420,], -["features.roomdetails.impl_RoomDetails_7_en","",20420,], -["features.roomdetails.impl_RoomDetails_8_en","",20420,], -["features.roomdetails.impl_RoomDetails_9_en","",20420,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20420,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20420,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20420,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20420,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20420,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20420,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20420,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20420,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20420,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20427,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20427,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20427,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20427,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20430,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20430,], +["features.roomdetails.impl_RoomDetails_0_en","",20427,], +["features.roomdetails.impl_RoomDetails_10_en","",20427,], +["features.roomdetails.impl_RoomDetails_11_en","",20427,], +["features.roomdetails.impl_RoomDetails_12_en","",20427,], +["features.roomdetails.impl_RoomDetails_13_en","",20427,], +["features.roomdetails.impl_RoomDetails_14_en","",20427,], +["features.roomdetails.impl_RoomDetails_15_en","",20427,], +["features.roomdetails.impl_RoomDetails_16_en","",20427,], +["features.roomdetails.impl_RoomDetails_17_en","",20427,], +["features.roomdetails.impl_RoomDetails_18_en","",20427,], +["features.roomdetails.impl_RoomDetails_19_en","",20427,], +["features.roomdetails.impl_RoomDetails_1_en","",20427,], +["features.roomdetails.impl_RoomDetails_2_en","",20427,], +["features.roomdetails.impl_RoomDetails_3_en","",20427,], +["features.roomdetails.impl_RoomDetails_4_en","",20427,], +["features.roomdetails.impl_RoomDetails_5_en","",20427,], +["features.roomdetails.impl_RoomDetails_6_en","",20427,], +["features.roomdetails.impl_RoomDetails_7_en","",20427,], +["features.roomdetails.impl_RoomDetails_8_en","",20427,], +["features.roomdetails.impl_RoomDetails_9_en","",20427,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20427,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20427,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20427,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20427,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20427,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20427,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20427,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20427,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20427,], ["features.home.impl.components_RoomListContentView_Day_2_en","features.home.impl.components_RoomListContentView_Night_2_en",0,], -["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20420,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20420,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20420,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20420,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20420,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20420,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20420,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20420,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20420,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20427,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20427,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20427,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20427,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20427,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20427,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20427,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20427,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20427,], ["features.home.impl.search_RoomListSearchContent_Day_0_en","features.home.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20420,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",0,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20420,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20420,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20427,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20430,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20427,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20427,], ["features.roommembermoderation.impl_RoomMemberModerationView_Day_9_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20420,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20420,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20420,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20420,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20420,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20420,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20420,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20420,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20427,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20427,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20427,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20427,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20427,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20427,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20427,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20427,], ["features.home.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.home.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_0_en","features.home.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_10_en","features.home.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -1023,14 +1024,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20420,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20420,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20427,], +["features.home.impl.components_RoomSummaryRow_Day_36_en","features.home.impl.components_RoomSummaryRow_Night_36_en",0,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_3_en","features.home.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_4_en","features.home.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_5_en","features.home.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -1038,105 +1041,105 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_7_en","features.home.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_8_en","features.home.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_9_en","features.home.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20420,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20420,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20420,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20427,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20427,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20427,], ["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",20420,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20420,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20420,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20420,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20427,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20427,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20427,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20427,], ["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","",20420,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20427,], ["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,], ["libraries.designsystem.theme.components_SearchFieldsDark_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchFieldsLight_Search_views_en","",0,], -["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20420,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20420,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20420,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20420,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20420,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20420,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20420,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20420,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20420,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20420,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20420,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20420,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20420,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",0,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",0,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20427,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20427,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20427,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20427,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20427,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20427,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20427,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20427,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20427,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20427,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20427,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20427,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20427,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20430,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20430,], ["libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_0_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_1_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_1_en",0,], @@ -1150,11 +1153,11 @@ export const screenshots = [ ["libraries.matrix.ui.components_SelectedUser_Day_1_en","libraries.matrix.ui.components_SelectedUser_Night_1_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",20420,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20420,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20420,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20420,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20420,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20427,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20427,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20427,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20427,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20427,], ["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,], @@ -1164,27 +1167,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",20420,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20420,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20420,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20420,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20420,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20420,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20420,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20420,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20427,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20427,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20427,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20427,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20427,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20427,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20427,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20427,], ["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",20420,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20420,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20420,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20420,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20420,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20420,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20420,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20420,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20420,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20420,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20427,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20427,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20427,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20427,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20427,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20427,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20427,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20427,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20427,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20427,], ["libraries.designsystem.components_SimpleModalBottomSheet_Day_0_en","libraries.designsystem.components_SimpleModalBottomSheet_Night_0_en",0,], ["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,], @@ -1194,102 +1197,102 @@ 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",20420,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20427,], ["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,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], -["features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en","features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en",20420,], +["features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en","features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en",20427,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20420,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20420,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20420,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20427,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20427,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20427,], ["libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Day_0_en","libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Night_0_en",0,], ["libraries.matrix.ui.components_SpaceMembersView_Day_0_en","libraries.matrix.ui.components_SpaceMembersView_Night_0_en",0,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20420,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20420,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20420,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20420,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20420,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20420,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20420,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20420,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20420,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20420,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20420,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20420,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20427,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20427,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20427,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20427,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20427,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20427,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20427,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20427,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20427,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20427,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20427,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20427,], ["libraries.designsystem.modifiers_SquareSizeModifierInsideSquare_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], -["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20420,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20420,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20420,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20420,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20420,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20420,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20420,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20427,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20427,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20427,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20427,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20427,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20427,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20427,], ["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",20420,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20427,], ["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",20420,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20427,], ["libraries.designsystem.components.avatar.internal_TextAvatar_Avatars_en","",0,], ["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",20420,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20420,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20420,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20420,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20420,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20420,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20420,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20420,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20420,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20420,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20420,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20420,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20420,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20420,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20420,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20427,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20427,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20427,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20427,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20427,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20427,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20427,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20427,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20427,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20427,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20427,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20427,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20427,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20427,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20427,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], -["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20420,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20420,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20427,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20427,], ["libraries.designsystem.components.list_TextFieldListItemEmpty_Text_field_List_item_-_empty_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItemTextFieldValue_Text_field_List_item_-_textfieldvalue_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItem_Text_field_List_item_-_text_List_items_en","",0,], @@ -1301,16 +1304,16 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_3_en","libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_3_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,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20420,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20420,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20420,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20420,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20420,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20427,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20427,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20427,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20427,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20427,], ["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",20420,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20420,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20427,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20427,], ["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_TimelineEventTimestampView_Day_7_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_7_en",0,], @@ -1320,18 +1323,18 @@ 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",20420,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20427,], ["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",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20420,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20427,], ["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,], @@ -1339,18 +1342,18 @@ 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",20420,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20420,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20427,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20427,], ["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_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20420,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20420,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20420,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20427,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20427,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20427,], ["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",20420,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20420,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20427,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20427,], ["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,], @@ -1359,41 +1362,41 @@ 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",20420,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20427,], ["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",20420,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20427,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20420,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20427,], ["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","",20420,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20427,], ["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",20420,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20420,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20427,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20427,], ["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",20420,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20427,], ["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",20420,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20420,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20420,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20420,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20427,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20427,], ["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",20420,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20420,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20427,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20427,], ["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",20420,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20427,], ["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,], @@ -1402,8 +1405,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",20420,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20420,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20427,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20427,], ["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,], @@ -1418,8 +1421,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",20420,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20420,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20427,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20427,], ["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,], @@ -1442,85 +1445,85 @@ 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",20420,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20420,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20427,], ["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",20420,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20420,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20420,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20420,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20420,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20420,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20420,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20420,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20427,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20427,], ["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",20420,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20427,], ["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",20420,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20427,], ["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",20420,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",20427,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.components.avatar.internal_TombstonedRoomAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TopAppBarStr_App_Bars_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",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20420,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20420,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20427,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20427,], ["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",20420,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20420,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20420,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20420,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20420,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20420,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20427,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20427,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20427,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20427,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20427,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20427,], ["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","",20420,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20427,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar.internal_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar.internal_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20420,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20420,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20420,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20420,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20427,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20427,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20427,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20427,], ["features.startchat.impl.components_UserListView_Day_3_en","features.startchat.impl.components_UserListView_Night_3_en",0,], ["features.startchat.impl.components_UserListView_Day_4_en","features.startchat.impl.components_UserListView_Night_4_en",0,], ["features.startchat.impl.components_UserListView_Day_5_en","features.startchat.impl.components_UserListView_Night_5_en",0,], ["features.startchat.impl.components_UserListView_Day_6_en","features.startchat.impl.components_UserListView_Night_6_en",0,], -["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20420,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20427,], ["features.startchat.impl.components_UserListView_Day_8_en","features.startchat.impl.components_UserListView_Night_8_en",0,], -["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20420,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20427,], ["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_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20420,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20420,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20420,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20420,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20420,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20420,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20420,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20420,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20420,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20420,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20420,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20420,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20427,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20427,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20427,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20427,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20427,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20427,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20427,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20427,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20427,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20427,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20427,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20427,], ["features.verifysession.impl.ui_VerificationUserProfileContent_Day_0_en","features.verifysession.impl.ui_VerificationUserProfileContent_Night_0_en",0,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_1_en",0,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20420,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20420,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20427,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20427,], ["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,], ["features.viewfolder.impl.file_ViewFileView_Day_2_en","features.viewfolder.impl.file_ViewFileView_Night_2_en",0,], -["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20420,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20427,], ["features.viewfolder.impl.file_ViewFileView_Day_4_en","features.viewfolder.impl.file_ViewFileView_Night_4_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_5_en","features.viewfolder.impl.file_ViewFileView_Night_5_en",0,], ["features.viewfolder.impl.folder_ViewFolderView_Day_0_en","features.viewfolder.impl.folder_ViewFolderView_Night_0_en",0,], diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en.png index 9f58184f04..a01340b169 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f2d14cff976468c7a2408c9e9d0dabcfbed4a0cfb1406f71db459f660305269 -size 24794 +oid sha256:f4467db8409103caf24b97dab28e5280da60ca420d951d689d353ebaf63841bf +size 24737 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en.png index da8873613c..e7c94c7669 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b904f634f9668cc207a922979e0b3abc92c586f3986cf3c57630da8aa2eb22fe -size 23835 +oid sha256:fd96a05649a403454636d07168398476b25aae4aaad76cac4e41265478ec4791 +size 23768 From 5d69f289f5a98ed4e6244a1eafe852d70baea00e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 8 Dec 2025 09:54:01 +0100 Subject: [PATCH 15/64] Add a way to configure value of android.packaging.jniLibs.useLegacyPackaging from command line. --- app/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2464155cb4..322ad47911 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -199,6 +199,10 @@ android { resources.pickFirsts += setOf( "META-INF/versions/9/OSGI-INF/MANIFEST.MF", ) + + jniLibs { + useLegacyPackaging = project.findProperty("useLegacyPackaging")?.toString()?.toBoolean() + } } } From 549054037a558d5e8057ac474bf2ef62790886c3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:26:21 +0000 Subject: [PATCH 16/64] chore(deps): update peter-evans/create-pull-request action to v7.0.11 --- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 073c075502..c928434b73 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -36,7 +36,7 @@ jobs: ./tools/localazy/importSupportedLocalesFromLocalazy.py ./tools/test/generateAllScreenshots.py - name: Create Pull Request for Strings - uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9 + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 with: token: ${{ secrets.DANGER_GITHUB_API_TOKEN }} commit-message: Sync Strings from Localazy diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index ca42b8fbe6..b603049a04 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -23,7 +23,7 @@ jobs: - name: Run SAS String script run: ./tools/sas/import_sas_strings.py - name: Create Pull Request for SAS Strings - uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9 + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 with: commit-message: Sync SAS Strings title: Sync SAS Strings From 38d17b4ac47e21dc57c126261bf01997d6e1949e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 8 Dec 2025 14:28:29 +0100 Subject: [PATCH 17/64] Trigger CI From f2622e2ee9ea6edb0c676e894a73d70ce85c27dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:50:03 +0100 Subject: [PATCH 18/64] Merge pull request #5853 from element-hq/renovate/io.sentry-sentry-android-8.x fix(deps): update dependency io.sentry:sentry-android to v8.28.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 71a1a097dc..e00585b9ee 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -217,7 +217,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.26.0" -sentry = "io.sentry:sentry-android:8.27.1" +sentry = "io.sentry:sentry-android:8.28.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.29.2" From 374c43794ad93dab45cd2cf68e0aca17e183b506 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:16:36 +0000 Subject: [PATCH 19/64] fix(deps): update dependency io.mockk:mockk to v1.14.7 (#5866) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e00585b9ee..c0dd448c17 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -160,7 +160,7 @@ test_corektx = { module = "androidx.test:core-ktx", version.ref = "test_core" } test_arch_core = "androidx.arch.core:core-testing:2.2.0" test_junit = "junit:junit:4.13.2" test_runner = "androidx.test:runner:1.7.0" -test_mockk = "io.mockk:mockk:1.14.6" +test_mockk = "io.mockk:mockk:1.14.7" test_konsist = "com.lemonappdev:konsist:0.17.3" test_turbine = "app.cash.turbine:turbine:1.2.1" test_truth = "com.google.truth:truth:1.4.5" From 2030e79f2e2458a070debaa9f4aed89ac8b9649e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:18:33 +0000 Subject: [PATCH 20/64] Update showkase to v1.0.5 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0dd448c17..00c7859895 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ serialization_json = "1.9.0" #other coil = "3.3.0" # Rollback to 1.0.4, 1.0.5 has this issue: https://github.com/airbnb/Showkase/issues/420 -showkase = "1.0.4" +showkase = "1.0.5" appyx = "1.7.1" sqldelight = "2.2.1" wysiwyg = "2.40.0" From eff79d0b8879b1a5977927f024b0f55cc5071dc8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 8 Dec 2025 15:28:38 +0100 Subject: [PATCH 21/64] Add accessibility to the "sending" picto. --- .../android/features/home/impl/components/RoomSummaryRow.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index da0f47ba05..b722c63622 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -243,7 +243,7 @@ private fun NameAndTimestampRow( Icon( modifier = Modifier.size(16.dp), imageVector = CompoundIcons.Time(), - contentDescription = null, + contentDescription = stringResource(CommonStrings.common_sending), tint = ElementTheme.colors.iconTertiary, ) } @@ -252,6 +252,7 @@ private fun NameAndTimestampRow( Icon( modifier = Modifier.size(16.dp), imageVector = CompoundIcons.ErrorSolid(), + // The last message contains the error. contentDescription = null, tint = ElementTheme.colors.iconCriticalPrimary, ) From d0ba02dd7ecf92325b111dcce902f2b233ae6e07 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Mon, 8 Dec 2025 20:19:15 +0000 Subject: [PATCH 22/64] Add alert to encrypted rooms with visible history (Android). (#5709) * feat: Add visible history alert to encrypted rooms. - Adds a dismissable alert that is displayed whenever the user opens a room with `history_visibility` != `joined`. When cleared, this is recorded in the app's data store. - When opening a room with `history_visibility` = `joined`, this flag is cleared.` Issue: https://github.com/element-hq/element-meta/issues/2875 * chore: Fix linting issues. * feat: Move alert showing logic into state presenter. * chore: Fix linting issues. * tests: Fixup tests. * feat: Use real link. * chore: Update license header. * chore: Add (c) to license headers. * chore: Add `.` to license header. * feat: Lock alert behind history sharing developer setting. * ci: Trigger record screenshots * feat: Create repo key using session ID for multi-account support. * feat: Use session ID hash for constructing data store. * tests: Correct and update tests. * tests: Update snapshots. * feat: Prevent identity alert from displaying with history visibility alert. * feat: Tidy up HistoryVisibleStatePresenter logic, update previews. * chore: Remove unused import. * chore: Update screenshots. * feat: Add translation string. * chore: Remove redundant temporary translation file. --- .../android/appconfig/LearnMoreConfig.kt | 1 + features/messages/impl/build.gradle.kts | 1 + .../messages/impl/MessagesPresenter.kt | 4 + .../features/messages/impl/MessagesState.kt | 2 + .../messages/impl/MessagesStateProvider.kt | 19 +++ .../features/messages/impl/MessagesView.kt | 16 ++- ...HistoryVisibleAcknowledgementRepository.kt | 48 +++++++ .../historyvisible/HistoryVisibleEvent.kt | 12 ++ .../historyvisible/HistoryVisibleState.kt | 13 ++ .../HistoryVisibleStatePresenter.kt | 62 +++++++++ .../HistoryVisibleStateProvider.kt | 25 ++++ .../historyvisible/HistoryVisibleStateView.kt | 81 +++++++++++ .../MessagesViewWithHistoryVisiblePreview.kt | 42 ++++++ .../messages/impl/di/MessagesBindsModule.kt | 5 + .../messages/impl/MessagesPresenterTest.kt | 2 + ...HistoryVisibleAcknowledgementRepository.kt | 42 ++++++ .../HistoryVisibleStatePresenterTest.kt | 127 ++++++++++++++++++ .../tests/konsist/KonsistPreviewTest.kt | 1 + ...sible_HistoryVisibleStateView_Day_0_en.png | 3 + ...sible_HistoryVisibleStateView_Day_1_en.png | 3 + ...ble_HistoryVisibleStateView_Night_0_en.png | 3 + ...ble_HistoryVisibleStateView_Night_1_en.png | 3 + ...essagesViewWithHistoryVisible_Day_0_en.png | 3 + ...essagesViewWithHistoryVisible_Day_1_en.png | 3 + ...sagesViewWithHistoryVisible_Night_0_en.png | 3 + ...sagesViewWithHistoryVisible_Night_1_en.png | 3 + ...s.messages.impl_MessagesView_Day_10_en.png | 3 + ...s.messages.impl_MessagesView_Day_11_en.png | 3 + ...s.messages.impl_MessagesView_Day_12_en.png | 3 + ...messages.impl_MessagesView_Night_10_en.png | 3 + ...messages.impl_MessagesView_Night_11_en.png | 3 + ...messages.impl_MessagesView_Night_12_en.png | 3 + 32 files changed, 541 insertions(+), 4 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleAcknowledgementRepository.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleEvent.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleState.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenter.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateProvider.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateView.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/MessagesViewWithHistoryVisiblePreview.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/FakeHistoryVisibleAcknowledgementRepository.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenterTest.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_12_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_12_en.png diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/LearnMoreConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/LearnMoreConfig.kt index c0c152142e..855586892a 100644 --- a/appconfig/src/main/kotlin/io/element/android/appconfig/LearnMoreConfig.kt +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/LearnMoreConfig.kt @@ -13,4 +13,5 @@ object LearnMoreConfig { const val DEVICE_VERIFICATION_URL: String = "https://element.io/help#encryption-device-verification" const val SECURE_BACKUP_URL: String = "https://element.io/help#encryption5" const val IDENTITY_CHANGE_URL: String = "https://element.io/help#encryption18" + const val HISTORY_VISIBLE_URL: String = "https://element.io/en/help#e2ee-history-sharing" } diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index ad6562a83c..eb8aff66ed 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -68,6 +68,7 @@ dependencies { implementation(libs.jsoup) implementation(libs.androidx.constraintlayout) implementation(libs.androidx.constraintlayout.compose) + implementation(libs.androidx.datastore.preferences) implementation(libs.androidx.media3.exoplayer) implementation(libs.androidx.media3.ui) implementation(libs.sigpwned.emoji4j) 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 e912722c6d..a5b3106b3d 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 @@ -32,6 +32,7 @@ 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.ActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleState import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState import io.element.android.features.messages.impl.link.LinkState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvent @@ -107,6 +108,7 @@ class MessagesPresenter( @Assisted private val timelinePresenter: Presenter, private val timelineProtectionPresenter: Presenter, private val identityChangeStatePresenter: Presenter, + private val historyVisibleStatePresenter: Presenter, private val linkPresenter: Presenter, @Assisted private val actionListPresenter: Presenter, private val customReactionPresenter: Presenter, @@ -158,6 +160,7 @@ class MessagesPresenter( val timelineState = timelinePresenter.present() val timelineProtectionState = timelineProtectionPresenter.present() val identityChangeState = identityChangeStatePresenter.present() + val historyVisibleState = historyVisibleStatePresenter.present() val actionListState = actionListPresenter.present() val linkState = linkPresenter.present() val customReactionState = customReactionPresenter.present() @@ -278,6 +281,7 @@ class MessagesPresenter( timelineState = timelineState, timelineProtectionState = timelineProtectionState, identityChangeState = identityChangeState, + historyVisibleState = historyVisibleState, linkState = linkState, actionListState = actionListState, customReactionState = customReactionState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 9faf2f69eb..b9d86a6597 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerState import io.element.android.features.messages.impl.actionlist.ActionListState +import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleState import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState import io.element.android.features.messages.impl.link.LinkState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState @@ -40,6 +41,7 @@ data class MessagesState( val timelineState: TimelineState, val timelineProtectionState: TimelineProtectionState, val identityChangeState: IdentityChangeState, + val historyVisibleState: HistoryVisibleState, val linkState: LinkState, val actionListState: ActionListState, val customReactionState: CustomReactionState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 3a077e6cf0..7831265fd0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -14,7 +14,10 @@ import io.element.android.features.messages.api.timeline.voicemessages.composer. import io.element.android.features.messages.api.timeline.voicemessages.composer.aVoiceMessagePreviewState import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState +import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleState +import io.element.android.features.messages.impl.crypto.historyvisible.aHistoryVisibleState import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState +import io.element.android.features.messages.impl.crypto.identity.aRoomMemberIdentityStateChange import io.element.android.features.messages.impl.crypto.identity.anIdentityChangeState import io.element.android.features.messages.impl.link.LinkState import io.element.android.features.messages.impl.link.aLinkState @@ -48,6 +51,7 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.textcomposer.model.MessageComposerMode +import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown import io.element.android.libraries.textcomposer.model.aTextEditorStateRich import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -83,6 +87,19 @@ open class MessagesStateProvider : PreviewParameterProvider { timelineItems = aTimelineItemList(aTimelineItemTextContent()), ) ), + aMessagesState( + composerState = aMessageComposerState(textEditorState = aTextEditorStateMarkdown()), + identityChangeState = anIdentityChangeState(listOf(aRoomMemberIdentityStateChange())) + ), + aMessagesState( + composerState = aMessageComposerState(textEditorState = aTextEditorStateMarkdown()), + historyVisibleState = aHistoryVisibleState(showAlert = true) + ), + aMessagesState( + composerState = aMessageComposerState(textEditorState = aTextEditorStateMarkdown()), + identityChangeState = anIdentityChangeState(listOf(aRoomMemberIdentityStateChange())), + historyVisibleState = aHistoryVisibleState(showAlert = true) + ) ) } @@ -103,6 +120,7 @@ fun aMessagesState( ), timelineProtectionState: TimelineProtectionState = aTimelineProtectionState(), identityChangeState: IdentityChangeState = anIdentityChangeState(), + historyVisibleState: HistoryVisibleState = aHistoryVisibleState(), linkState: LinkState = aLinkState(), readReceiptBottomSheetState: ReadReceiptBottomSheetState = aReadReceiptBottomSheetState(), actionListState: ActionListState = anActionListState(), @@ -125,6 +143,7 @@ fun aMessagesState( voiceMessageComposerState = voiceMessageComposerState, timelineProtectionState = timelineProtectionState, identityChangeState = identityChangeState, + historyVisibleState = historyVisibleState, linkState = linkState, timelineState = timelineState, readReceiptBottomSheetState = readReceiptBottomSheetState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index a37710843d..5479836bb3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -53,6 +53,7 @@ import io.element.android.features.messages.api.timeline.voicemessages.composer. import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleStateView import io.element.android.features.messages.impl.crypto.identity.IdentityChangeStateView import io.element.android.features.messages.impl.link.LinkEvents import io.element.android.features.messages.impl.link.LinkView @@ -486,10 +487,17 @@ private fun MessagesViewComposerBottomSheetContents( // Do not show the identity change if user is composing a Rich message or is seeing suggestion(s). if (state.composerState.suggestions.isEmpty() && state.composerState.textEditorState is TextEditorState.Markdown) { - IdentityChangeStateView( - state = state.identityChangeState, - onLinkClick = onLinkClick, - ) + if (state.identityChangeState.roomMemberIdentityStateChanges.isNotEmpty()) { + IdentityChangeStateView( + state = state.identityChangeState, + onLinkClick = onLinkClick, + ) + } else { + HistoryVisibleStateView( + state = state.historyVisibleState, + onLinkClick = onLinkClick, + ) + } } val verificationViolation = state.identityChangeState.roomMemberIdentityStateChanges.firstOrNull { it.identityState == IdentityState.VerificationViolation diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleAcknowledgementRepository.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleAcknowledgementRepository.kt new file mode 100644 index 0000000000..1fa992fc3e --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleAcknowledgementRepository.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.hash.hash +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +interface HistoryVisibleAcknowledgementRepository { + fun hasAcknowledged(roomId: RoomId): Flow + suspend fun setAcknowledged(roomId: RoomId, value: Boolean) +} + +@ContributesBinding(SessionScope::class) +class DefaultHistoryVisibleAcknowledgementRepository( + sessionId: SessionId, + preferenceDataStoreFactory: PreferenceDataStoreFactory, +) : HistoryVisibleAcknowledgementRepository { + val store = + sessionId.value.hash().take(16).let { hash -> + preferenceDataStoreFactory.create("elementx_historyvisible_$hash") + } + + override fun hasAcknowledged(roomId: RoomId): Flow { + return store.data.map { prefs -> + val acknowledged = prefs[booleanPreferencesKey(roomId.value)] ?: false + acknowledged + } + } + + override suspend fun setAcknowledged(roomId: RoomId, value: Boolean) { + store.edit { prefs -> + prefs[booleanPreferencesKey(roomId.value)] = value + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleEvent.kt new file mode 100644 index 0000000000..775d9c00d4 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleEvent.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +sealed interface HistoryVisibleEvent { + data object Acknowledge : HistoryVisibleEvent +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleState.kt new file mode 100644 index 0000000000..3f980eb086 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleState.kt @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +data class HistoryVisibleState( + val showAlert: Boolean, + val eventSink: (HistoryVisibleEvent) -> Unit, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenter.kt new file mode 100644 index 0000000000..d76e567b3c --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenter.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import dev.zacsweers.metro.Inject +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.RoomId +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch + +@Inject +class HistoryVisibleStatePresenter( + private val featureFlagService: FeatureFlagService, + private val repository: HistoryVisibleAcknowledgementRepository, + private val room: JoinedRoom, +) : Presenter { + @Composable + override fun present(): HistoryVisibleState { + val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false) + val roomInfo by room.roomInfoFlow.collectAsState() + // Implicitly assume the alert is initially acknowledged to avoid flashes in UI. + val acknowledged by repository.hasAcknowledged(room.roomId).collectAsState(initial = true) + + val coroutineScope = rememberCoroutineScope() + + LaunchedEffect(roomInfo.historyVisibility, acknowledged) { + if (roomInfo.historyVisibility == RoomHistoryVisibility.Joined && acknowledged) { + repository.setAcknowledged(room.roomId, false) + } + } + + fun handleEvent(event: HistoryVisibleEvent) { + when (event) { + is HistoryVisibleEvent.Acknowledge -> coroutineScope.setAcknowledged(room.roomId, true) + } + } + + return HistoryVisibleState( + showAlert = isFeatureEnabled && roomInfo.historyVisibility != RoomHistoryVisibility.Joined && roomInfo.isEncrypted == true && !acknowledged, + eventSink = ::handleEvent, + ) + } + + private fun CoroutineScope.setAcknowledged(roomId: RoomId, value: Boolean) = launch { + repository.setAcknowledged(roomId, value) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateProvider.kt new file mode 100644 index 0000000000..752abdc76b --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateProvider.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +class HistoryVisibleStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aHistoryVisibleState(showAlert = true), + ) +} + +internal fun aHistoryVisibleState( + showAlert: Boolean = false, + eventSink: (HistoryVisibleEvent) -> Unit = {}, +) = HistoryVisibleState( + showAlert, + eventSink = eventSink, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateView.kt new file mode 100644 index 0000000000..9c08c9d101 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStateView.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.LinkAnnotation +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.appconfig.LearnMoreConfig +import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertLevel +import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun HistoryVisibleStateView( + state: HistoryVisibleState, + onLinkClick: (String, Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + if (!state.showAlert) { + return + } + + ComposerAlertMolecule( + modifier = modifier, + avatar = null, + showIcon = true, + level = ComposerAlertLevel.Info, + content = buildAnnotatedString { + val learnMoreStr = stringResource(CommonStrings.action_learn_more) + val fullText = stringResource(CommonStrings.crypto_history_visible, learnMoreStr) + append(fullText) + val learnMoreStartIndex = fullText.lastIndexOf(learnMoreStr) + addStyle( + style = SpanStyle( + textDecoration = TextDecoration.Underline, + fontWeight = FontWeight.Bold, + color = ElementTheme.colors.textPrimary + ), + start = learnMoreStartIndex, + end = learnMoreStartIndex + learnMoreStr.length, + ) + addLink( + url = LinkAnnotation.Url( + url = LearnMoreConfig.HISTORY_VISIBLE_URL, + linkInteractionListener = { + onLinkClick(LearnMoreConfig.HISTORY_VISIBLE_URL, true) + } + ), + start = learnMoreStartIndex, + end = learnMoreStartIndex + learnMoreStr.length, + ) + }, + submitText = stringResource(CommonStrings.action_dismiss), + onSubmitClick = { state.eventSink(HistoryVisibleEvent.Acknowledge) }, + ) +} + +@PreviewsDayNight +@Composable +internal fun HistoryVisibleStateViewPreview( + @PreviewParameter(HistoryVisibleStateProvider::class) state: HistoryVisibleState, +) = ElementPreview { + HistoryVisibleStateView( + state = state, + onLinkClick = { _, _ -> }, + ) +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/MessagesViewWithHistoryVisiblePreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/MessagesViewWithHistoryVisiblePreview.kt new file mode 100644 index 0000000000..07cf5170d3 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/MessagesViewWithHistoryVisiblePreview.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import androidx.compose.runtime.Composable +import io.element.android.features.messages.impl.MessagesView +import io.element.android.features.messages.impl.aMessagesState +import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown + +@PreviewsDayNight +@Composable +internal fun MessagesViewWithHistoryVisiblePreview() = ElementPreview { + MessagesView( + state = aMessagesState( + composerState = aMessageComposerState( + textEditorState = aTextEditorStateMarkdown( + initialText = "", + initialFocus = false, + ) + ), + historyVisibleState = aHistoryVisibleState(showAlert = true), + ), + onBackClick = {}, + onRoomDetailsClick = {}, + onEventContentClick = { _, _ -> false }, + onUserDataClick = {}, + onLinkClick = { _, _ -> }, + onSendLocationClick = {}, + onCreatePollClick = {}, + onJoinCallClick = {}, + onViewAllPinnedMessagesClick = {}, + knockRequestsBannerView = {} + ) +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesBindsModule.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesBindsModule.kt index a345e09fa2..a88dbb1b49 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesBindsModule.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesBindsModule.kt @@ -11,6 +11,8 @@ package io.element.android.features.messages.impl.di import dev.zacsweers.metro.BindingContainer import dev.zacsweers.metro.Binds import dev.zacsweers.metro.ContributesTo +import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleState +import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleStatePresenter import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState import io.element.android.features.messages.impl.crypto.identity.IdentityChangeStatePresenter import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailurePresenter @@ -61,4 +63,7 @@ interface MessagesBindsModule { @Binds fun bindIdentityChangeStatePresenter(presenter: IdentityChangeStatePresenter): Presenter + + @Binds + fun bindHistoryVisibleStatePresenter(presenter: HistoryVisibleStatePresenter): Presenter } 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 852e2504b2..de2c8a81c9 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 @@ -17,6 +17,7 @@ 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.anActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.historyvisible.aHistoryVisibleState import io.element.android.features.messages.impl.crypto.identity.anIdentityChangeState import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.link.aLinkState @@ -1355,6 +1356,7 @@ class MessagesPresenterTest { timelinePresenter = { aTimelineState(eventSink = timelineEventSink) }, timelineProtectionPresenter = { aTimelineProtectionState() }, identityChangeStatePresenter = { anIdentityChangeState() }, + historyVisibleStatePresenter = { aHistoryVisibleState() }, linkPresenter = { aLinkState() }, actionListPresenter = { anActionListState(eventSink = actionListEventSink) }, customReactionPresenter = { aCustomReactionState() }, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/FakeHistoryVisibleAcknowledgementRepository.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/FakeHistoryVisibleAcknowledgementRepository.kt new file mode 100644 index 0000000000..faf21720fa --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/FakeHistoryVisibleAcknowledgementRepository.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class FakeHistoryVisibleAcknowledgementRepository( + private val acknowledgements: MutableMap> = mutableMapOf() +) : HistoryVisibleAcknowledgementRepository { + override fun hasAcknowledged(roomId: RoomId): Flow { + return acknowledgements.getOrPut(roomId) { + MutableStateFlow(false) + } + } + + override suspend fun setAcknowledged(roomId: RoomId, value: Boolean) { + val flow = acknowledgements.getOrPut(roomId) { + MutableStateFlow(value) + } + flow.emit(value) + } + + companion object { + /** + * Create the repository with a pre-existing entry. + */ + fun withRoom(roomId: RoomId, acknowledged: Boolean = false): FakeHistoryVisibleAcknowledgementRepository { + return FakeHistoryVisibleAcknowledgementRepository( + mutableMapOf( + roomId to MutableStateFlow(acknowledged) + ) + ) + } + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenterTest.kt new file mode 100644 index 0000000000..b6619851e6 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/historyvisible/HistoryVisibleStatePresenterTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.historyvisible + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.awaitLastSequentialItem +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class HistoryVisibleStatePresenterTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - not visible if feature disabled`() = runTest { + val room = FakeJoinedRoom() + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Joined, isEncrypted = true)) + val presenter = createHistoryVisibleStatePresenter(room, enabled = false, acknowledged = false) + presenter.test { + assertThat(awaitLastSequentialItem().showAlert).isFalse() + } + } + + @Test + fun `present - initial with room shared, unencrypted`() = runTest { + val room = FakeJoinedRoom() + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared, isEncrypted = false)) + val presenter = createHistoryVisibleStatePresenter(room) + presenter.test { + assertThat(awaitLastSequentialItem().showAlert).isFalse() + } + } + + @Test + fun `present - initial with room joined, encrypted`() = runTest { + val room = FakeJoinedRoom() + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Joined, isEncrypted = false)) + val presenter = createHistoryVisibleStatePresenter(room) + presenter.test { + assertThat(awaitLastSequentialItem().showAlert).isFalse() + } + } + + @Test + fun `present - initial with room shared, encrypted, unacknowledged`() = runTest { + val room = FakeJoinedRoom() + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared, isEncrypted = true)) + val presenter = createHistoryVisibleStatePresenter(room, acknowledged = false) + presenter.test { + val initialState = awaitItem() + assertThat(initialState.showAlert).isFalse() + val nextState = awaitItem() + assertThat(nextState.showAlert).isTrue() + } + } + + @Test + fun `present - initial with room shared, encrypted, acknowledged`() = runTest { + val room = FakeJoinedRoom() + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared, isEncrypted = true)) + val presenter = createHistoryVisibleStatePresenter(room, acknowledged = true) + presenter.test { + assertThat(awaitLastSequentialItem().showAlert).isFalse() + } + } + + @Test + fun `present - transition from joined + unencrypted, to shared + encrypted`() = runTest { + val room = FakeJoinedRoom() + val featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true)) + val repository = FakeHistoryVisibleAcknowledgementRepository() + + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Joined, isEncrypted = false)) + + val presenter = HistoryVisibleStatePresenter( + featureFlagService, + repository, + room, + ) + + presenter.test { + // emitted by the feature flag service(?) + assertThat(awaitItem().showAlert).isFalse() + + // emitted state from room info assignment + assertThat(awaitItem().showAlert).isFalse() + + // room is marked as encrypted + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Joined, isEncrypted = true)) + assertThat(awaitItem().showAlert).isFalse() + + // room history visibility is changed to shared + room.givenRoomInfo(aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared, isEncrypted = true)) + assertThat(awaitItem().showAlert).isTrue() + + // alert is acknowledged + repository.setAcknowledged(room.roomId, true) + assertThat(awaitItem().showAlert).isFalse() + } + } + + private fun createHistoryVisibleStatePresenter( + room: JoinedRoom = FakeJoinedRoom(), + enabled: Boolean = true, + acknowledged: Boolean = false + ): HistoryVisibleStatePresenter { + return HistoryVisibleStatePresenter( + room = room, + featureFlagService = FakeFeatureFlagService(mapOf("feature.enableKeyShareOnInvite" to enabled)), + repository = FakeHistoryVisibleAcknowledgementRepository.withRoom(room.roomId, acknowledged) + ) + } +} diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt index b4f15d8d96..32f2908cf7 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt @@ -97,6 +97,7 @@ class KonsistPreviewTest { "MessageComposerViewVoicePreview", "MessagesReactionButtonAddPreview", "MessagesReactionButtonExtraPreview", + "MessagesViewWithHistoryVisiblePreview", "MessagesViewWithIdentityChangePreview", "PendingMemberRowWithLongNamePreview", "PinUnlockViewInAppPreview", diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png new file mode 100644 index 0000000000..d19a140456 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96bc0c555188cee4b3f3e3e0f28f944a4225e27b9a1069edf2b10a2993ee3080 +size 26078 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png new file mode 100644 index 0000000000..d19a140456 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96bc0c555188cee4b3f3e3e0f28f944a4225e27b9a1069edf2b10a2993ee3080 +size 26078 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png new file mode 100644 index 0000000000..d21a12dd64 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a103daf8447cb571a0c5010d062a7790aaa0f3dce30f052bf86884708f4881a5 +size 28769 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png new file mode 100644 index 0000000000..d21a12dd64 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a103daf8447cb571a0c5010d062a7790aaa0f3dce30f052bf86884708f4881a5 +size 28769 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png new file mode 100644 index 0000000000..22d05e61fa --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9682cdd7e08e32591fa47f56da5e6ef4cc3a777700931c2c86e9b802a9cf25cb +size 67342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png new file mode 100644 index 0000000000..22d05e61fa --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9682cdd7e08e32591fa47f56da5e6ef4cc3a777700931c2c86e9b802a9cf25cb +size 67342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png new file mode 100644 index 0000000000..b2bb8ac3fc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d20c04c6385e675bd71d93d2d5d832509b1300a27708245755f263392b33bc8a +size 69457 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png new file mode 100644 index 0000000000..b2bb8ac3fc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d20c04c6385e675bd71d93d2d5d832509b1300a27708245755f263392b33bc8a +size 69457 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png new file mode 100644 index 0000000000..826ba15d61 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0581c343abffc4a71db827cdc5f8b183525daed8b17b80cd6b511cb70ae9a05 +size 66428 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png new file mode 100644 index 0000000000..ca2c69a01b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97065ad20dc15bad0e6be815df8a5bd8b0411d11e7189e50a7abd13438f60f4b +size 69292 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_12_en.png new file mode 100644 index 0000000000..826ba15d61 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0581c343abffc4a71db827cdc5f8b183525daed8b17b80cd6b511cb70ae9a05 +size 66428 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png new file mode 100644 index 0000000000..57fac247d9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5d618df3faa09281e59897b7f478d12f5a0d907b47f58747607e1de8cbc6e61 +size 68146 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png new file mode 100644 index 0000000000..34738a39fb --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f65782549d9ae258584413de54a016705b705f05fd653b48c302b62dc3cd0c71 +size 70718 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_12_en.png new file mode 100644 index 0000000000..57fac247d9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5d618df3faa09281e59897b7f478d12f5a0d907b47f58747607e1de8cbc6e61 +size 68146 From dafc508e060dffdc0c537ee46a8fd01598a3e528 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:07:38 +0000 Subject: [PATCH 23/64] Update metro to v0.8.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0dd448c17..2c8f84b01d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -52,7 +52,7 @@ haze = "1.6.10" dependencyAnalysis = "3.5.1" # DI -metro = "0.8.1" +metro = "0.8.2" # Auto service autoservice = "1.1.1" From a6df4af7ed33b17c1e764275075f18d7949b7fc4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 13:07:50 +0000 Subject: [PATCH 24/64] Update dependency net.zetetic:sqlcipher-android to v4.12.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2c8f84b01d..eb2f1c9af2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -199,7 +199,7 @@ matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } -sqlcipher = "net.zetetic:sqlcipher-android:4.11.0" +sqlcipher = "net.zetetic:sqlcipher-android:4.12.0" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" unifiedpush = "org.unifiedpush.android:connector:3.1.2" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" From 618171be0541a840d2028a9f1ca817e285dccac1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 19:49:57 +0000 Subject: [PATCH 25/64] chore(deps): update codecov/codecov-action action to v5.5.2 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4965530b5a..b412eb4a49 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -83,7 +83,7 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov - uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From e668c503516d49a4abd0b106fe500c8a742f2cf5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:11:40 +0000 Subject: [PATCH 26/64] fix(deps): update dependency org.maplibre.gl:android-sdk to v12.2.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0b410b713..86a8bb5fe0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -206,7 +206,7 @@ vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" } telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" } statemachine = "com.freeletics.flowredux:compose:1.2.2" -maplibre = "org.maplibre.gl:android-sdk:12.2.1" +maplibre = "org.maplibre.gl:android-sdk:12.2.2" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" opusencoder = "io.element.android:opusencoder:1.2.0" From b34f2cddeff7b13139c00871fd0e6ed6b3d523ba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Dec 2025 10:32:37 +0100 Subject: [PATCH 27/64] Fix issue where the wrong system was opened when dealing with other permissions than Manifest.permission.POST_NOTIFICATIONS --- .../permissions/impl/DefaultPermissionsPresenter.kt | 2 +- .../permissions/impl/action/AndroidPermissionActions.kt | 9 +++++++-- .../permissions/impl/action/PermissionActions.kt | 2 +- .../NotificationTroubleshootCheckPermissionTest.kt | 2 +- .../permissions/impl/action/FakePermissionActions.kt | 6 +++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt index 76e288013b..99f42a2a0c 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt @@ -113,7 +113,7 @@ class DefaultPermissionsPresenter( } } PermissionsEvents.OpenSystemSettingAndCloseDialog -> { - permissionActions.openSettings() + permissionActions.openSettings(permission) showDialog.value = false } } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/AndroidPermissionActions.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/AndroidPermissionActions.kt index 59ebfc6deb..1be8428890 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/AndroidPermissionActions.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/AndroidPermissionActions.kt @@ -8,9 +8,11 @@ package io.element.android.libraries.permissions.impl.action +import android.Manifest import android.content.Context import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.system.openAppSettingsPage import io.element.android.libraries.androidutils.system.startNotificationSettingsIntent import io.element.android.libraries.di.annotations.ApplicationContext @@ -18,7 +20,10 @@ import io.element.android.libraries.di.annotations.ApplicationContext class AndroidPermissionActions( @ApplicationContext private val context: Context ) : PermissionActions { - override fun openSettings() { - context.startNotificationSettingsIntent() + override fun openSettings(permission: String) { + when (permission) { + Manifest.permission.POST_NOTIFICATIONS -> context.startNotificationSettingsIntent() + else -> context.openAppSettingsPage() + } } } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/PermissionActions.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/PermissionActions.kt index 5c496bf4c7..2b1249b823 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/PermissionActions.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/action/PermissionActions.kt @@ -9,5 +9,5 @@ package io.element.android.libraries.permissions.impl.action interface PermissionActions { - fun openSettings() + fun openSettings(permission: String) } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt index f5ff79e910..eff20fabec 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt @@ -61,6 +61,6 @@ class NotificationTroubleshootCheckPermissionTest( navigator: NotificationTroubleshootNavigator, ) { // Do not bother about asking the permission inline, just lead the user to the settings - permissionActions.openSettings() + permissionActions.openSettings(Manifest.permission.POST_NOTIFICATIONS) } } diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt index 4299672d8d..fb84109a48 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt @@ -9,13 +9,13 @@ package io.element.android.libraries.permissions.impl.action class FakePermissionActions( - val openSettingsAction: () -> Unit = {} + val openSettingsAction: (String) -> Unit = {} ) : PermissionActions { var openSettingsCalled = false private set - override fun openSettings() { - openSettingsAction() + override fun openSettings(permission: String) { + openSettingsAction(permission) openSettingsCalled = true } } From 0309b9d4cb7079b8873f302442925d216a8ec58b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Dec 2025 10:36:15 +0100 Subject: [PATCH 28/64] Improve test. --- .../impl/DefaultPermissionsPresenterTest.kt | 11 ++++++++--- .../permissions/impl/action/FakePermissionActions.kt | 10 ++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index 069a632807..6036652748 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -20,6 +20,8 @@ import io.element.android.libraries.permissions.api.PermissionsEvents import io.element.android.libraries.permissions.impl.action.FakePermissionActions import io.element.android.libraries.permissions.test.InMemoryPermissionsStore import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -107,7 +109,10 @@ class DefaultPermissionsPresenterTest { FakeComposablePermissionStateProvider( permissionState ) - val permissionActions = FakePermissionActions() + val openSettingsAction = lambdaRecorder { } + val permissionActions = FakePermissionActions( + openSettingsAction = openSettingsAction, + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, @@ -122,10 +127,10 @@ class DefaultPermissionsPresenterTest { initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) val withDialogState = awaitItem() assertThat(withDialogState.showDialog).isTrue() - assertThat(permissionActions.openSettingsCalled).isFalse() + openSettingsAction.assertions().isNeverCalled() withDialogState.eventSink.invoke(PermissionsEvents.OpenSystemSettingAndCloseDialog) assertThat(awaitItem().showDialog).isFalse() - assertThat(permissionActions.openSettingsCalled).isTrue() + openSettingsAction.assertions().isCalledOnce().with(value(A_PERMISSION)) } } diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt index fb84109a48..df66dee377 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/action/FakePermissionActions.kt @@ -8,14 +8,12 @@ package io.element.android.libraries.permissions.impl.action -class FakePermissionActions( - val openSettingsAction: (String) -> Unit = {} -) : PermissionActions { - var openSettingsCalled = false - private set +import io.element.android.tests.testutils.lambda.lambdaError +class FakePermissionActions( + val openSettingsAction: (String) -> Unit = { lambdaError() } +) : PermissionActions { override fun openSettings(permission: String) { openSettingsAction(permission) - openSettingsCalled = true } } From 87b85409fc44a9ab474b7dd75e9cba2d5cee9f55 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Dec 2025 10:49:16 +0100 Subject: [PATCH 29/64] Test cleanup --- .../impl/DefaultPermissionsPresenterTest.kt | 203 +++++++----------- 1 file changed, 83 insertions(+), 120 deletions(-) diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index 6036652748..e15a8a5a77 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -10,23 +10,23 @@ package io.element.android.libraries.permissions.impl -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionStatus import com.google.common.truth.Truth.assertThat import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsStore import io.element.android.libraries.permissions.impl.action.FakePermissionActions +import io.element.android.libraries.permissions.impl.action.PermissionActions import io.element.android.libraries.permissions.test.InMemoryPermissionsStore import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -const val A_PERMISSION = "A_PERMISSION" +private const val A_PERMISSION = "A_PERMISSION" class DefaultPermissionsPresenterTest { @get:Rule @@ -34,24 +34,8 @@ class DefaultPermissionsPresenterTest { @Test fun `present - initial state`() = runTest { - val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Granted - ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - FakePermissionActions(), - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + val presenter = createPresenter() + presenter.test { val initialState = awaitItem() assertThat(initialState.permission).isEqualTo(A_PERMISSION) assertThat(initialState.permissionGranted).isTrue() @@ -68,23 +52,16 @@ class DefaultPermissionsPresenterTest { permissionDenied = true, permissionAsked = true ) - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Denied(shouldShowRationale = false) + val permissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = aFakePermissionState( + initialStatus = PermissionStatus.Denied(shouldShowRationale = false) + ), ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - FakePermissionActions(), + val presenter = createPresenter( + permissionsStore = permissionsStore, + permissionStateProvider = permissionStateProvider, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) @@ -101,27 +78,21 @@ class DefaultPermissionsPresenterTest { permissionDenied = true, permissionAsked = true ) - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Denied(shouldShowRationale = false) + val permissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = aFakePermissionState( + initialStatus = PermissionStatus.Denied(shouldShowRationale = false), + ), ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) val openSettingsAction = lambdaRecorder { } val permissionActions = FakePermissionActions( openSettingsAction = openSettingsAction, ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - permissionActions, + val presenter = createPresenter( + permissionsStore = permissionsStore, + permissionStateProvider = permissionStateProvider, + permissionActions = permissionActions, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) @@ -136,24 +107,16 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user does not grant permission`() = runTest { - val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Denied(shouldShowRationale = false) + val permissionState = aFakePermissionState( + initialStatus = PermissionStatus.Denied(shouldShowRationale = false) ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - FakePermissionActions(), + val permissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = permissionState, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + val presenter = createPresenter( + permissionStateProvider = permissionStateProvider, + ) + presenter.test { val initialState = awaitItem() assertThat(initialState.showDialog).isFalse() initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) @@ -171,24 +134,16 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user does not grant permission second time`() = runTest { - val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Denied(shouldShowRationale = true) + val permissionState = aFakePermissionState( + initialStatus = PermissionStatus.Denied(shouldShowRationale = true) ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - FakePermissionActions(), + val permissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = permissionState, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + val presenter = createPresenter( + permissionStateProvider = permissionStateProvider, + ) + presenter.test { val initialState = awaitItem() assertThat(initialState.showDialog).isFalse() initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) @@ -206,28 +161,21 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user does not grant permission third time`() = runTest { - val permissionsStore = - InMemoryPermissionsStore( - permissionDenied = true, - permissionAsked = true - ) - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Denied(shouldShowRationale = false) + val permissionsStore = InMemoryPermissionsStore( + permissionDenied = true, + permissionAsked = true, ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - FakePermissionActions(), + val permissionState = aFakePermissionState( + initialStatus = PermissionStatus.Denied(shouldShowRationale = false), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + val permissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = permissionState, + ) + val presenter = createPresenter( + permissionsStore = permissionsStore, + permissionStateProvider = permissionStateProvider, + ) + presenter.test { skipItems(1) val initialState = awaitItem() initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) @@ -241,24 +189,16 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user grants permission`() = runTest { - val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState( - A_PERMISSION, - PermissionStatus.Denied(shouldShowRationale = false) + val permissionState = aFakePermissionState( + initialStatus = PermissionStatus.Denied(shouldShowRationale = false) ) - val permissionStateProvider = - FakeComposablePermissionStateProvider( - permissionState - ) - val presenter = DefaultPermissionsPresenter( - A_PERMISSION, - permissionsStore, - permissionStateProvider, - FakePermissionActions(), + val permissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = permissionState, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + val presenter = createPresenter( + permissionStateProvider = permissionStateProvider, + ) + presenter.test { val initialState = awaitItem() assertThat(initialState.showDialog).isFalse() initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) @@ -274,3 +214,26 @@ class DefaultPermissionsPresenterTest { } } } + +private fun createPresenter( + permission: String = A_PERMISSION, + permissionsStore: PermissionsStore = InMemoryPermissionsStore(), + permissionStateProvider: ComposablePermissionStateProvider = FakeComposablePermissionStateProvider( + permissionState = aFakePermissionState(), + ), + permissionActions: PermissionActions = FakePermissionActions(), +) = DefaultPermissionsPresenter( + permission = permission, + permissionsStore = permissionsStore, + composablePermissionStateProvider = permissionStateProvider, + permissionActions = permissionActions, +) + +private fun aFakePermissionState( + permission: String = A_PERMISSION, + initialStatus: PermissionStatus = PermissionStatus.Granted, +) = FakePermissionState( + permission = permission, + initialStatus = initialStatus, +) + From d65cbd46a9ea7aac4ccda4b748527d4c16b7d92c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Dec 2025 10:50:10 +0100 Subject: [PATCH 30/64] PermissionsEvents -> PermissionsEvent --- .../configureroom/ConfigureRoomPresenter.kt | 4 ++-- .../NotificationsOptInPresenter.kt | 4 ++-- .../qrcode/intro/QrCodeIntroPresenter.kt | 4 ++-- .../MessageComposerPresenter.kt | 6 +++--- .../DefaultVoiceMessageComposerPresenter.kt | 8 ++++---- .../editprofile/EditUserProfilePresenter.kt | 4 ++-- .../impl/RoomDetailsEditPresenter.kt | 4 ++-- ...ermissionsEvents.kt => PermissionsEvent.kt} | 8 ++++---- .../permissions/api/PermissionsState.kt | 2 +- .../permissions/api/PermissionsView.kt | 4 ++-- .../impl/DefaultPermissionsPresenter.kt | 10 +++++----- .../impl/DefaultPermissionsPresenterTest.kt | 18 +++++++++--------- .../test/FakePermissionsPresenter.kt | 10 +++++----- 13 files changed, 43 insertions(+), 43 deletions(-) rename libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/{PermissionsEvents.kt => PermissionsEvent.kt} (71%) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index c5d68e127f..dbec30c0c5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -40,7 +40,7 @@ import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidityEf import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider import io.element.android.libraries.mediaupload.api.MediaPreProcessor -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.services.analytics.api.AnalyticsService import kotlinx.collections.immutable.toImmutableList @@ -132,7 +132,7 @@ class ConfigureRoomPresenter( cameraPhotoPicker.launch() } else { pendingPermissionRequest = true - cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + cameraPermissionState.eventSink(PermissionsEvent.RequestPermissions) } AvatarAction.Remove -> dataStore.setAvatarUri(uri = null) } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt index 344d83c38f..deb7fc59b9 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt @@ -19,7 +19,7 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.permissions.api.PermissionStateProvider -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider @@ -58,7 +58,7 @@ class NotificationsOptInPresenter( if (notificationsPermissionsState.permissionGranted) { callback.onNotificationsOptInFinished() } else { - notificationsPermissionsState.eventSink(PermissionsEvents.RequestPermissions) + notificationsPermissionsState.eventSink(PermissionsEvent.RequestPermissions) } } NotificationsOptInEvents.NotNowClicked -> { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroPresenter.kt index 4da6448027..13888fe23f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroPresenter.kt @@ -18,7 +18,7 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter @Inject @@ -46,7 +46,7 @@ class QrCodeIntroPresenter( canContinue = true } else { pendingPermissionRequest = true - cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + cameraPermissionState.eventSink(PermissionsEvent.RequestPermissions) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 276499d5bb..b193e97fa3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -63,7 +63,7 @@ import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider import io.element.android.libraries.mediaupload.api.MediaSenderFactory import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.push.api.notifications.conversations.NotificationConversationService @@ -284,7 +284,7 @@ class MessageComposerPresenter( cameraPhotoPicker.launch() } else { pendingEvent = event - cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + cameraPermissionState.eventSink(PermissionsEvent.RequestPermissions) } } MessageComposerEvent.PickAttachmentSource.VideoFromCamera -> localCoroutineScope.launch { @@ -293,7 +293,7 @@ class MessageComposerPresenter( cameraVideoPicker.launch() } else { pendingEvent = event - cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + cameraPermissionState.eventSink(PermissionsEvent.RequestPermissions) } } MessageComposerEvent.PickAttachmentSource.Location -> { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt index 051ded02ae..56b0e402d2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt @@ -33,7 +33,7 @@ import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.mediaupload.api.MediaSenderFactory -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.textcomposer.model.VoiceMessagePlayerEvent import io.element.android.libraries.textcomposer.model.VoiceMessageRecorderEvent @@ -111,7 +111,7 @@ class DefaultVoiceMessageComposerPresenter( } else -> { Timber.i("Voice message permission needed") - permissionState.eventSink(PermissionsEvents.RequestPermissions) + permissionState.eventSink(PermissionsEvent.RequestPermissions) } } } @@ -176,10 +176,10 @@ class DefaultVoiceMessageComposerPresenter( localCoroutineScope.deleteRecording() } VoiceMessageComposerEvent.DismissPermissionsRationale -> { - permissionState.eventSink(PermissionsEvents.CloseDialog) + permissionState.eventSink(PermissionsEvent.CloseDialog) } VoiceMessageComposerEvent.AcceptPermissionRationale -> { - permissionState.eventSink(PermissionsEvents.OpenSystemSettingAndCloseDialog) + permissionState.eventSink(PermissionsEvent.OpenSystemSettingAndCloseDialog) } is VoiceMessageComposerEvent.LifecycleEvent -> handleLifecycleEvent(event.event) VoiceMessageComposerEvent.DismissSendFailureDialog -> { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index 0bdbb1031f..bddae2fffb 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -35,7 +35,7 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider import io.element.android.libraries.mediaupload.api.MediaPreProcessor -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope @@ -127,7 +127,7 @@ class EditUserProfilePresenter( cameraPhotoPicker.launch() } else { pendingPermissionRequest = true - cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + cameraPermissionState.eventSink(PermissionsEvent.RequestPermissions) } AvatarAction.Remove -> { temporaryUriDeleter.delete(userAvatarUri?.toUri()) diff --git a/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt b/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt index 4a2dfa3f11..5e685ff81f 100644 --- a/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt +++ b/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt @@ -36,7 +36,7 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider import io.element.android.libraries.mediaupload.api.MediaPreProcessor -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope @@ -157,7 +157,7 @@ class RoomDetailsEditPresenter( cameraPhotoPicker.launch() } else { pendingPermissionRequest = true - cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + cameraPermissionState.eventSink(PermissionsEvent.RequestPermissions) } AvatarAction.Remove -> { temporaryUriDeleter.delete(roomAvatarUriEdited?.toUri()) diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvents.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt similarity index 71% rename from libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvents.kt rename to libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt index 2d3cb0099f..fd01e12134 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvents.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt @@ -8,8 +8,8 @@ package io.element.android.libraries.permissions.api -sealed interface PermissionsEvents { - data object RequestPermissions : PermissionsEvents - data object CloseDialog : PermissionsEvents - data object OpenSystemSettingAndCloseDialog : PermissionsEvents +sealed interface PermissionsEvent { + data object RequestPermissions : PermissionsEvent + data object CloseDialog : PermissionsEvent + data object OpenSystemSettingAndCloseDialog : PermissionsEvent } diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsState.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsState.kt index 28c34e6dee..3cbdfea50d 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsState.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsState.kt @@ -17,5 +17,5 @@ data class PermissionsState( val permissionAlreadyAsked: Boolean, // If true, there is no need to ask again, the system dialog will not be displayed val permissionAlreadyDenied: Boolean, - val eventSink: (PermissionsEvents) -> Unit + val eventSink: (PermissionsEvent) -> Unit ) diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt index ef686149ee..af0f3dd5e8 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt @@ -35,9 +35,9 @@ fun PermissionsView( content = content ?: state.permission.toDialogContent(), submitText = stringResource(id = CommonStrings.action_open_settings), onSubmitClick = { - state.eventSink.invoke(PermissionsEvents.OpenSystemSettingAndCloseDialog) + state.eventSink.invoke(PermissionsEvent.OpenSystemSettingAndCloseDialog) }, - onDismiss = { state.eventSink.invoke(PermissionsEvents.CloseDialog) }, + onDismiss = { state.eventSink.invoke(PermissionsEvent.CloseDialog) }, icon = icon, ) } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt index 99f42a2a0c..42331e001a 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt @@ -28,7 +28,7 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.core.log.logger.LoggerTag -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.api.PermissionsState import io.element.android.libraries.permissions.api.PermissionsStore @@ -100,19 +100,19 @@ class DefaultPermissionsPresenter( val showDialog = rememberSaveable { mutableStateOf(false) } - fun handleEvent(event: PermissionsEvents) { + fun handleEvent(event: PermissionsEvent) { when (event) { - PermissionsEvents.CloseDialog -> { + PermissionsEvent.CloseDialog -> { showDialog.value = false } - PermissionsEvents.RequestPermissions -> { + PermissionsEvent.RequestPermissions -> { if (permissionState.status !is PermissionStatus.Granted && isAlreadyDenied) { showDialog.value = true } else { permissionState.launchPermissionRequest() } } - PermissionsEvents.OpenSystemSettingAndCloseDialog -> { + PermissionsEvent.OpenSystemSettingAndCloseDialog -> { permissionActions.openSettings(permission) showDialog.value = false } diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index e15a8a5a77..5335849cbd 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -13,7 +13,7 @@ package io.element.android.libraries.permissions.impl import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionStatus import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsStore import io.element.android.libraries.permissions.impl.action.FakePermissionActions import io.element.android.libraries.permissions.impl.action.PermissionActions @@ -64,10 +64,10 @@ class DefaultPermissionsPresenterTest { presenter.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) + initialState.eventSink.invoke(PermissionsEvent.RequestPermissions) val withDialogState = awaitItem() assertThat(withDialogState.showDialog).isTrue() - withDialogState.eventSink.invoke(PermissionsEvents.CloseDialog) + withDialogState.eventSink.invoke(PermissionsEvent.CloseDialog) assertThat(awaitItem().showDialog).isFalse() } } @@ -95,11 +95,11 @@ class DefaultPermissionsPresenterTest { presenter.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) + initialState.eventSink.invoke(PermissionsEvent.RequestPermissions) val withDialogState = awaitItem() assertThat(withDialogState.showDialog).isTrue() openSettingsAction.assertions().isNeverCalled() - withDialogState.eventSink.invoke(PermissionsEvents.OpenSystemSettingAndCloseDialog) + withDialogState.eventSink.invoke(PermissionsEvent.OpenSystemSettingAndCloseDialog) assertThat(awaitItem().showDialog).isFalse() openSettingsAction.assertions().isCalledOnce().with(value(A_PERMISSION)) } @@ -119,7 +119,7 @@ class DefaultPermissionsPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.showDialog).isFalse() - initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) + initialState.eventSink.invoke(PermissionsEvent.RequestPermissions) assertThat(permissionState.launchPermissionRequestCalled).isTrue() // User does not grant permission permissionStateProvider.userGiveAnswer(answer = false, firstTime = true) @@ -146,7 +146,7 @@ class DefaultPermissionsPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.showDialog).isFalse() - initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) + initialState.eventSink.invoke(PermissionsEvent.RequestPermissions) assertThat(permissionState.launchPermissionRequestCalled).isTrue() // User does not grant permission permissionStateProvider.userGiveAnswer(answer = false, firstTime = false) @@ -178,7 +178,7 @@ class DefaultPermissionsPresenterTest { presenter.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) + initialState.eventSink.invoke(PermissionsEvent.RequestPermissions) val withDialogState = awaitItem() assertThat(withDialogState.showDialog).isTrue() assertThat(withDialogState.permissionGranted).isFalse() @@ -201,7 +201,7 @@ class DefaultPermissionsPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.showDialog).isFalse() - initialState.eventSink.invoke(PermissionsEvents.RequestPermissions) + initialState.eventSink.invoke(PermissionsEvent.RequestPermissions) assertThat(permissionState.launchPermissionRequestCalled).isTrue() // User grants permission permissionStateProvider.userGiveAnswer(answer = true, firstTime = true) diff --git a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt index b15f4db3ee..efd584585f 100644 --- a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt @@ -10,7 +10,7 @@ package io.element.android.libraries.permissions.test import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf -import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.api.PermissionsState import io.element.android.libraries.permissions.api.aPermissionsState @@ -18,11 +18,11 @@ import io.element.android.libraries.permissions.api.aPermissionsState class FakePermissionsPresenter( private val initialState: PermissionsState = aPermissionsState(showDialog = false), ) : PermissionsPresenter { - private fun handleEvent(event: PermissionsEvents) { + private fun handleEvent(event: PermissionsEvent) { when (event) { - PermissionsEvents.RequestPermissions -> state.value = state.value.copy(showDialog = true, permissionAlreadyAsked = true) - PermissionsEvents.CloseDialog -> state.value = state.value.copy(showDialog = false) - PermissionsEvents.OpenSystemSettingAndCloseDialog -> state.value = state.value.copy(showDialog = false) + PermissionsEvent.RequestPermissions -> state.value = state.value.copy(showDialog = true, permissionAlreadyAsked = true) + PermissionsEvent.CloseDialog -> state.value = state.value.copy(showDialog = false) + PermissionsEvent.OpenSystemSettingAndCloseDialog -> state.value = state.value.copy(showDialog = false) } } From 9529c1cb906b00fc1e8c22e63971518186227c17 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Dec 2025 10:56:52 +0100 Subject: [PATCH 31/64] Remove empty line --- .../permissions/impl/DefaultPermissionsPresenterTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index 5335849cbd..c7a10ca8d1 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -236,4 +236,3 @@ private fun aFakePermissionState( permission = permission, initialStatus = initialStatus, ) - From 9c72310cb4fdf70bed370c722cc174ad0b719fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 28 Nov 2025 07:58:06 +0100 Subject: [PATCH 32/64] Add developer option to optimize the SDK DBs --- .../impl/developer/DeveloperSettingsEvents.kt | 1 + .../developer/DeveloperSettingsPresenter.kt | 5 ++++ .../impl/developer/DeveloperSettingsView.kt | 8 ++++++ .../impl/tasks/VacuumStoresUseCase.kt | 27 +++++++++++++++++++ .../libraries/matrix/api/MatrixClient.kt | 2 ++ .../libraries/matrix/impl/RustMatrixClient.kt | 6 +++++ 6 files changed, 49 insertions(+) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt index 3bf4f375d5..1804d7e070 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt @@ -21,4 +21,5 @@ sealed interface DeveloperSettingsEvents { data class SetShowColorPicker(val show: Boolean) : DeveloperSettingsEvents data class ChangeBrandColor(val color: Color?) : DeveloperSettingsEvents data object ClearCache : DeveloperSettingsEvents + data object VacuumStores : DeveloperSettingsEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt index 52e522dc89..db35a1dc83 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt @@ -29,6 +29,7 @@ import io.element.android.features.preferences.impl.developer.tracing.toLogLevel import io.element.android.features.preferences.impl.model.EnabledFeature import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase +import io.element.android.features.preferences.impl.tasks.VacuumStoresUseCase import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData @@ -61,6 +62,7 @@ class DeveloperSettingsPresenter( private val appPreferencesStore: AppPreferencesStore, private val buildMeta: BuildMeta, private val enterpriseService: EnterpriseService, + private val vacuumStoresUseCase: VacuumStoresUseCase, ) : Presenter { @Composable override fun present(): DeveloperSettingsState { @@ -151,6 +153,9 @@ class DeveloperSettingsPresenter( is DeveloperSettingsEvents.SetShowColorPicker -> { showColorPicker = event.show } + DeveloperSettingsEvents.VacuumStores -> coroutineScope.launch { + vacuumStoresUseCase() + } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 6d34e97f63..2bfb2f086a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -146,6 +146,14 @@ fun DeveloperSettingsView( } val cache = state.cacheSize PreferenceCategory(title = "Cache") { + ListItem( + headlineContent = { + Text("Vacuum stores") + }, + onClick = { + state.eventSink(DeveloperSettingsEvents.VacuumStores) + } + ) ListItem( headlineContent = { Text("Clear cache") diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt new file mode 100644 index 0000000000..0e6068cb4d --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.preferences.impl.tasks + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.matrix.api.MatrixClient +import timber.log.Timber + +interface VacuumStoresUseCase { + suspend operator fun invoke() +} + +@ContributesBinding(AppScope::class) +class DefaultVacuumStoresUseCase( + private val matrixClient: MatrixClient, +) : VacuumStoresUseCase { + override suspend fun invoke() { + matrixClient.vacuumStores() + .onFailure { Timber.e(it, "Failed to vacuum stores") } + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 1718f810df..566434b6be 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -194,6 +194,8 @@ interface MatrixClient { * Use [Timeline.markAsRead] instead when possible. */ suspend fun markRoomAsFullyRead(roomId: RoomId, eventId: EventId): Result + + suspend fun vacuumStores(): Result } /** diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index fca2aaa197..31e80cf442 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -726,6 +726,12 @@ class RustMatrixClient( } } + override suspend fun vacuumStores(): Result = withContext(sessionDispatcher) { + runCatchingExceptions { + innerClient.optimizeStores() + } + } + private suspend fun getCacheSize( includeCryptoDb: Boolean = false, ): Long = withContext(sessionDispatcher) { From 482d7e0648b2060f5a2b8a6fb16ca3bb259bcad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 5 Dec 2025 14:19:36 +0100 Subject: [PATCH 33/64] Add a periodic DB vacuuming task --- .../impl/tasks/VacuumStoresUseCase.kt | 4 +- .../DeveloperSettingsPresenterTest.kt | 20 ++++++++++ .../libraries/matrix/api/MatrixClient.kt | 2 +- libraries/matrix/impl/build.gradle.kts | 2 + .../libraries/matrix/impl/RustMatrixClient.kt | 19 ++++++++- .../matrix/impl/RustMatrixClientFactory.kt | 3 ++ ...PerformDatabaseVacuumWorkManagerRequest.kt | 40 +++++++++++++++++++ .../impl/workmanager/VacuumDatabaseWorker.kt | 38 ++++++++++++++++++ .../impl/RustMatrixClientFactoryTest.kt | 12 +++++- .../matrix/impl/RustMatrixClientTest.kt | 2 + .../libraries/matrix/test/FakeMatrixClient.kt | 5 +++ .../NotificationResolverQueue.kt | 4 +- .../workmanager/FetchNotificationsWorker.kt | 2 +- .../SyncNotificationWorkManagerRequest.kt | 2 +- ...> SyncNotificationsWorkerDataConverter.kt} | 2 +- .../push/impl/push/DefaultPushHandlerTest.kt | 4 +- .../FetchNotificationWorkerTest.kt | 2 +- .../SyncNotificationWorkManagerRequestTest.kt | 4 +- .../workmanager/WorkerDataConverterTest.kt | 12 +++--- .../workmanager/api/WorkManagerScheduler.kt | 3 ++ .../impl/DefaultWorkManagerScheduler.kt | 5 +++ .../test/FakeWorkManagerScheduler.kt | 6 +++ 22 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/PerformDatabaseVacuumWorkManagerRequest.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt rename libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/{WorkerDataConverter.kt => SyncNotificationsWorkerDataConverter.kt} (99%) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt index 0e6068cb4d..1d0de56f09 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/VacuumStoresUseCase.kt @@ -12,7 +12,7 @@ import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.matrix.api.MatrixClient import timber.log.Timber -interface VacuumStoresUseCase { +fun interface VacuumStoresUseCase { suspend operator fun invoke() } @@ -21,7 +21,7 @@ class DefaultVacuumStoresUseCase( private val matrixClient: MatrixClient, ) : VacuumStoresUseCase { override suspend fun invoke() { - matrixClient.vacuumStores() + matrixClient.performDatabaseVacuum() .onFailure { Timber.e(it, "Failed to vacuum stores") } } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt index fe2d8445fd..75ae12b714 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt @@ -17,6 +17,7 @@ import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase +import io.element.android.features.preferences.impl.tasks.VacuumStoresUseCase import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData @@ -212,6 +213,23 @@ class DeveloperSettingsPresenterTest { } } + @Test + fun `present - VacuumStores action invokes the VacuumStoresUseCase`() = runTest { + var vacuumCalled = false + val presenter = createDeveloperSettingsPresenter( + vacuumStoresUseCase = VacuumStoresUseCase { + vacuumCalled = true + } + ) + presenter.test { + val state = awaitItem() + assertThat(vacuumCalled).isFalse() + state.eventSink(DeveloperSettingsEvents.VacuumStores) + skipItems(1) + assertThat(vacuumCalled).isTrue() + } + } + private fun createDeveloperSettingsPresenter( sessionId: SessionId = A_SESSION_ID, featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService( @@ -230,6 +248,7 @@ class DeveloperSettingsPresenterTest { preferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), buildMeta: BuildMeta = aBuildMeta(), enterpriseService: EnterpriseService = FakeEnterpriseService(), + vacuumStoresUseCase: VacuumStoresUseCase = VacuumStoresUseCase {}, ): DeveloperSettingsPresenter { return DeveloperSettingsPresenter( sessionId = sessionId, @@ -240,6 +259,7 @@ class DeveloperSettingsPresenterTest { appPreferencesStore = preferencesStore, buildMeta = buildMeta, enterpriseService = enterpriseService, + vacuumStoresUseCase = vacuumStoresUseCase, ) } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 566434b6be..ae803110d5 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -195,7 +195,7 @@ interface MatrixClient { */ suspend fun markRoomAsFullyRead(roomId: RoomId, eventId: EventId): Result - suspend fun vacuumStores(): Result + suspend fun performDatabaseVacuum(): Result } /** diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 394cb2398e..6edf26008a 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation(projects.libraries.featureflag.api) implementation(projects.libraries.network) implementation(projects.libraries.preferences.api) + implementation(projects.libraries.workmanager.api) implementation(projects.services.analytics.api) implementation(projects.services.toolbox.api) api(projects.libraries.matrix.api) @@ -49,6 +50,7 @@ dependencies { testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.previewutils) testImplementation(projects.libraries.sessionStorage.test) + testImplementation(projects.libraries.workmanager.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 31e80cf442..8784a69d7c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -75,7 +75,10 @@ import io.element.android.libraries.matrix.impl.util.SessionPathsProvider import io.element.android.libraries.matrix.impl.util.cancelAndDestroy import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService +import io.element.android.libraries.matrix.impl.workmanager.PerformDatabaseVacuumWorkManagerRequest import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.workmanager.api.WorkManagerRequestType +import io.element.android.libraries.workmanager.api.WorkManagerScheduler import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.collections.immutable.ImmutableList @@ -133,6 +136,7 @@ class RustMatrixClient( timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, private val featureFlagService: FeatureFlagService, private val analyticsService: AnalyticsService, + private val workManagerScheduler: WorkManagerScheduler, ) : MatrixClient { override val sessionId: UserId = UserId(innerClient.userId()) override val deviceId: DeviceId = DeviceId(innerClient.deviceId()) @@ -276,6 +280,9 @@ class RustMatrixClient( // Force a refresh of the profile getUserProfile() } + + // Schedule regular database vacuuming to ensure DB performance remains optimal + scheduleDatabaseVacuum() } override fun userIdServerName(): String { @@ -726,8 +733,9 @@ class RustMatrixClient( } } - override suspend fun vacuumStores(): Result = withContext(sessionDispatcher) { + override suspend fun performDatabaseVacuum(): Result = withContext(sessionDispatcher) { runCatchingExceptions { + Timber.d("Performing database vacuuming for session $sessionId...") innerClient.optimizeStores() } } @@ -756,6 +764,15 @@ class RustMatrixClient( // Delete all the files for this session sessionPathsProvider.provides(sessionId)?.deleteRecursively() } + + private fun scheduleDatabaseVacuum() { + // If there's already a periodic work request, do not schedule another one + if (workManagerScheduler.hasPendingWork(sessionId, WorkManagerRequestType.DB_VACUUM)) return + + Timber.i("Scheduling periodic database vacuuming for session $sessionId") + val request = PerformDatabaseVacuumWorkManagerRequest(sessionId) + workManagerScheduler.submit(request) + } } private val defaultRoomCreationPowerLevels = PowerLevels( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 58e3485279..3d94f7554d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.impl.util.anonymizedTokens import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.workmanager.api.WorkManagerScheduler import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CoroutineScope @@ -63,6 +64,7 @@ class RustMatrixClientFactory( private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, private val clientBuilderProvider: ClientBuilderProvider, private val sqliteStoreBuilderProvider: SqliteStoreBuilderProvider, + private val workManagerScheduler: WorkManagerScheduler, ) { private val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers) @@ -116,6 +118,7 @@ class RustMatrixClientFactory( timelineEventTypeFilterFactory = timelineEventTypeFilterFactory, featureFlagService = featureFlagService, analyticsService = analyticsService, + workManagerScheduler = workManagerScheduler, ).also { Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/PerformDatabaseVacuumWorkManagerRequest.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/PerformDatabaseVacuumWorkManagerRequest.kt new file mode 100644 index 0000000000..9c192bd96d --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/PerformDatabaseVacuumWorkManagerRequest.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.workmanager + +import androidx.work.Constraints +import androidx.work.Data +import androidx.work.PeriodicWorkRequest +import androidx.work.WorkRequest +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.impl.workmanager.VacuumDatabaseWorker.Companion.SESSION_ID_PARAM +import io.element.android.libraries.workmanager.api.WorkManagerRequest +import io.element.android.libraries.workmanager.api.WorkManagerRequestType +import io.element.android.libraries.workmanager.api.workManagerTag +import java.util.concurrent.TimeUnit + +class PerformDatabaseVacuumWorkManagerRequest( + private val sessionId: SessionId, +) : WorkManagerRequest { + override fun build(): Result> { + val data = Data.Builder().putString(SESSION_ID_PARAM, sessionId.value).build() + val workRequest = PeriodicWorkRequest.Builder( + workerClass = VacuumDatabaseWorker::class, + // Run once a day + repeatInterval = 1, + repeatIntervalTimeUnit = TimeUnit.DAYS, + ) + .addTag(workManagerTag(sessionId, WorkManagerRequestType.DB_VACUUM)) + .setInputData(data) + // Only run when the device is idle to avoid impacting user experience + .setConstraints(Constraints.Builder().setRequiresDeviceIdle(true).build()) + .build() + + return Result.success(listOf(workRequest)) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt new file mode 100644 index 0000000000..0602c2fdc2 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.workmanager + +import android.content.Context +import androidx.work.CoroutineWorker +import androidx.work.WorkerParameters +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.MatrixClientProvider +import io.element.android.libraries.matrix.api.core.SessionId + +@AssistedInject +class VacuumDatabaseWorker( + @Assisted workerParams: WorkerParameters, + @ApplicationContext private val context: Context, + private val matrixClientProvider: MatrixClientProvider, +) : CoroutineWorker(context, workerParams) { + companion object { + const val SESSION_ID_PARAM = "session_id" + } + + override suspend fun doWork(): Result { + val sessionId = inputData.getString(SESSION_ID_PARAM)?.let(::SessionId) ?: return Result.failure() + val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return Result.failure() + return client.performDatabaseVacuum() + .fold( + onSuccess = { Result.success() }, + onFailure = { Result.failure() } + ) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt index a1b52d430a..fa69752afe 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt @@ -19,8 +19,11 @@ import io.element.android.libraries.network.useragent.SimpleUserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.libraries.workmanager.api.WorkManagerRequest +import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest @@ -30,9 +33,14 @@ import java.io.File class RustMatrixClientFactoryTest { @Test fun test() = runTest { - val sut = createRustMatrixClientFactory() + val scheduleVacuumLambda = lambdaRecorder {} + val workManagerScheduler = FakeWorkManagerScheduler(submitLambda = scheduleVacuumLambda) + val sut = createRustMatrixClientFactory(workManagerScheduler = workManagerScheduler) + val result = sut.create(aSessionData()) + assertThat(result.sessionId).isEqualTo(SessionId("@alice:server.org")) + scheduleVacuumLambda.assertions().isCalledOnce() result.destroy() } } @@ -43,6 +51,7 @@ fun TestScope.createRustMatrixClientFactory( updateUserProfileResult = { _, _, _ -> }, ), clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(), + workManagerScheduler: FakeWorkManagerScheduler = FakeWorkManagerScheduler(), ) = RustMatrixClientFactory( cacheDirectory = cacheDirectory, appCoroutineScope = backgroundScope, @@ -57,4 +66,5 @@ fun TestScope.createRustMatrixClientFactory( timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), clientBuilderProvider = clientBuilderProvider, sqliteStoreBuilderProvider = FakeSqliteStoreBuilderProvider(), + workManagerScheduler = workManagerScheduler, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index c81d9f1c15..3c8619ed72 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -116,5 +117,6 @@ class RustMatrixClientTest { timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), featureFlagService = FakeFeatureFlagService(), analyticsService = FakeAnalyticsService(), + workManagerScheduler = FakeWorkManagerScheduler(submitLambda = {}), ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 940cce6164..38d4d1aefe 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -104,6 +104,7 @@ class FakeMatrixClient( private val getRecentEmojisLambda: () -> Result> = { Result.success(emptyList()) }, private val addRecentEmojiLambda: (String) -> Result = { Result.success(Unit) }, private val markRoomAsFullyReadResult: (RoomId, EventId) -> Result = { _, _ -> lambdaError() }, + private val performDatabaseVacuumLambda: () -> Result = { lambdaError() }, ) : MatrixClient { var setDisplayNameCalled: Boolean = false private set @@ -351,4 +352,8 @@ class FakeMatrixClient( override suspend fun markRoomAsFullyRead(roomId: RoomId, eventId: EventId): Result { return markRoomAsFullyReadResult(roomId, eventId) } + + override suspend fun performDatabaseVacuum(): Result { + return performDatabaseVacuumLambda() + } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResolverQueue.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResolverQueue.kt index 0d1478cb9e..b40b3fe79f 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResolverQueue.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResolverQueue.kt @@ -17,7 +17,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.push.api.push.NotificationEventRequest import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEvent import io.element.android.libraries.push.impl.workmanager.SyncNotificationWorkManagerRequest -import io.element.android.libraries.push.impl.workmanager.WorkerDataConverter +import io.element.android.libraries.push.impl.workmanager.SyncNotificationsWorkerDataConverter import io.element.android.libraries.workmanager.api.WorkManagerScheduler import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider import kotlinx.coroutines.CoroutineScope @@ -50,7 +50,7 @@ class DefaultNotificationResolverQueue( private val appCoroutineScope: CoroutineScope, private val workManagerScheduler: WorkManagerScheduler, private val featureFlagService: FeatureFlagService, - private val workerDataConverter: WorkerDataConverter, + private val workerDataConverter: SyncNotificationsWorkerDataConverter, private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider, ) : NotificationResolverQueue { companion object { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt index ccc0a02749..eeac5ff66f 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationsWorker.kt @@ -49,7 +49,7 @@ class FetchNotificationsWorker( private val workManagerScheduler: WorkManagerScheduler, private val syncOnNotifiableEvent: SyncOnNotifiableEvent, private val coroutineDispatchers: CoroutineDispatchers, - private val workerDataConverter: WorkerDataConverter, + private val workerDataConverter: SyncNotificationsWorkerDataConverter, private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider, ) : CoroutineWorker(context, workerParams) { override suspend fun doWork(): Result = withContext(coroutineDispatchers.io) { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequest.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequest.kt index b11b83d6e4..50ef28903c 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequest.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequest.kt @@ -26,7 +26,7 @@ import java.security.InvalidParameterException class SyncNotificationWorkManagerRequest( private val sessionId: SessionId, private val notificationEventRequests: List, - private val workerDataConverter: WorkerDataConverter, + private val workerDataConverter: SyncNotificationsWorkerDataConverter, private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider, ) : WorkManagerRequest { override fun build(): Result> { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverter.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationsWorkerDataConverter.kt similarity index 99% rename from libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverter.kt rename to libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationsWorkerDataConverter.kt index 23e66396c6..46b7d760c0 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverter.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationsWorkerDataConverter.kt @@ -21,7 +21,7 @@ import io.element.android.libraries.push.api.push.NotificationEventRequest import timber.log.Timber @Inject -class WorkerDataConverter( +class SyncNotificationsWorkerDataConverter( private val json: JsonProvider, ) { fun serialize(notificationEventRequests: List): Result> { diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt index 89b8c0d319..7c95034985 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt @@ -47,7 +47,7 @@ import io.element.android.libraries.push.impl.notifications.model.NotifiableEven import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEvent import io.element.android.libraries.push.impl.test.DefaultTestPush import io.element.android.libraries.push.impl.troubleshoot.DiagnosticPushHandler -import io.element.android.libraries.push.impl.workmanager.WorkerDataConverter +import io.element.android.libraries.push.impl.workmanager.SyncNotificationsWorkerDataConverter import io.element.android.libraries.pushproviders.api.PushData import io.element.android.libraries.pushstore.api.UserPushStore import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret @@ -718,7 +718,7 @@ class DefaultPushHandlerTest { appCoroutineScope = backgroundScope, workManagerScheduler = workManagerScheduler, featureFlagService = featureFlagService, - workerDataConverter = WorkerDataConverter(DefaultJsonProvider()), + workerDataConverter = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()), buildVersionSdkIntProvider = FakeBuildVersionSdkIntProvider(33), ), appCoroutineScope = backgroundScope, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationWorkerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationWorkerTest.kt index 23a38db66c..d40ef17b53 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationWorkerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchNotificationWorkerTest.kt @@ -177,7 +177,7 @@ class FetchNotificationWorkerTest { workManagerScheduler = workManagerScheduler, syncOnNotifiableEvent = syncOnNotifiableEvent, coroutineDispatchers = testCoroutineDispatchers(), - workerDataConverter = WorkerDataConverter(DefaultJsonProvider()), + workerDataConverter = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()), buildVersionSdkIntProvider = FakeBuildVersionSdkIntProvider(33), ) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequestTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequestTest.kt index 9dae435a9a..1f8d646e2b 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequestTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/SyncNotificationWorkManagerRequestTest.kt @@ -78,7 +78,7 @@ class SyncNotificationWorkManagerRequestTest { val request = createSyncNotificationWorkManagerRequest( sessionId = A_SESSION_ID, notificationEventRequests = listOf(aNotificationEventRequest()), - workerDataConverter = WorkerDataConverter({ error("error during serialization") }) + workerDataConverter = SyncNotificationsWorkerDataConverter({ error("error during serialization") }) ) val result = request.build() assertThat(result.isFailure).isTrue() @@ -88,7 +88,7 @@ class SyncNotificationWorkManagerRequestTest { private fun createSyncNotificationWorkManagerRequest( sessionId: SessionId, notificationEventRequests: List, - workerDataConverter: WorkerDataConverter = WorkerDataConverter(DefaultJsonProvider()), + workerDataConverter: SyncNotificationsWorkerDataConverter = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()), sdkVersion: Int = 33, ) = SyncNotificationWorkManagerRequest( sessionId = sessionId, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverterTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverterTest.kt index 6c6998cb35..85b55e0d62 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverterTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/WorkerDataConverterTest.kt @@ -57,10 +57,10 @@ class WorkerDataConverterTest { providerInfo = "info$it", ) } - val sut = WorkerDataConverter(DefaultJsonProvider()) + val sut = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()) val serialized = sut.serialize(data) assertThat(serialized.getOrNull()?.size).isGreaterThan(1) - assertThat(serialized.getOrNull()?.size).isEqualTo(100 / WorkerDataConverter.CHUNK_SIZE) + assertThat(serialized.getOrNull()?.size).isEqualTo(100 / SyncNotificationsWorkerDataConverter.CHUNK_SIZE) // All the items are present val deserialized = serialized.getOrNull()?.flatMap { sut.deserialize(it)!! } assertThat(deserialized).containsExactlyElementsIn(data) @@ -76,10 +76,10 @@ class WorkerDataConverterTest { providerInfo = "info$it", ) } - val sut = WorkerDataConverter(DefaultJsonProvider()) + val sut = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()) val serialized = sut.serialize(data) assertThat(serialized.getOrNull()?.size).isGreaterThan(1) - assertThat(serialized.getOrNull()?.size).isEqualTo(100 / WorkerDataConverter.CHUNK_SIZE + 1) + assertThat(serialized.getOrNull()?.size).isEqualTo(100 / SyncNotificationsWorkerDataConverter.CHUNK_SIZE + 1) // All the items are present val deserialized = serialized.getOrNull()?.flatMap { sut.deserialize(it)!! } assertThat(deserialized).containsExactlyElementsIn(data) @@ -112,7 +112,7 @@ class WorkerDataConverterTest { ) } val data = (data1 + data2 + data3).shuffled() - val sut = WorkerDataConverter(DefaultJsonProvider()) + val sut = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()) val serialized = sut.serialize(data) assertThat(serialized.getOrNull()?.size).isEqualTo(2) // All the items are present @@ -133,7 +133,7 @@ class WorkerDataConverterTest { } private fun testIdentity(data: List) { - val sut = WorkerDataConverter(DefaultJsonProvider()) + val sut = SyncNotificationsWorkerDataConverter(DefaultJsonProvider()) val serialized = sut.serialize(data).getOrThrow() val result = sut.deserialize(serialized.first()) assertThat(result).isEqualTo(data) diff --git a/libraries/workmanager/api/src/main/kotlin/io/element/android/libraries/workmanager/api/WorkManagerScheduler.kt b/libraries/workmanager/api/src/main/kotlin/io/element/android/libraries/workmanager/api/WorkManagerScheduler.kt index b385f0b2fb..b538486d35 100644 --- a/libraries/workmanager/api/src/main/kotlin/io/element/android/libraries/workmanager/api/WorkManagerScheduler.kt +++ b/libraries/workmanager/api/src/main/kotlin/io/element/android/libraries/workmanager/api/WorkManagerScheduler.kt @@ -12,16 +12,19 @@ import io.element.android.libraries.matrix.api.core.SessionId interface WorkManagerScheduler { fun submit(workManagerRequest: WorkManagerRequest) + fun hasPendingWork(sessionId: SessionId, requestType: WorkManagerRequestType): Boolean fun cancel(sessionId: SessionId) } fun workManagerTag(sessionId: SessionId, requestType: WorkManagerRequestType): String { val prefix = when (requestType) { WorkManagerRequestType.NOTIFICATION_SYNC -> "notifications" + WorkManagerRequestType.DB_VACUUM -> "db_vacuum" } return "$prefix-$sessionId" } enum class WorkManagerRequestType { NOTIFICATION_SYNC, + DB_VACUUM, } diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index e5bd67c604..9a96d2ae73 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.workmanager.impl import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.core.bool.orFalse import dev.zacsweers.metro.SingleIn import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.observer.SessionListener @@ -51,6 +52,10 @@ class DefaultWorkManagerScheduler( ) } + override fun hasPendingWork(sessionId: SessionId, requestType: WorkManagerRequestType): Boolean { + return workManager.getWorkInfosByTag(workManagerTag(sessionId, requestType)).get()?.isNotEmpty().orFalse() + } + override fun cancel(sessionId: SessionId) { Timber.d("Cancelling work for sessionId: $sessionId") for (requestType in WorkManagerRequestType.entries) { diff --git a/libraries/workmanager/test/src/main/kotlin/io/element/android/libraries/workmanager/test/FakeWorkManagerScheduler.kt b/libraries/workmanager/test/src/main/kotlin/io/element/android/libraries/workmanager/test/FakeWorkManagerScheduler.kt index 94ee826ddc..f2caa8c743 100644 --- a/libraries/workmanager/test/src/main/kotlin/io/element/android/libraries/workmanager/test/FakeWorkManagerScheduler.kt +++ b/libraries/workmanager/test/src/main/kotlin/io/element/android/libraries/workmanager/test/FakeWorkManagerScheduler.kt @@ -10,17 +10,23 @@ package io.element.android.libraries.workmanager.test import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.workmanager.api.WorkManagerRequest +import io.element.android.libraries.workmanager.api.WorkManagerRequestType import io.element.android.libraries.workmanager.api.WorkManagerScheduler import io.element.android.tests.testutils.lambda.lambdaError class FakeWorkManagerScheduler( private val submitLambda: (WorkManagerRequest) -> Unit = { lambdaError() }, + private val hasPendingWorkLambda: (SessionId, WorkManagerRequestType) -> Boolean = { _, _ -> false }, private val cancelLambda: (SessionId) -> Unit = { lambdaError() }, ) : WorkManagerScheduler { override fun submit(workManagerRequest: WorkManagerRequest) { submitLambda(workManagerRequest) } + override fun hasPendingWork(sessionId: SessionId, requestType: WorkManagerRequestType): Boolean { + return hasPendingWorkLambda(sessionId, requestType) + } + override fun cancel(sessionId: SessionId) { cancelLambda(sessionId) } From 6887ca06d732d52849efa2e09da72c2e07f631f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 9 Dec 2025 10:11:54 +0100 Subject: [PATCH 34/64] Fix lint issues --- .../libraries/workmanager/impl/DefaultWorkManagerScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index 9a96d2ae73..476e5995a8 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -11,8 +11,8 @@ package io.element.android.libraries.workmanager.impl import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.core.bool.orFalse import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.observer.SessionListener import io.element.android.libraries.sessionstorage.api.observer.SessionObserver From d78e28be5e642a44a64022ed3c540fe336c527b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 9 Dec 2025 13:50:21 +0100 Subject: [PATCH 35/64] Make sure we schedule the vacuum task only if there isn't an existing one --- .../matrix/impl/workmanager/VacuumDatabaseWorker.kt | 12 ++++++++++-- .../workmanager/impl/DefaultWorkManagerScheduler.kt | 5 +++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt index 0602c2fdc2..c6f1b32405 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt @@ -15,6 +15,7 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.SessionId +import timber.log.Timber @AssistedInject class VacuumDatabaseWorker( @@ -27,12 +28,19 @@ class VacuumDatabaseWorker( } override suspend fun doWork(): Result { + Timber.d("Starting database vacuuming...") val sessionId = inputData.getString(SESSION_ID_PARAM)?.let(::SessionId) ?: return Result.failure() val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return Result.failure() return client.performDatabaseVacuum() .fold( - onSuccess = { Result.success() }, - onFailure = { Result.failure() } + onSuccess = { + Timber.d("Database vacuuming finished successfully") + Result.success() + }, + onFailure = { + Timber.e(it, "Database vacuuming failed") + Result.failure() + } ) } } diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index 476e5995a8..ce16e323de 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -12,7 +12,6 @@ import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn -import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.observer.SessionListener import io.element.android.libraries.sessionstorage.api.observer.SessionObserver @@ -53,7 +52,9 @@ class DefaultWorkManagerScheduler( } override fun hasPendingWork(sessionId: SessionId, requestType: WorkManagerRequestType): Boolean { - return workManager.getWorkInfosByTag(workManagerTag(sessionId, requestType)).get()?.isNotEmpty().orFalse() + val workInfos = workManager.getWorkInfosByTag(workManagerTag(sessionId, requestType)).get().orEmpty() + // It has pending work if it's periodic or it isn't but it's not finished + return workInfos.any { it.periodicityInfo != null || !it.state.isFinished } } override fun cancel(sessionId: SessionId) { From 09cab10abc65a542cf624eb4f901f253703c425f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 9 Dec 2025 15:17:45 +0100 Subject: [PATCH 36/64] Fix dependency injection --- .../matrix/impl/workmanager/VacuumDatabaseWorker.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt index c6f1b32405..2f799b362b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt @@ -10,11 +10,17 @@ package io.element.android.libraries.matrix.impl.workmanager import android.content.Context import androidx.work.CoroutineWorker import androidx.work.WorkerParameters +import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject +import dev.zacsweers.metro.ContributesIntoMap +import dev.zacsweers.metro.binding import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory +import io.element.android.libraries.workmanager.api.di.WorkerKey import timber.log.Timber @AssistedInject @@ -43,4 +49,9 @@ class VacuumDatabaseWorker( } ) } + + @ContributesIntoMap(AppScope::class, binding = binding>()) + @WorkerKey(VacuumDatabaseWorker::class) + @AssistedFactory + interface Factory : MetroWorkerFactory.WorkerInstanceFactory } From 7e3acd6b58c4f0cf5a47c11900902e65b36e3ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 08:17:57 +0100 Subject: [PATCH 37/64] Add Sentry transaction so we can check how long it takes to vacuum and if there were any errors when doing it --- .../impl/workmanager/VacuumDatabaseWorker.kt | 28 +++++++++++-------- .../analytics/api/NoopAnalyticsTransaction.kt | 1 + .../api/AnalyticsTransaction.kt | 1 + .../sentry/SentryAnalyticsTransaction.kt | 3 ++ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt index 2f799b362b..d52edddbb4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/workmanager/VacuumDatabaseWorker.kt @@ -21,6 +21,8 @@ import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory import io.element.android.libraries.workmanager.api.di.WorkerKey +import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.analytics.api.recordTransaction import timber.log.Timber @AssistedInject @@ -28,6 +30,7 @@ class VacuumDatabaseWorker( @Assisted workerParams: WorkerParameters, @ApplicationContext private val context: Context, private val matrixClientProvider: MatrixClientProvider, + private val analyticsService: AnalyticsService, ) : CoroutineWorker(context, workerParams) { companion object { const val SESSION_ID_PARAM = "session_id" @@ -37,17 +40,20 @@ class VacuumDatabaseWorker( Timber.d("Starting database vacuuming...") val sessionId = inputData.getString(SESSION_ID_PARAM)?.let(::SessionId) ?: return Result.failure() val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return Result.failure() - return client.performDatabaseVacuum() - .fold( - onSuccess = { - Timber.d("Database vacuuming finished successfully") - Result.success() - }, - onFailure = { - Timber.e(it, "Database vacuuming failed") - Result.failure() - } - ) + return analyticsService.recordTransaction("Vacuuming DBs", "vacuuming") { transaction -> + client.performDatabaseVacuum() + .fold( + onSuccess = { + Timber.d("Database vacuuming finished successfully") + Result.success() + }, + onFailure = { error -> + transaction.attachError(error) + Timber.e(error, "Database vacuuming failed") + Result.failure() + } + ) + } } @ContributesIntoMap(AppScope::class, binding = binding>()) diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/NoopAnalyticsTransaction.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/NoopAnalyticsTransaction.kt index 024a7ac05e..e6f69ae99b 100644 --- a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/NoopAnalyticsTransaction.kt +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/NoopAnalyticsTransaction.kt @@ -14,5 +14,6 @@ object NoopAnalyticsTransaction : AnalyticsTransaction { override fun setData(key: String, value: Any) {} override fun isFinished(): Boolean = true override fun traceId(): String? = null + override fun attachError(throwable: Throwable) {} override fun finish() {} } diff --git a/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsTransaction.kt b/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsTransaction.kt index ea63a7f167..84575d5dd0 100644 --- a/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsTransaction.kt +++ b/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsTransaction.kt @@ -12,6 +12,7 @@ interface AnalyticsTransaction { fun setData(key: String, value: Any) fun isFinished(): Boolean fun traceId(): String? + fun attachError(throwable: Throwable) fun finish() } diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsTransaction.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsTransaction.kt index 75872b7d44..77a008b0a4 100644 --- a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsTransaction.kt +++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsTransaction.kt @@ -23,6 +23,9 @@ class SentryAnalyticsTransaction private constructor(span: ISpan) : AnalyticsTra override fun setData(key: String, value: Any) = inner.setData(key, value) override fun traceId(): String? = inner.toSentryTrace().value override fun isFinished(): Boolean = inner.isFinished + override fun attachError(throwable: Throwable) { + inner.throwable = throwable + } override fun finish() { val name = if (inner is ITransaction) inner.name else inner.operation Timber.d("Finishing transaction: $name") From 1e52e1139fba1aca296a08035352fa59871854ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 13:22:39 +0100 Subject: [PATCH 38/64] Tweak the `DefaultWorkManagerScheduler.hasPendingWork` logic --- .../workmanager/impl/DefaultWorkManagerScheduler.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt index ce16e323de..4f3806db62 100644 --- a/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt +++ b/libraries/workmanager/impl/src/main/kotlin/io/element/android/libraries/workmanager/impl/DefaultWorkManagerScheduler.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.workmanager.impl +import androidx.work.WorkInfo import androidx.work.WorkManager import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding @@ -53,8 +54,14 @@ class DefaultWorkManagerScheduler( override fun hasPendingWork(sessionId: SessionId, requestType: WorkManagerRequestType): Boolean { val workInfos = workManager.getWorkInfosByTag(workManagerTag(sessionId, requestType)).get().orEmpty() - // It has pending work if it's periodic or it isn't but it's not finished - return workInfos.any { it.periodicityInfo != null || !it.state.isFinished } + return workInfos.any { info -> + val isPeriodic = info.periodicityInfo != null + val isCancelled = info.state == WorkInfo.State.CANCELLED + // It has pending work if: + // - It's not periodic and is not finished. + // - It's periodic and is not cancelled - since it'll be run again in a next iteration otherwise + !isPeriodic && !info.state.isFinished || isPeriodic && !isCancelled + } } override fun cancel(sessionId: SessionId) { From a59b9c86e91680bf4ee4e871a7619faf64fe39af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 13:09:00 +0100 Subject: [PATCH 39/64] URL-encode deep link path segments in `DefaultDeepLinkCreator` Decode them later in `DefaultDeepLinkParser` too --- .../libraries/androidutils/text/TextUtils.kt | 15 ++++++ .../deeplink/impl/DefaultDeepLinkCreator.kt | 9 ++-- .../deeplink/impl/DefaultDeeplinkParser.kt | 3 +- .../impl/DefaultDeepLinkCreatorTest.kt | 53 +++++++++++++++---- .../impl/DefaultDeeplinkParserTest.kt | 15 ++++++ 5 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/text/TextUtils.kt diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/text/TextUtils.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/text/TextUtils.kt new file mode 100644 index 0000000000..dde63e79a6 --- /dev/null +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/text/TextUtils.kt @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.androidutils.text + +import java.net.URLDecoder +import java.net.URLEncoder +import java.nio.charset.Charset + +fun String.urlEncoded(charset: Charset = Charsets.UTF_8): String = URLEncoder.encode(this, charset.name()) +fun String.urlDecoded(charset: Charset = Charsets.UTF_8): String = URLDecoder.decode(this, charset.name()) diff --git a/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreator.kt b/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreator.kt index 97c6eeda3f..95b7ccf116 100644 --- a/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreator.kt +++ b/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreator.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.deeplink.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.text.urlEncoded import io.element.android.libraries.deeplink.api.DeepLinkCreator import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -21,13 +22,13 @@ class DefaultDeepLinkCreator : DeepLinkCreator { override fun create(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?, eventId: EventId?): String { return buildString { append("$SCHEME://$HOST/") - append(sessionId.value) + append(sessionId.value.urlEncoded()) append("/") - append(roomId?.value.orEmpty()) + append(roomId?.value?.urlEncoded().orEmpty()) append("/") - append(threadId?.value.orEmpty()) + append(threadId?.value?.urlEncoded().orEmpty()) append("/") - append(eventId?.value.orEmpty()) + append(eventId?.value?.urlEncoded().orEmpty()) } // Remove all possible trailing '/' characters: // No event id diff --git a/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParser.kt b/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParser.kt index ca1a39d5d0..8c865b6557 100644 --- a/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParser.kt +++ b/libraries/deeplink/impl/src/main/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParser.kt @@ -12,6 +12,7 @@ import android.content.Intent import android.net.Uri import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.text.urlDecoded import io.element.android.libraries.deeplink.api.DeeplinkData import io.element.android.libraries.deeplink.api.DeeplinkParser import io.element.android.libraries.matrix.api.core.EventId @@ -31,7 +32,7 @@ class DefaultDeeplinkParser : DeeplinkParser { private fun Uri.toDeeplinkData(): DeeplinkData? { if (scheme != SCHEME) return null if (host != HOST) return null - val pathBits = path.orEmpty().split("/").drop(1) + val pathBits = encodedPath.orEmpty().split("/").drop(1).map { it.urlDecoded() } val sessionId = pathBits.elementAtOrNull(0)?.let(::SessionId) ?: return null return when (val screenPathComponent = pathBits.elementAtOrNull(1)) { diff --git a/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt b/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt index 4e3a10e861..ee01b20a8f 100644 --- a/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt +++ b/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt @@ -9,6 +9,11 @@ package io.element.android.libraries.deeplink.impl import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.androidutils.text.urlEncoded +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID @@ -19,15 +24,43 @@ class DefaultDeepLinkCreatorTest { @Test fun create() { val sut = DefaultDeepLinkCreator() - assertThat(sut.create(A_SESSION_ID, null, null, null)) - .isEqualTo("elementx://open/@alice:server.org") - assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, null, null)) - .isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain") - assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID, null)) - .isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId") - assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID, AN_EVENT_ID)) - .isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId/\$anEventId") - assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, null, AN_EVENT_ID)) - .isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain//\$anEventId") + val sessionId = A_SESSION_ID + val roomId = A_ROOM_ID + val threadId = A_THREAD_ID + val eventId = AN_EVENT_ID + assertThat(sut.create(sessionId, null, null, null)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, null, null)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, threadId, null)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, threadId, eventId)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}/${eventId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, null, eventId)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}//${eventId.urlEncoded()}") + } + + @Test + fun `create - with escaped invalid characters`() { + val sut = DefaultDeepLinkCreator() + val sessionId = SessionId("@a/:domain") + val roomId = RoomId("!a/RoomId:domain") + val threadId = ThreadId("\$a/ThreadId") + val eventId = EventId("\$an/EventId") + assertThat(sut.create(sessionId, null, null, null)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, null, null)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, threadId, null)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, threadId, eventId)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}/${eventId.urlEncoded()}") + assertThat(sut.create(sessionId, roomId, null, eventId)) + .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}//${eventId.urlEncoded()}") } } + +private fun SessionId.urlEncoded() = this.value.urlEncoded() +private fun RoomId.urlEncoded() = this.value.urlEncoded() +private fun ThreadId.urlEncoded() = this.value.urlEncoded() +private fun EventId.urlEncoded() = this.value.urlEncoded() diff --git a/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParserTest.kt b/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParserTest.kt index 4b79f2b08c..7f563ddd7f 100644 --- a/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParserTest.kt +++ b/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeeplinkParserTest.kt @@ -12,6 +12,10 @@ import android.content.Intent import androidx.core.net.toUri import com.google.common.truth.Truth.assertThat import io.element.android.libraries.deeplink.api.DeeplinkData +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID @@ -34,6 +38,8 @@ class DefaultDeeplinkParserTest { "elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId/\$anEventId" const val A_URI_WITH_ROOM_WITH_EVENT_AND_NO_THREAD = "elementx://open/@alice:server.org/!aRoomId:domain//\$anEventId" + const val A_URI_WITH_ROOM_WITH_THREAD_AND_EVENT_AND_INVALID_CHARACTERS = + "elementx://open/@a%2Flice:server.org/!a%2FRoomId:domain/\$a%2FThreadId/\$an%2FEventId" } @Test @@ -49,6 +55,15 @@ class DefaultDeeplinkParserTest { .isEqualTo(DeeplinkData.Room(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID, AN_EVENT_ID)) assertThat(sut.getFromIntent(createIntent(A_URI_WITH_ROOM_WITH_EVENT_AND_NO_THREAD))) .isEqualTo(DeeplinkData.Room(A_SESSION_ID, A_ROOM_ID, null, AN_EVENT_ID)) + assertThat(sut.getFromIntent(createIntent(A_URI_WITH_ROOM_WITH_THREAD_AND_EVENT_AND_INVALID_CHARACTERS))) + .isEqualTo( + DeeplinkData.Room( + sessionId = SessionId("@a/lice:server.org"), + roomId = RoomId("!a/RoomId:domain"), + threadId = ThreadId("\$a/ThreadId"), + eventId = EventId("\$an/EventId"), + ) + ) } @Test From fc9ba17f8498ca3119374d83269357baa3c58930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 15:27:36 +0100 Subject: [PATCH 40/64] Use the raw expected string for `DefaultDeepLinkCreatorTest` cases --- .../impl/DefaultDeepLinkCreatorTest.kt | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt b/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt index ee01b20a8f..b27a645802 100644 --- a/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt +++ b/libraries/deeplink/impl/src/test/kotlin/io/element/android/libraries/deeplink/impl/DefaultDeepLinkCreatorTest.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.deeplink.impl import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.androidutils.text.urlEncoded import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId @@ -29,15 +28,15 @@ class DefaultDeepLinkCreatorTest { val threadId = A_THREAD_ID val eventId = AN_EVENT_ID assertThat(sut.create(sessionId, null, null, null)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}") + .isEqualTo("elementx://open/%40alice%3Aserver.org") assertThat(sut.create(sessionId, roomId, null, null)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}") + .isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain") assertThat(sut.create(sessionId, roomId, threadId, null)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}") + .isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain/%24aThreadId") assertThat(sut.create(sessionId, roomId, threadId, eventId)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}/${eventId.urlEncoded()}") + .isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain/%24aThreadId/%24anEventId") assertThat(sut.create(sessionId, roomId, null, eventId)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}//${eventId.urlEncoded()}") + .isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain//%24anEventId") } @Test @@ -47,20 +46,13 @@ class DefaultDeepLinkCreatorTest { val roomId = RoomId("!a/RoomId:domain") val threadId = ThreadId("\$a/ThreadId") val eventId = EventId("\$an/EventId") - assertThat(sut.create(sessionId, null, null, null)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}") assertThat(sut.create(sessionId, roomId, null, null)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}") + .isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain") assertThat(sut.create(sessionId, roomId, threadId, null)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}") + .isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain/%24a%2FThreadId") assertThat(sut.create(sessionId, roomId, threadId, eventId)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}/${threadId.urlEncoded()}/${eventId.urlEncoded()}") + .isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain/%24a%2FThreadId/%24an%2FEventId") assertThat(sut.create(sessionId, roomId, null, eventId)) - .isEqualTo("elementx://open/${sessionId.urlEncoded()}/${roomId.urlEncoded()}//${eventId.urlEncoded()}") + .isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain//%24an%2FEventId") } } - -private fun SessionId.urlEncoded() = this.value.urlEncoded() -private fun RoomId.urlEncoded() = this.value.urlEncoded() -private fun ThreadId.urlEncoded() = this.value.urlEncoded() -private fun EventId.urlEncoded() = this.value.urlEncoded() From 287d0a38d71c07c120fc56cc9a72cf6ec07a3f6b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 13:18:28 +0000 Subject: [PATCH 41/64] fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v25.12.10 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8245e730af..1ed3ea4f4e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -177,7 +177,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.12.4" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.12.10" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 289c0751d53dd7e58eccafc50d5496848434c6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 15:55:44 +0100 Subject: [PATCH 42/64] Fix broken API changes: use `Room.latestEvent`, which will keep its name, but it'll be using the logic previously in `Room.newLatestEvent` --- .../matrix/impl/roomlist/RoomSummaryFactory.kt | 2 +- .../matrix/impl/fixtures/fakes/FakeFfiRoom.kt | 10 ++-------- .../impl/roomlist/RoomSummaryListProcessorTest.kt | 3 +-- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt index 3d5efedd54..4872dc48e8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt @@ -24,7 +24,7 @@ class RoomSummaryFactory( ) { suspend fun create(room: Room): RoomSummary { val roomInfo = room.roomInfo().let(roomInfoMapper::map) - val latestEvent = room.newLatestEvent().use { event -> + val latestEvent = room.latestEvent().use { event -> when (event) { is RustLatestEventValue.None -> LatestEventValue.None is RustLatestEventValue.Local -> LatestEventValue.Local( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt index 7b60a9f4c2..953e42b132 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoom.kt @@ -12,7 +12,6 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.tests.testutils.lambda.lambdaError -import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.LatestEventValue import org.matrix.rustcomponents.sdk.NoHandle import org.matrix.rustcomponents.sdk.Room @@ -25,8 +24,7 @@ class FakeFfiRoom( private val getMembers: () -> RoomMembersIterator = { lambdaError() }, private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() }, private val leaveLambda: () -> Unit = { lambdaError() }, - private val latestEventLambda: () -> EventTimelineItem? = { lambdaError() }, - private val newLatestEventLambda: () -> LatestEventValue = { lambdaError() }, + private val latestEventLambda: () -> LatestEventValue = { lambdaError() }, private val suggestedRoleForUserLambda: (String) -> RoomMemberRole = { lambdaError() }, private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value), ) : Room(NoHandle) { @@ -50,7 +48,7 @@ class FakeFfiRoom( return roomInfo } - override suspend fun latestEvent(): EventTimelineItem? { + override suspend fun latestEvent(): LatestEventValue { return latestEventLambda() } @@ -58,10 +56,6 @@ class FakeFfiRoom( return suggestedRoleForUserLambda(userId) } - override suspend fun newLatestEvent(): LatestEventValue { - return newLatestEventLambda() - } - override fun close() { // No-op } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index 36d5b81f42..78c4f54626 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -174,8 +174,7 @@ class RoomSummaryListProcessorTest { private fun aRustRoom(roomId: RoomId = A_ROOM_ID) = FakeFfiRoom( roomId = roomId, - latestEventLambda = { null }, - newLatestEventLambda = { LatestEventValue.None } + latestEventLambda = { LatestEventValue.None } ) private fun TestScope.createProcessor() = RoomSummaryListProcessor( From 9723a7c426fef9f950e02ea16ea32100bece4925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 15:55:52 +0100 Subject: [PATCH 43/64] Add missing trace log packs --- .../android/libraries/matrix/api/tracing/TraceLogPack.kt | 6 ++++++ .../libraries/matrix/impl/tracing/TraceLogPacksMapping.kt | 2 ++ 2 files changed, 8 insertions(+) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TraceLogPack.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TraceLogPack.kt index 4f71f7309c..a0e5050a23 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TraceLogPack.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TraceLogPack.kt @@ -20,6 +20,12 @@ enum class TraceLogPack(val key: String) { }, NOTIFICATION_CLIENT("notification_client") { override val title: String = "Notification Client" + }, + SYNC_PROFILING("sync_profiling") { + override val title: String = "Sync Profiling" + }, + LATEST_EVENTS("latest_events") { + override val title = "Latest Events" }; abstract val title: String diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TraceLogPacksMapping.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TraceLogPacksMapping.kt index 0e26935b5a..ec70fc90f8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TraceLogPacksMapping.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TraceLogPacksMapping.kt @@ -16,6 +16,8 @@ fun TraceLogPack.map(): RustTraceLogPack = when (this) { TraceLogPack.EVENT_CACHE -> RustTraceLogPack.EVENT_CACHE TraceLogPack.TIMELINE -> RustTraceLogPack.TIMELINE TraceLogPack.NOTIFICATION_CLIENT -> RustTraceLogPack.NOTIFICATION_CLIENT + TraceLogPack.LATEST_EVENTS -> RustTraceLogPack.LATEST_EVENTS + TraceLogPack.SYNC_PROFILING -> RustTraceLogPack.SYNC_PROFILING } fun Collection.map(): List { From 8d0e2e669e6f2b536b26b55b8d9f5b5247ee95c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 10 Dec 2025 16:40:53 +0100 Subject: [PATCH 44/64] Improve proguard config to keep the names in the classes in out packages --- app/proguard-rules.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 96109425fa..320db8c4c1 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -69,4 +69,4 @@ -keep class org.matrix.rustcomponents.sdk.** { *;} -keep class uniffi.** { *;} -keep class io.element.android.x.di.** { *; } --keepnames class io.element.android.x.** +-keepnames class io.element.android.** From cf00b799f23cc6a72f67931a16d522b7d0dff5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 11 Dec 2025 09:38:39 +0100 Subject: [PATCH 45/64] Make explicit we want to keep the member names too, but we want to allow optimization of the code and shrinking when methods aren't used --- app/proguard-rules.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 320db8c4c1..d915d67a25 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -69,4 +69,4 @@ -keep class org.matrix.rustcomponents.sdk.** { *;} -keep class uniffi.** { *;} -keep class io.element.android.x.di.** { *; } --keepnames class io.element.android.** +-keepclasseswithmembernames,allowoptimization,allowshrinking class io.element.android.** { *; } From 6d93ce25aa92aee83362ec0b2d474cd7470f07d2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Dec 2025 13:52:30 +0100 Subject: [PATCH 46/64] RoomSummary: move the icon related to the last message state on start of the message. --- .../home/impl/components/RoomSummaryRow.kt | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index b722c63622..50b9559e94 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -121,7 +121,6 @@ internal fun RoomSummaryRow( ) { NameAndTimestampRow( name = room.name, - latestEvent = room.latestEvent, timestamp = room.timestamp, isHighlighted = room.isHighlighted ) @@ -138,7 +137,6 @@ internal fun RoomSummaryRow( ) { NameAndTimestampRow( name = room.name, - latestEvent = room.latestEvent, timestamp = null, isHighlighted = room.isHighlighted ) @@ -214,7 +212,6 @@ private fun RoomSummaryScaffoldRow( @Composable private fun NameAndTimestampRow( name: String?, - latestEvent: LatestEvent, timestamp: String?, isHighlighted: Boolean, modifier: Modifier = Modifier @@ -236,29 +233,6 @@ private fun NameAndTimestampRow( maxLines = 1, overflow = TextOverflow.Ellipsis ) - // Picto - when (latestEvent) { - is LatestEvent.Sending -> { - Spacer(modifier = Modifier.width(4.dp)) - Icon( - modifier = Modifier.size(16.dp), - imageVector = CompoundIcons.Time(), - contentDescription = stringResource(CommonStrings.common_sending), - tint = ElementTheme.colors.iconTertiary, - ) - } - is LatestEvent.Error -> { - Spacer(modifier = Modifier.width(4.dp)) - Icon( - modifier = Modifier.size(16.dp), - imageVector = CompoundIcons.ErrorSolid(), - // The last message contains the error. - contentDescription = null, - tint = ElementTheme.colors.iconCriticalPrimary, - ) - } - else -> Unit - } } // Timestamp Text( @@ -303,7 +277,6 @@ private fun MessagePreviewAndIndicatorRow( ) { Row( modifier = modifier.fillMaxWidth(), - horizontalArrangement = spacedBy(28.dp) ) { if (room.isTombstoned) { Text( @@ -317,6 +290,16 @@ private fun MessagePreviewAndIndicatorRow( ) } else { if (room.latestEvent is LatestEvent.Error) { + Icon( + modifier = Modifier + .padding(top = 2.dp) + .size(16.dp), + imageVector = CompoundIcons.ErrorSolid(), + // The last message contains the error. + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary, + ) + Spacer(modifier = Modifier.width(6.dp)) Text( modifier = Modifier.weight(1f), text = stringResource(CommonStrings.common_message_failed_to_send), @@ -327,6 +310,17 @@ private fun MessagePreviewAndIndicatorRow( overflow = TextOverflow.Ellipsis, ) } else { + if (room.latestEvent is LatestEvent.Sending) { + Icon( + modifier = Modifier + .padding(top = 2.dp) + .size(16.dp), + imageVector = CompoundIcons.Time(), + contentDescription = stringResource(CommonStrings.common_sending), + tint = ElementTheme.colors.iconTertiary, + ) + Spacer(modifier = Modifier.width(6.dp)) + } val messagePreview = room.latestEvent.content() val annotatedMessagePreview = messagePreview as? AnnotatedString ?: AnnotatedString(text = messagePreview.orEmpty().toString()) Text( @@ -340,7 +334,7 @@ private fun MessagePreviewAndIndicatorRow( ) } } - + Spacer(modifier = Modifier.width(16.dp)) // Call and unread Row( modifier = Modifier From 6876d0da223918239d3b2f42b9a82f2552fc6d0e Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 11 Dec 2025 14:06:53 +0000 Subject: [PATCH 47/64] Update screenshots --- ...ures.home.impl.components_RoomListContentView_Day_0_en.png | 4 ++-- ...ures.home.impl.components_RoomListContentView_Day_5_en.png | 4 ++-- ...es.home.impl.components_RoomListContentView_Night_0_en.png | 4 ++-- ...es.home.impl.components_RoomListContentView_Night_5_en.png | 4 ++-- ...features.home.impl.components_RoomSummaryRow_Day_36_en.png | 4 ++-- ...features.home.impl.components_RoomSummaryRow_Day_37_en.png | 4 ++-- .../features.home.impl.components_RoomSummaryRow_Day_4_en.png | 4 ++-- ...atures.home.impl.components_RoomSummaryRow_Night_36_en.png | 4 ++-- ...atures.home.impl.components_RoomSummaryRow_Night_37_en.png | 4 ++-- ...eatures.home.impl.components_RoomSummaryRow_Night_4_en.png | 4 ++-- ...atures.home.impl.search_RoomListSearchContent_Day_1_en.png | 4 ++-- ...ures.home.impl.search_RoomListSearchContent_Night_1_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeViewA11y_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_0_en.png | 4 ++-- .../images/features.home.impl_HomeView_Day_13_en.png | 4 ++-- .../images/features.home.impl_HomeView_Day_14_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_1_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_2_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_5_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_9_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_0_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_13_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_14_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_1_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_2_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_5_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_9_en.png | 4 ++-- ...crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png | 3 --- ...ypto.historyvisible_HistoryVisibleStateView_Night_1_en.png | 3 --- ...historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png | 3 --- ...storyvisible_MessagesViewWithHistoryVisible_Night_1_en.png | 3 --- 31 files changed, 54 insertions(+), 66 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_0_en.png index a3abd4937d..2b4bab0904 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4013ad25e9f4e38109e7ee49921814adc8ec5e4952c8f8d4d6946a4badf67081 -size 41513 +oid sha256:5ad4cbbad7f8d12579ea2336dbe90519d164baf1ba5ca1d1398f598c699a37b3 +size 41814 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_5_en.png index 53a25223bd..bbf55e44a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d035c3d696dae89026dbcc8cfc918a98cc8bb8b3f79548b57d36b96b29f097f -size 59908 +oid sha256:b9a6f816acf13335c15e188cb6d9d240aa9f19e76f80c65cb6ce5d02036b4d92 +size 60017 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_0_en.png index dd6b0742fd..2721654be9 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1720068dd3f0b75076ef81642d680f00e52f7162247beb30dc515fb74c25cf2a -size 41164 +oid sha256:2cffbce8a793651437dc5ff93c697d859df047a71a6a128996c41af918ad18fc +size 41499 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_5_en.png index 71048bb36d..53fc2dba28 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomListContentView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf2cedb0979d0eb916df2a1810c7d872d159214b0e26d5b3a353001dfed0aa06 -size 58935 +oid sha256:ca660f44ee031e98540134d3b37743dbb893566a6a8359dfbd4dd4da87bc2e83 +size 59128 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_36_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_36_en.png index fb772998e4..9462c2e058 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_36_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_36_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:761e963499f97f21b5c5b8b80e5d75092fbc4305371bcc413f595b503890d511 -size 13085 +oid sha256:c125c71ef07cc228ea24bd34a43091e0728d529d2303e44684529f32beaa09f8 +size 13113 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_37_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_37_en.png index 42db131266..93c9eb369e 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_37_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_37_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de31aa3dbb9c9427189621d35022211220197de8ed8584f36801eb99d613f0b1 -size 13728 +oid sha256:c7b78a9d066b454130ad08bfa035a2afafa6ec1711d88921a7fabb84a73b01ee +size 13616 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_4_en.png index b95547f00a..e6443ec3f7 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:929d7eb7ea27b4638a8bb71093f6c0d7c01da4d7bf563ebaf31c91657f3db7fb -size 20629 +oid sha256:2a8c23e9560ba89e226390862ab0b724465ebb2ab7c20e5a41f2df72b9ee76a1 +size 21024 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_36_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_36_en.png index bb29aaa4b5..132c8a716a 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_36_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_36_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f7327f29c9236b549d7f5037e3483e487a23902c5c30bd20a7a4bc0e6c13bec -size 13009 +oid sha256:a49cc5e58070d5af3fb905076a41ce5cb0bf77eda4d34550d8e7ac1f4c771472 +size 12981 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_37_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_37_en.png index c8ce9b58a1..640ad68f5b 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_37_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_37_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f92a70303d515a135eb87eac344dc4a974183da8773524a48f790b31a70338e8 -size 13528 +oid sha256:3377bf16f847083f340218bd6bf4f4f3290d354c06193a808402f26ee34ea8a7 +size 13432 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_4_en.png index 73823e4199..c8c2170780 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:112dcba335114372a39a531be0ad6350f1bcdffe03d4c6033d2a4799715bed6d -size 20300 +oid sha256:ff0df80592079fadfbf82b192ed79e9684dce58d146bf2e571a04c6784a9e6bc +size 20696 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Day_1_en.png index fdf4fd6693..bc04f12385 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10d68a9d1c5913fe9c14edd6d3663b7692f9c9031dd08205ad290c4d1f1593bf -size 43973 +oid sha256:de647a2d609bb2ac37875767780dccfa34d47b68da504b59ebb27e2f8d989452 +size 44250 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Night_1_en.png index 30bb25d9f9..93624ab755 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.search_RoomListSearchContent_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fb9912ee3b7489424e9f364610cb4f9c7c3276e17f7e6fe75c2be7a3cd84bf4 -size 43434 +oid sha256:1decbfcf1afc6d2f827d570ef0145674ab1f598ce375b95331ca83975793509e +size 43762 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png index e2340106b8..7323ddc95f 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3530f2d4ba4b189c7e40c19548fe1d44fea844505ed411cd476eb41add5aac5 -size 122437 +oid sha256:88dff52e06c62a7df91c08ed0237068a2e8bcdfd5f83426a52cf7a3097ee8cfa +size 122935 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_0_en.png index c87b2327c8..3e870ea8d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f321d5352e1966b44e13b4b9e56da3f2cfd14e5eb4a468b61b1939799d364a -size 61182 +oid sha256:580c70e645e954e9e3d29a68aa46b1eae3a82651eb5e419eb92cba48bf7baaf1 +size 61515 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_13_en.png index 7728b33306..343550c109 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf7d32047c608340c06edfb8ade3cc8b92858eaa763fedafa915c16439657fc2 -size 88205 +oid sha256:821cb6a2068561375d0988d4ba5404e52411a6d9b73cefbe1a6bd7bc6d467673 +size 88367 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_14_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_14_en.png index 32cf426e12..191d910e04 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abf95575cbd55470c798accf988bc6a509daea71eded4108857595993873df4e -size 81038 +oid sha256:f9f5fef39d80aacb9666deeea43e4df48f7c70231bd8ec41edf2f3eed5f0aa42 +size 81149 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_1_en.png index c87b2327c8..3e870ea8d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f321d5352e1966b44e13b4b9e56da3f2cfd14e5eb4a468b61b1939799d364a -size 61182 +oid sha256:580c70e645e954e9e3d29a68aa46b1eae3a82651eb5e419eb92cba48bf7baaf1 +size 61515 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_2_en.png index c87b2327c8..3e870ea8d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f321d5352e1966b44e13b4b9e56da3f2cfd14e5eb4a468b61b1939799d364a -size 61182 +oid sha256:580c70e645e954e9e3d29a68aa46b1eae3a82651eb5e419eb92cba48bf7baaf1 +size 61515 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_5_en.png index c87b2327c8..3e870ea8d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f321d5352e1966b44e13b4b9e56da3f2cfd14e5eb4a468b61b1939799d364a -size 61182 +oid sha256:580c70e645e954e9e3d29a68aa46b1eae3a82651eb5e419eb92cba48bf7baaf1 +size 61515 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_9_en.png index 4c31f1f2ee..277cd740bb 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:196cad6f5c3d01d52c88713526848d7905b59b49866f27f6e420df0b6b8f9e73 -size 80857 +oid sha256:a5a68b4d8951b7c516561d538c5d328a84948c66af7eb7c80ac77cd005620cf2 +size 80977 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_0_en.png index 2366c44bf9..a46c9d21bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e9b4b3247cf2f540866286de61760a45956d8179891aeb669b4763bdd29393d -size 57993 +oid sha256:37660e7c0626ae3e5a8404fdc7e57e41d43750abb4004572ffd9c25a501c668e +size 58325 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_13_en.png index 54fd5321eb..8094781a7f 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7ff4652d94dec6bc98b3f1dea0d182576c7bfc72e39f232d224046e6492b55e -size 83764 +oid sha256:541740cdd54ef7b9a868c1409330a6ca7417bce9f022b22c3d395ac9b215d470 +size 83939 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_14_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_14_en.png index 766b356208..40695d7c0c 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb1d9b5143703ec9a8035e11374c7e56ce4d3f836005632a109e5556b141c59b -size 77098 +oid sha256:a44897f23fc0e6a90779fe96638c560973caf7dbb9a7c92ec4d2f5b56de3ddcc +size 77280 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_1_en.png index 2366c44bf9..a46c9d21bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e9b4b3247cf2f540866286de61760a45956d8179891aeb669b4763bdd29393d -size 57993 +oid sha256:37660e7c0626ae3e5a8404fdc7e57e41d43750abb4004572ffd9c25a501c668e +size 58325 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_2_en.png index 2366c44bf9..a46c9d21bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e9b4b3247cf2f540866286de61760a45956d8179891aeb669b4763bdd29393d -size 57993 +oid sha256:37660e7c0626ae3e5a8404fdc7e57e41d43750abb4004572ffd9c25a501c668e +size 58325 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_5_en.png index 2366c44bf9..a46c9d21bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e9b4b3247cf2f540866286de61760a45956d8179891aeb669b4763bdd29393d -size 57993 +oid sha256:37660e7c0626ae3e5a8404fdc7e57e41d43750abb4004572ffd9c25a501c668e +size 58325 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_9_en.png index fdfec064e2..fc269825f1 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:101d0425024c30f2dce8b6d91ed2416fc115c4bf3719fd6c46093705ba4ef772 -size 76985 +oid sha256:49ea33ae74532c350b4176355203561cfc5eb79c93c4993d6ffb0cf933f8ad2f +size 77167 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png deleted file mode 100644 index d19a140456..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96bc0c555188cee4b3f3e3e0f28f944a4225e27b9a1069edf2b10a2993ee3080 -size 26078 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png deleted file mode 100644 index d21a12dd64..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a103daf8447cb571a0c5010d062a7790aaa0f3dce30f052bf86884708f4881a5 -size 28769 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png deleted file mode 100644 index 22d05e61fa..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9682cdd7e08e32591fa47f56da5e6ef4cc3a777700931c2c86e9b802a9cf25cb -size 67342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png deleted file mode 100644 index b2bb8ac3fc..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d20c04c6385e675bd71d93d2d5d832509b1300a27708245755f263392b33bc8a -size 69457 From 4f5ce5711d41d2ca4a960c6bb19262763007a29e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Dec 2025 17:05:42 +0100 Subject: [PATCH 48/64] Remove nullability --- .../io/element/android/libraries/qrcode/QRCodeAnalyzer.kt | 7 +++++-- .../element/android/libraries/qrcode/QrCodeCameraView.kt | 7 +------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt index ab2ee2ce7b..e9d43d86a3 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt @@ -15,7 +15,7 @@ import timber.log.Timber import zxingcpp.BarcodeReader internal class QRCodeAnalyzer( - private val onScanQrCode: (result: ByteArray?) -> Unit + private val onScanQrCode: (data: ByteArray) -> Unit ) : ImageAnalysis.Analyzer { private val reader by lazy { BarcodeReader() } @@ -23,7 +23,10 @@ internal class QRCodeAnalyzer( if (image.format in SUPPORTED_IMAGE_FORMATS) { try { val bytes = reader.read(image).firstNotNullOfOrNull { it.bytes } - bytes?.let { onScanQrCode(it) } + if (bytes != null) { + Timber.d("QR code scanned!") + onScanQrCode(bytes) + } } catch (e: Exception) { Timber.w(e, "Error decoding QR code") } finally { diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt index a0d6613a3f..8c7563c5f8 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt @@ -80,12 +80,7 @@ fun QrCodeCameraView( .build() imageAnalysis.setAnalyzer( ContextCompat.getMainExecutor(previewView.context), - QRCodeAnalyzer { result -> - result?.let { - Timber.d("QR code scanned!") - onScanQrCode(it) - } - } + QRCodeAnalyzer(onScanQrCode) ) try { // Make sure we unbind all use cases before binding them again From efa5c7794d575014583f37af4e1eabad80c5571e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Dec 2025 17:07:55 +0100 Subject: [PATCH 49/64] Improve code --- .../libraries/qrcode/QRCodeAnalyzer.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt index e9d43d86a3..168e898965 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QRCodeAnalyzer.kt @@ -20,17 +20,19 @@ internal class QRCodeAnalyzer( private val reader by lazy { BarcodeReader() } override fun analyze(image: ImageProxy) { - if (image.format in SUPPORTED_IMAGE_FORMATS) { - try { - val bytes = reader.read(image).firstNotNullOfOrNull { it.bytes } - if (bytes != null) { - Timber.d("QR code scanned!") - onScanQrCode(bytes) + image.use { + if (image.format in SUPPORTED_IMAGE_FORMATS) { + try { + val bytes = reader.read(image).firstNotNullOfOrNull { it.bytes } + if (bytes != null) { + Timber.d("QR code scanned!") + onScanQrCode(bytes) + } + } catch (e: Exception) { + Timber.w(e, "Error decoding QR code") } - } catch (e: Exception) { - Timber.w(e, "Error decoding QR code") - } finally { - image.close() + } else { + Timber.w("Unsupported image format: ${image.format}") } } } From 6100d4944f0f7f87b8a2975a56de3bf2af45200e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Dec 2025 17:23:34 +0100 Subject: [PATCH 50/64] Cleanup --- .../screens/qrcode/scan/QrCodeScanView.kt | 2 +- .../libraries/qrcode/QrCodeCameraView.kt | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanView.kt index 4f444b14bc..6fa3d1b0c7 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanView.kt @@ -106,7 +106,7 @@ private fun Content( QrCodeCameraView( modifier = Modifier.fillMaxSize(), onScanQrCode = { state.eventSink.invoke(QrCodeScanEvents.QrCodeScanned(it)) }, - renderPreview = state.isScanning, + isScanning = state.isScanning, ) } } diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt index 8c7563c5f8..e687d4a945 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt @@ -45,7 +45,7 @@ import kotlin.coroutines.suspendCoroutine @Composable fun QrCodeCameraView( onScanQrCode: (ByteArray) -> Unit, - renderPreview: Boolean, + isScanning: Boolean, modifier: Modifier = Modifier, ) { if (LocalInspectionMode.current) { @@ -73,13 +73,13 @@ fun QrCodeCameraView( cameraProvider = localContext.getCameraProvider() } - suspend fun startQRCodeAnalysis(cameraProvider: ProcessCameraProvider, previewView: PreviewView, attempt: Int = 1) { + suspend fun startQRCodeAnalysis(cameraProvider: ProcessCameraProvider, attempt: Int = 1) { lastFrame = null val cameraSelector = CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build() imageAnalysis.setAnalyzer( - ContextCompat.getMainExecutor(previewView.context), + ContextCompat.getMainExecutor(localContext), QRCodeAnalyzer(onScanQrCode) ) try { @@ -100,7 +100,7 @@ fun QrCodeCameraView( } else { Timber.e(e, "Use case binding failed (attempt #$attempt). Retrying after a delay...") delay(100) - startQRCodeAnalysis(cameraProvider, previewView, attempt + 1) + startQRCodeAnalysis(cameraProvider, attempt + 1) } } } @@ -123,16 +123,18 @@ fun QrCodeCameraView( AndroidView( factory = { context -> val previewView = PreviewView(context) - previewUseCase.setSurfaceProvider(previewView.surfaceProvider) + previewUseCase.surfaceProvider = previewView.surfaceProvider previewView.previewStreamState.observe(lifecycleOwner) { state -> previewView.alpha = if (state == PreviewView.StreamState.STREAMING) 1f else 0f } previewView }, update = { previewView -> - if (renderPreview) { + if (isScanning) { cameraProvider?.let { provider -> - coroutineScope.launch { startQRCodeAnalysis(provider, previewView) } + coroutineScope.launch { + startQRCodeAnalysis(provider) + } } } else { stopQRCodeAnalysis(previewView) @@ -150,12 +152,14 @@ fun QrCodeCameraView( } } -@Suppress("BlockingMethodInNonBlockingContext") private suspend fun Context.getCameraProvider(): ProcessCameraProvider = suspendCoroutine { continuation -> ProcessCameraProvider.getInstance(this).also { cameraProvider -> - cameraProvider.addListener({ - continuation.resume(cameraProvider.get()) - }, ContextCompat.getMainExecutor(this)) + cameraProvider.addListener( + { + continuation.resume(cameraProvider.get()) + }, + ContextCompat.getMainExecutor(this) + ) } } From 06c20e3abf6870595b342ad6ad40d6ad0d2fc467 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 11 Dec 2025 17:33:24 +0100 Subject: [PATCH 51/64] Move usage of LocalInspectionMode.current into the deeper block. --- .../libraries/qrcode/QrCodeCameraView.kt | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt index e687d4a945..7f089818d0 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt @@ -48,78 +48,78 @@ fun QrCodeCameraView( isScanning: Boolean, modifier: Modifier = Modifier, ) { - if (LocalInspectionMode.current) { - Box( - modifier = modifier - .background(color = ElementTheme.colors.bgSubtlePrimary), - contentAlignment = Alignment.Center, - ) { - Text("CameraView") - } - } else { - val coroutineScope = rememberCoroutineScope() - val localContext = LocalContext.current - val lifecycleOwner = LocalLifecycleOwner.current - var cameraProvider by remember { mutableStateOf(null) } - val previewUseCase = remember { Preview.Builder().build() } - var lastFrame by remember { mutableStateOf(null) } - val imageAnalysis = remember { - ImageAnalysis.Builder() - .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) - .build() - } + val coroutineScope = rememberCoroutineScope() + val localContext = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + var cameraProvider by remember { mutableStateOf(null) } + val previewUseCase = remember { Preview.Builder().build() } + var lastFrame by remember { mutableStateOf(null) } + val imageAnalysis = remember { + ImageAnalysis.Builder() + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build() + } - LaunchedEffect(Unit) { - cameraProvider = localContext.getCameraProvider() - } + LaunchedEffect(Unit) { + cameraProvider = localContext.getCameraProvider() + } - suspend fun startQRCodeAnalysis(cameraProvider: ProcessCameraProvider, attempt: Int = 1) { - lastFrame = null - val cameraSelector = CameraSelector.Builder() - .requireLensFacing(CameraSelector.LENS_FACING_BACK) - .build() - imageAnalysis.setAnalyzer( - ContextCompat.getMainExecutor(localContext), - QRCodeAnalyzer(onScanQrCode) + suspend fun startQRCodeAnalysis(cameraProvider: ProcessCameraProvider, attempt: Int = 1) { + lastFrame = null + val cameraSelector = CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build() + imageAnalysis.setAnalyzer( + ContextCompat.getMainExecutor(localContext), + QRCodeAnalyzer(onScanQrCode) + ) + try { + // Make sure we unbind all use cases before binding them again + cameraProvider.unbindAll() + + cameraProvider.bindToLifecycle( + lifecycleOwner, + cameraSelector, + previewUseCase, + imageAnalysis, ) - try { - // Make sure we unbind all use cases before binding them again - cameraProvider.unbindAll() - - cameraProvider.bindToLifecycle( - lifecycleOwner, - cameraSelector, - previewUseCase, - imageAnalysis - ) - lastFrame = null - } catch (e: Exception) { - val maxAttempts = 3 - if (attempt > maxAttempts) { - Timber.e(e, "Use case binding failed after $maxAttempts attempts. Giving up.") - } else { - Timber.e(e, "Use case binding failed (attempt #$attempt). Retrying after a delay...") - delay(100) - startQRCodeAnalysis(cameraProvider, attempt + 1) - } + lastFrame = null + } catch (e: Exception) { + val maxAttempts = 3 + if (attempt > maxAttempts) { + Timber.e(e, "Use case binding failed after $maxAttempts attempts. Giving up.") + } else { + Timber.e(e, "Use case binding failed (attempt #$attempt). Retrying after a delay...") + delay(100) + startQRCodeAnalysis(cameraProvider, attempt + 1) } } + } - fun stopQRCodeAnalysis(previewView: PreviewView) { - // Stop analyzer - imageAnalysis.clearAnalyzer() + fun stopQRCodeAnalysis(previewView: PreviewView) { + // Stop analyzer + imageAnalysis.clearAnalyzer() - // Save last frame to display it as the 'frozen' preview - if (lastFrame == null) { - lastFrame = previewView.bitmap - Timber.d("Saving last frame for frozen preview.") - } - - // Unbind preview use case - cameraProvider?.unbindAll() + // Save last frame to display it as the 'frozen' preview + if (lastFrame == null) { + lastFrame = previewView.bitmap + Timber.d("Saving last frame for frozen preview.") } - Box(modifier.clipToBounds()) { + // Unbind preview use case + cameraProvider?.unbindAll() + } + + Box(modifier.clipToBounds()) { + if (LocalInspectionMode.current) { + Box( + modifier = modifier + .background(color = ElementTheme.colors.bgSubtlePrimary), + contentAlignment = Alignment.Center, + ) { + Text("CameraView") + } + } else { AndroidView( factory = { context -> val previewView = PreviewView(context) @@ -145,9 +145,9 @@ fun QrCodeCameraView( cameraProvider = null }, ) - lastFrame?.let { - Image(bitmap = it.asImageBitmap(), contentDescription = null) - } + } + lastFrame?.let { + Image(bitmap = it.asImageBitmap(), contentDescription = null) } } } @@ -159,7 +159,7 @@ private suspend fun Context.getCameraProvider(): ProcessCameraProvider = { continuation.resume(cameraProvider.get()) }, - ContextCompat.getMainExecutor(this) + ContextCompat.getMainExecutor(this), ) } } From 2dc8018c371c0ddc6c7ffb3f60193c7e3d648985 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 5 Dec 2025 12:53:58 +0100 Subject: [PATCH 52/64] misc(power level) : introduce RoomPermissions --- .../libraries/matrix/api/room/BaseRoom.kt | 6 + .../api/room/powerlevels/RoomPermissions.kt | 142 ++++++++++++++++++ .../matrix/impl/room/RustBaseRoom.kt | 8 + .../room/powerlevels/RustRoomPermissions.kt | 95 ++++++++++++ .../matrix/test/room/FakeBaseRoom.kt | 7 + .../room/powerlevels/FakeRoomPermissions.kt | 58 +++++++ 6 files changed, 316 insertions(+) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RustRoomPermissions.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt index 41e6ce0e62..cde3a5eff7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.draft.ComposerDraft +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility @@ -99,6 +100,11 @@ interface BaseRoom : Closeable { */ suspend fun userRole(userId: UserId): Result + /** + * Gets the permissions of the room. + */ + suspend fun roomPermissions(): Result + /** * Gets the display name of the user with the provided [userId] in the room. */ diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt new file mode 100644 index 0000000000..cdc735b819 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.powerlevels + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType + +/** + * Provides information about the permissions of users in a room. + */ +interface RoomPermissions : AutoCloseable { + fun canOwnUserBan(): Boolean + + /** + * Returns true if the current user is able to invite in the room. + */ + fun canOwnUserInvite(): Boolean + + /** + * Returns true if the current user is able to kick in the room. + */ + fun canOwnUserKick(): Boolean + + /** + * Returns true if the current user is able to pin or unpin events in the + * room. + */ + fun canOwnUserPinUnpin(): Boolean + + /** + * Returns true if the current user user is able to redact messages of + * other users in the room. + */ + fun canOwnUserRedactOther(): Boolean + + /** + * Returns true if the current user is able to redact their own messages in + * the room. + */ + fun canOwnUserRedactOwn(): Boolean + + /** + * Returns true if the current user is able to send a specific message type + * in the room. + */ + fun canOwnUserSendMessage(message: MessageEventType): Boolean + + /** + * Returns true if the current user is able to send a specific state event + * type in the room. + */ + fun canOwnUserSendState(stateEvent: StateEventType): Boolean + + /** + * Returns true if the current user is able to trigger a notification in + * the room. + */ + fun canOwnUserTriggerRoomNotification(): Boolean + + /** + * Returns true if the user with the given userId is able to ban in the + * room. + */ + fun canUserBan(userId: UserId): Boolean + + /** + * Returns true if the user with the given userId is able to invite in the + * room. + */ + fun canUserInvite(userId: UserId): Boolean + + /** + * Returns true if the user with the given userId is able to kick in the + * room. + */ + fun canUserKick(userId: UserId): Boolean + + /** + * Returns true if the user with the given userId is able to pin or unpin + * events in the room. + */ + fun canUserPinUnpin(userId: UserId): Boolean + + /** + * Returns true if the user with the given userId is able to redact + * messages of other users in the room. + */ + fun canUserRedactOther(userId: UserId): Boolean + + /** + * Returns true if the user with the given userId is able to redact + * their own messages in the room. + */ + fun canUserRedactOwn(userId: UserId): Boolean + + /** + * Returns true if the user with the given userId is able to send a + * specific message type in the room. + */ + fun canUserSendMessage(userId: UserId, message: MessageEventType): Boolean + + /** + * Returns true if the user with the given userId is able to send a + * specific state event type in the room. + */ + fun canUserSendState(userId: UserId, stateEvent: StateEventType): Boolean + + /** + * Returns true if the user with the given userId is able to trigger a + * notification in the room. + * + * The call may fail if there is an error in getting the power levels. + */ + fun canUserTriggerRoomNotification(userId: UserId): Boolean +} + +fun RoomPermissions.canEditRoomDetails(): Boolean { + return canOwnUserSendState(StateEventType.ROOM_NAME) || + canOwnUserSendState(StateEventType.ROOM_TOPIC) || + canOwnUserSendState(StateEventType.ROOM_AVATAR) +} + +fun RoomPermissions.canManageKnockRequests(): Boolean { + return canOwnUserInvite() || canOwnUserBan() || canOwnUserKick() +} + +fun RoomPermissions.canEditSecurityAndPrivacy(): Boolean { + return canOwnUserSendState(StateEventType.ROOM_JOIN_RULES) || + canOwnUserSendState(StateEventType.ROOM_HISTORY_VISIBILITY) || + canOwnUserSendState(StateEventType.ROOM_CANONICAL_ALIAS) || + canOwnUserSendState(StateEventType.ROOM_ENCRYPTION) +} + +fun RoomPermissions.canEditRolesAndPermissions(): Boolean { + return canOwnUserSendState(StateEventType.ROOM_POWER_LEVELS) +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index be7f6240ee..eec9591e32 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.draft.ComposerDraft +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility @@ -33,6 +34,7 @@ import io.element.android.libraries.matrix.impl.room.draft.into import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsValuesMapper +import io.element.android.libraries.matrix.impl.room.powerlevels.RustRoomPermissions import io.element.android.libraries.matrix.impl.room.tombstone.map import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType @@ -178,6 +180,12 @@ class RustBaseRoom( } } + override suspend fun roomPermissions(): Result = withContext(roomDispatcher) { + runCatchingExceptions { + RustRoomPermissions(innerRoom.getPowerLevels()) + } + } + override suspend fun canUserInvite(userId: UserId): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.getPowerLevels().use { it.canUserInvite(userId.value) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RustRoomPermissions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RustRoomPermissions.kt new file mode 100644 index 0000000000..57e20b166f --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RustRoomPermissions.kt @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.powerlevels + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions +import io.element.android.libraries.matrix.impl.room.map +import org.matrix.rustcomponents.sdk.RoomPowerLevels + +class RustRoomPermissions( + private val inner: RoomPowerLevels, +) : RoomPermissions { + override fun canOwnUserBan(): Boolean { + return inner.canOwnUserBan() + } + + override fun canOwnUserInvite(): Boolean { + return inner.canOwnUserInvite() + } + + override fun canOwnUserKick(): Boolean { + return inner.canOwnUserKick() + } + + override fun canOwnUserPinUnpin(): Boolean { + return inner.canOwnUserPinUnpin() + } + + override fun canOwnUserRedactOther(): Boolean { + return inner.canOwnUserRedactOther() + } + + override fun canOwnUserRedactOwn(): Boolean { + return inner.canOwnUserRedactOwn() + } + + override fun canOwnUserSendMessage(message: MessageEventType): Boolean { + return inner.canOwnUserSendMessage(message.map()) + } + + override fun canOwnUserSendState(stateEvent: StateEventType): Boolean { + return inner.canOwnUserSendState(stateEvent.map()) + } + + override fun canOwnUserTriggerRoomNotification(): Boolean { + return inner.canOwnUserTriggerRoomNotification() + } + + override fun canUserBan(userId: UserId): Boolean { + return inner.canUserBan(userId.value) + } + + override fun canUserInvite(userId: UserId): Boolean { + return inner.canUserInvite(userId.value) + } + + override fun canUserKick(userId: UserId): Boolean { + return inner.canUserKick(userId.value) + } + + override fun canUserPinUnpin(userId: UserId): Boolean { + return inner.canUserPinUnpin(userId.value) + } + + override fun canUserRedactOther(userId: UserId): Boolean { + return inner.canUserRedactOther(userId.value) + } + + override fun canUserRedactOwn(userId: UserId): Boolean { + return inner.canUserRedactOwn(userId.value) + } + + override fun canUserSendMessage(userId: UserId, message: MessageEventType): Boolean { + return inner.canUserSendMessage(userId.value, message.map()) + } + + override fun canUserSendState(userId: UserId, stateEvent: StateEventType): Boolean { + return inner.canUserSendState(userId.value, stateEvent.map()) + } + + override fun canUserTriggerRoomNotification(userId: UserId): Boolean { + return inner.canUserTriggerRoomNotification(userId.value) + } + + override fun close() { + inner.close() + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt index 56f880dc11..b05eff77e2 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt @@ -21,12 +21,14 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.draft.ComposerDraft +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.CoroutineScope @@ -48,6 +50,7 @@ class FakeBaseRoom( private val userRoleResult: () -> Result = { lambdaError() }, private val getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, private val joinRoomResult: () -> Result = { lambdaError() }, + private val roomPermissionsResult: () -> Result = { Result.success(FakeRoomPermissions()) }, private val canInviteResult: (UserId) -> Result = { lambdaError() }, private val canKickResult: (UserId) -> Result = { lambdaError() }, private val canBanResult: (UserId) -> Result = { lambdaError() }, @@ -129,6 +132,10 @@ class FakeBaseRoom( return userRoleResult() } + override suspend fun roomPermissions(): Result { + return roomPermissionsResult() + } + override suspend fun getPermalink(): Result { return roomPermalinkResult() } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt new file mode 100644 index 0000000000..04ecb1f60b --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.room.powerlevels + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +data class FakeRoomPermissions( + val ownerCanBan: Boolean = false, + val ownerCanInvite: Boolean = false, + val ownerCanKick: Boolean = false, + val ownerCanPinUnpin: Boolean = false, + val ownerCanRedactOther: Boolean = false, + val ownerCanRedactOwn: Boolean = false, + val ownerCanTriggerRoomNotification: Boolean = false, + val ownerCanSendMessage: (MessageEventType) -> Boolean = { false }, + val ownerCanSendState: (StateEventType) -> Boolean = { false }, + val userCanBan: (UserId) -> Boolean = { false }, + val userCanInvite: (UserId) -> Boolean = { false }, + val userCanKick: (UserId) -> Boolean = { false }, + val userCanPinUnpin: (UserId) -> Boolean = { false }, + val userCanRedactOther: (UserId) -> Boolean = { false }, + val userCanRedactOwn: (UserId) -> Boolean = { false }, + val userCanTriggerRoomNotification: (UserId) -> Boolean = { false }, + val userCanSendMessage: (UserId, MessageEventType) -> Boolean = { _, _ -> false }, + val userCanSendState: (UserId, StateEventType) -> Boolean = { _, _ -> false }, +) : RoomPermissions { + + override fun canOwnUserBan(): Boolean = ownerCanBan + override fun canOwnUserInvite(): Boolean = ownerCanInvite + override fun canOwnUserKick(): Boolean = ownerCanKick + override fun canOwnUserPinUnpin(): Boolean = ownerCanPinUnpin + override fun canOwnUserRedactOther(): Boolean = ownerCanRedactOther + override fun canOwnUserRedactOwn(): Boolean = ownerCanRedactOwn + override fun canOwnUserSendMessage(message: MessageEventType): Boolean = ownerCanSendMessage(message) + override fun canOwnUserSendState(stateEvent: StateEventType): Boolean = ownerCanSendState(stateEvent) + override fun canOwnUserTriggerRoomNotification(): Boolean = ownerCanTriggerRoomNotification + override fun canUserBan(userId: UserId): Boolean = userCanBan(userId) + override fun canUserInvite(userId: UserId): Boolean = userCanInvite(userId) + override fun canUserKick(userId: UserId): Boolean = userCanKick(userId) + override fun canUserPinUnpin(userId: UserId): Boolean = userCanPinUnpin(userId) + override fun canUserRedactOther(userId: UserId): Boolean = userCanRedactOther(userId) + override fun canUserRedactOwn(userId: UserId): Boolean = userCanRedactOwn(userId) + override fun canUserSendMessage(userId: UserId, message: MessageEventType): Boolean = userCanSendMessage(userId, message) + override fun canUserSendState(userId: UserId, stateEvent: StateEventType): Boolean = userCanSendState(userId, stateEvent) + override fun canUserTriggerRoomNotification(userId: UserId): Boolean = userCanTriggerRoomNotification(userId) + + override fun close() { + // no-op for the fake + } +} From ee38fb5f633a7cb7b5c9005dacdc0d627018e91f Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Dec 2025 22:23:07 +0100 Subject: [PATCH 53/64] misc(power level) : use new api --- .../api/KnockRequestPermissions.kt | 34 +++++++++ .../banner/KnockRequestsBannerPresenter.kt | 2 +- .../impl/data/KnockRequestPermissions.kt | 33 --------- .../impl/data/KnockRequestsModule.kt | 7 +- .../impl/data/KnockRequestsService.kt | 1 + .../impl/list/KnockRequestsListState.kt | 2 +- .../list/KnockRequestsListStateProvider.kt | 2 +- .../KnockRequestsBannerPresenterTest.kt | 2 +- .../list/KnockRequestsListPresenterTest.kt | 2 +- .../messages/impl/MessagesPresenter.kt | 30 ++------ .../messages/impl/UserEventPermissions.kt | 13 ++++ .../MessageComposerPresenter.kt | 5 +- .../list/PinnedMessagesListPresenter.kt | 69 ++++++++---------- .../impl/timeline/TimelinePresenter.kt | 19 +++-- .../roomcall/impl/RoomCallStatePresenter.kt | 6 +- .../roomdetails/impl/RoomDetailsPresenter.kt | 71 +++++++++---------- .../impl/members/RoomMemberListPresenter.kt | 5 +- .../api/RoomDetailsEditPermissions.kt | 37 ++++++++++ .../impl/RoomDetailsEditPresenter.kt | 21 +++--- .../impl/RoomMemberModerationPresenter.kt | 30 ++++---- .../api/SecurityAndPrivacyPermissions.kt | 24 +++---- .../impl/root/SecurityAndPrivacyPresenter.kt | 8 ++- .../impl/root/UserProfilePresenter.kt | 7 +- .../libraries/matrix/api/room/BaseRoom.kt | 51 ------------- .../api/room/powerlevels/RoomPermissions.kt | 58 ++++++++++----- .../room/powerlevels/RoomPowerLevelsValues.kt | 52 -------------- .../impl/gallery/MediaGalleryPresenter.kt | 14 ++-- .../impl/model/MediaPermissions.kt | 29 ++++++++ .../impl/viewer/MediaViewerPresenter.kt | 12 ++-- 29 files changed, 312 insertions(+), 334 deletions(-) create mode 100644 features/knockrequests/api/src/main/kotlin/io/element/android/features/knockrequests/api/KnockRequestPermissions.kt delete mode 100644 features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestPermissions.kt create mode 100644 features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt create mode 100644 libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaPermissions.kt diff --git a/features/knockrequests/api/src/main/kotlin/io/element/android/features/knockrequests/api/KnockRequestPermissions.kt b/features/knockrequests/api/src/main/kotlin/io/element/android/features/knockrequests/api/KnockRequestPermissions.kt new file mode 100644 index 0000000000..82bceb5be0 --- /dev/null +++ b/features/knockrequests/api/src/main/kotlin/io/element/android/features/knockrequests/api/KnockRequestPermissions.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.knockrequests.api + +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +data class KnockRequestPermissions( + val canAccept: Boolean, + val canDecline: Boolean, + val canBan: Boolean, +) { + val hasAny = canAccept || canDecline || canBan + + companion object { + val DEFAULT = KnockRequestPermissions( + canAccept = false, + canDecline = false, + canBan = false, + ) + } +} + +fun RoomPermissions.knockRequestPermissions(): KnockRequestPermissions { + return KnockRequestPermissions( + canAccept = canOwnUserInvite(), + canDecline = canOwnUserKick(), + canBan = canOwnUserBan(), + ) +} diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenter.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenter.kt index 641efffaa3..f340d597b1 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenter.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenter.kt @@ -49,7 +49,7 @@ class KnockRequestsBannerPresenter( val shouldShowBanner by remember { derivedStateOf { - permissions.canHandle && knockRequests.isNotEmpty() + permissions.hasAny && knockRequests.isNotEmpty() } } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestPermissions.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestPermissions.kt deleted file mode 100644 index 2ca4d4df74..0000000000 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestPermissions.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.knockrequests.impl.data - -import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.powerlevels.canBan -import io.element.android.libraries.matrix.api.room.powerlevels.canInvite -import io.element.android.libraries.matrix.api.room.powerlevels.canKick -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map - -data class KnockRequestPermissions( - val canAccept: Boolean, - val canDecline: Boolean, - val canBan: Boolean, -) { - val canHandle = canAccept || canDecline || canBan -} - -fun JoinedRoom.knockRequestPermissionsFlow(): Flow { - return syncUpdateFlow.map { - val canAccept = canInvite().getOrDefault(false) - val canDecline = canKick().getOrDefault(false) - val canBan = canBan().getOrDefault(false) - KnockRequestPermissions(canAccept, canDecline, canBan) - } -} diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt index eeba54f87d..b51b78f105 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt @@ -12,10 +12,13 @@ import dev.zacsweers.metro.BindingContainer import dev.zacsweers.metro.ContributesTo import dev.zacsweers.metro.Provides import dev.zacsweers.metro.SingleIn +import io.element.android.features.knockrequests.api.KnockRequestPermissions +import io.element.android.features.knockrequests.api.knockRequestPermissions 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.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsFlow @BindingContainer @ContributesTo(RoomScope::class) @@ -25,7 +28,9 @@ object KnockRequestsModule { fun knockRequestsService(room: JoinedRoom, featureFlagService: FeatureFlagService): KnockRequestsService { return KnockRequestsService( knockRequestsFlow = room.knockRequestsFlow, - permissionsFlow = room.knockRequestPermissionsFlow(), + permissionsFlow = room.permissionsFlow(KnockRequestPermissions.DEFAULT) { perms -> + perms.knockRequestPermissions() + }, isKnockFeatureEnabledFlow = featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock), coroutineScope = room.roomCoroutineScope ) diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt index 04c2f7b316..98570e6b28 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt @@ -8,6 +8,7 @@ package io.element.android.features.knockrequests.impl.data +import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.knock.KnockRequest diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt index a1bb90cae8..ae770a297d 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt @@ -9,7 +9,7 @@ package io.element.android.features.knockrequests.impl.list import androidx.compose.runtime.Immutable -import io.element.android.features.knockrequests.impl.data.KnockRequestPermissions +import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.impl.data.KnockRequestPresentable import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt index 2c4c92a6b6..85fc0675ad 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt @@ -9,7 +9,7 @@ package io.element.android.features.knockrequests.impl.list import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.knockrequests.impl.data.KnockRequestPermissions +import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.impl.data.KnockRequestPresentable import io.element.android.features.knockrequests.impl.data.aKnockRequestPresentable import io.element.android.libraries.architecture.AsyncAction diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt index 9eaa51cecb..3161d3e81f 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt @@ -9,7 +9,7 @@ package io.element.android.features.knockrequests.impl.banner import com.google.common.truth.Truth.assertThat -import io.element.android.features.knockrequests.impl.data.KnockRequestPermissions +import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.impl.data.KnockRequestsService import io.element.android.libraries.matrix.api.room.knock.KnockRequest import io.element.android.libraries.matrix.test.A_USER_ID diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt index b0d0b68c91..7102b01773 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt @@ -11,7 +11,7 @@ package io.element.android.features.knockrequests.impl.list import com.google.common.truth.Truth.assertThat -import io.element.android.features.knockrequests.impl.data.KnockRequestPermissions +import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.impl.data.KnockRequestsService import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData 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 a5b3106b3d..8a5f3cf423 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 @@ -12,12 +12,10 @@ import android.os.Build import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable @@ -76,14 +74,10 @@ import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.isDm -import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn -import io.element.android.libraries.matrix.api.room.powerlevels.canSendMessage +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.ui.messages.reply.map import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -170,7 +164,9 @@ class MessagesPresenter( val roomCallState = roomCallStatePresenter.present() val roomMemberModerationState = roomMemberModerationPresenter.present() - val userEventPermissions by userEventPermissions(roomInfo) + val userEventPermissions by room.permissionsAsState(UserEventPermissions.DEFAULT) { perms -> + perms.userEventPermissions() + } val roomAvatar by remember { derivedStateOf { roomInfo.avatarData() } @@ -301,24 +297,6 @@ class MessagesPresenter( ) } - @Composable - private fun userEventPermissions(roomInfo: RoomInfo): State { - val key = if (roomInfo.privilegedCreatorRole && roomInfo.creators.contains(room.sessionId)) { - Long.MAX_VALUE - } else { - roomInfo.roomPowerLevels?.hashCode() ?: 0L - } - return produceState(UserEventPermissions.DEFAULT, key1 = key) { - value = UserEventPermissions( - canSendMessage = room.canSendMessage(type = MessageEventType.RoomMessage).getOrElse { true }, - canSendReaction = room.canSendMessage(type = MessageEventType.Reaction).getOrElse { true }, - canRedactOwn = room.canRedactOwn().getOrElse { false }, - canRedactOther = room.canRedactOther().getOrElse { false }, - canPinUnpin = room.canPinUnpin().getOrElse { false }, - ) - } - } - private fun RoomInfo.avatarData(): AvatarData { return AvatarData( id = id.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt index f7d221950b..349c8e58dc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/UserEventPermissions.kt @@ -8,6 +8,9 @@ package io.element.android.features.messages.impl +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + /** * Represents the permissions a user has in a room. * It's dependent of the user's power level in the room. @@ -29,3 +32,13 @@ data class UserEventPermissions( ) } } + +fun RoomPermissions.userEventPermissions(): UserEventPermissions { + return UserEventPermissions( + canRedactOwn = canOwnUserRedactOwn(), + canRedactOther = canOwnUserRedactOther(), + canSendMessage = canOwnUserSendMessage(MessageEventType.RoomMessage), + canSendReaction = canOwnUserSendMessage(MessageEventType.Reaction), + canPinUnpin = canOwnUserPinUnpin() + ) +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index b193e97fa3..b2c5182a0a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -55,6 +55,7 @@ import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType import io.element.android.libraries.matrix.api.room.getDirectRoomMember import io.element.android.libraries.matrix.api.room.isDm +import io.element.android.libraries.matrix.api.room.powerlevels.use import io.element.android.libraries.matrix.api.timeline.TimelineException import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails @@ -396,7 +397,9 @@ class MessageComposerPresenter( val currentUserId = room.sessionId suspend fun canSendRoomMention(): Boolean { - val userCanSendAtRoom = room.canUserTriggerRoomNotification(currentUserId).getOrDefault(false) + val userCanSendAtRoom = room.roomPermissions().use(false){ perms -> + perms.canOwnUserTriggerRoomNotification() + } return !room.isDm() && userCanSendAtRoom } 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 cdc1f85f1d..b2d2caa7f9 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 @@ -10,11 +10,10 @@ package io.element.android.features.messages.impl.pinned.list import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue @@ -35,6 +34,7 @@ import io.element.android.features.messages.impl.timeline.factories.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState import io.element.android.features.messages.impl.typing.TypingNotificationState +import io.element.android.features.messages.impl.userEventPermissions import io.element.android.features.roomcall.api.aStandByCallState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter @@ -44,11 +44,9 @@ import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn +import io.element.android.libraries.matrix.api.room.isDm +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers -import io.element.android.libraries.matrix.ui.room.isDmAsState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction @@ -97,31 +95,33 @@ class PinnedMessagesListPresenter( @Composable override fun present(): PinnedMessagesListState { htmlConverterProvider.Update() - val isDm by room.isDmAsState() - - val timelineRoomInfo = remember(isDm) { - TimelineRoomInfo( - isDm = isDm, - name = room.info().name, - // We don't need to compute those values - userHasPermissionToSendMessage = false, - userHasPermissionToSendReaction = false, - // We do not care about the call state here. - roomCallState = aStandByCallState(), - // don't compute this value or the pin icon will be shown - pinnedEventIds = persistentListOf(), - typingNotificationState = TypingNotificationState( - renderTypingNotifications = false, - typingMembers = persistentListOf(), - reserveSpace = false, - ), - predecessorRoom = room.predecessorRoom(), - ) + val roomInfo by room.roomInfoFlow.collectAsState() + val timelineRoomInfo by remember { + derivedStateOf { + TimelineRoomInfo( + isDm = roomInfo.isDm, + name = roomInfo.name, + // We don't need to compute those values + userHasPermissionToSendMessage = false, + userHasPermissionToSendReaction = false, + // We do not care about the call state here. + roomCallState = aStandByCallState(), + // don't compute this value or the pin icon will be shown + pinnedEventIds = persistentListOf(), + typingNotificationState = TypingNotificationState( + renderTypingNotifications = false, + typingMembers = persistentListOf(), + reserveSpace = false, + ), + predecessorRoom = room.predecessorRoom(), + ) + } } val timelineProtectionState = timelineProtectionPresenter.present() val linkState = linkPresenter.present() - val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val userEventPermissions by userEventPermissions(syncUpdateFlow.value) + val userEventPermissions by room.permissionsAsState(UserEventPermissions.DEFAULT) { perms -> + perms.userEventPermissions() + } val displayThreadSummaries by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Threads).collectAsState(false) @@ -192,19 +192,6 @@ class PinnedMessagesListPresenter( } } - @Composable - private fun userEventPermissions(updateKey: Long): State { - return produceState(UserEventPermissions.DEFAULT, key1 = updateKey) { - value = UserEventPermissions( - canSendMessage = false, - canSendReaction = false, - canRedactOwn = room.canRedactOwn().getOrElse { false }, - canRedactOther = room.canRedactOther().getOrElse { false }, - canPinUnpin = room.canPinUnpin().getOrElse { false }, - ) - } - } - @Composable private fun PinnedMessagesListEffect(onItemsChange: (AsyncData>) -> Unit) { val updatedOnItemsChange by rememberUpdatedState(onItemsChange) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index e44cac4f27..4815602c8e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -24,6 +24,7 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import io.element.android.features.messages.impl.MessagesNavigator +import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory @@ -32,6 +33,7 @@ import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemTypingNotificationModel import io.element.android.features.messages.impl.typing.TypingNotificationState +import io.element.android.features.messages.impl.userEventPermissions import io.element.android.features.messages.impl.voicemessages.timeline.RedactedVoiceMessageManager import io.element.android.features.poll.api.actions.EndPollAction import io.element.android.features.poll.api.actions.SendPollResponseAction @@ -46,14 +48,13 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.isDm +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin -import io.element.android.libraries.matrix.ui.room.canSendMessageAsState import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.DisplayFirstTimelineItems import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.NotificationTapOpensTimeline @@ -128,11 +129,6 @@ class TimelinePresenter( val roomInfo by room.roomInfoFlow.collectAsState() - val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - - val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.RoomMessage, updateKey = syncUpdateFlow.value) - val userHasPermissionToSendReaction by room.canSendMessageAsState(type = MessageEventType.Reaction, updateKey = syncUpdateFlow.value) - val prevMostRecentItemId = rememberSaveable { mutableStateOf(null) } val newEventState = remember { mutableStateOf(NewEventState.None) } @@ -285,13 +281,16 @@ class TimelinePresenter( val typingNotificationState = typingNotificationPresenter.present() val roomCallState = roomCallStatePresenter.present() + val userEventPermissions by room.permissionsAsState(UserEventPermissions.DEFAULT) { perms -> + perms.userEventPermissions() + } val timelineRoomInfo by remember(typingNotificationState, roomCallState, roomInfo) { derivedStateOf { TimelineRoomInfo( name = roomInfo.name, - isDm = roomInfo.isDm.orFalse(), - userHasPermissionToSendMessage = userHasPermissionToSendMessage, - userHasPermissionToSendReaction = userHasPermissionToSendReaction, + isDm = roomInfo.isDm, + userHasPermissionToSendMessage = userEventPermissions.canSendMessage, + userHasPermissionToSendReaction = userEventPermissions.canSendReaction, roomCallState = roomCallState, pinnedEventIds = roomInfo.pinnedEventIds, typingNotificationState = typingNotificationState, diff --git a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt index 5de47f9ff2..b18a2772a3 100644 --- a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt +++ b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt @@ -21,7 +21,8 @@ import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.roomcall.api.RoomCallState import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.ui.room.canCall +import io.element.android.libraries.matrix.api.room.powerlevels.canCall +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState @Inject class RoomCallStatePresenter( @@ -35,8 +36,7 @@ class RoomCallStatePresenter( value = sessionEnterpriseService.isElementCallAvailable() } val roomInfo by room.roomInfoFlow.collectAsState() - val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val canJoinCall by room.canCall(updateKey = syncUpdateFlow.value) + val canJoinCall by room.permissionsAsState(false) { perms -> perms.canCall() } val isUserInTheCall by remember { derivedStateOf { room.sessionId in roomInfo.activeRoomCallParticipants diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 95c4f1e9e2..83840ad604 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -10,6 +10,7 @@ package io.element.android.features.roomdetails.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -18,11 +19,14 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import dev.zacsweers.metro.Inject import im.vector.app.features.analytics.plan.Interaction +import io.element.android.features.knockrequests.api.knockRequestPermissions import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter -import io.element.android.features.securityandprivacy.api.securityAndPrivacyPermissionsAsState +import io.element.android.features.roomdetailsedit.api.RoomDetailsEditPermissions +import io.element.android.features.roomdetailsedit.api.roomDetailsEditPermissions +import io.element.android.features.securityandprivacy.api.securityAndPrivacyPermissions import io.element.android.libraries.androidutils.clipboard.ClipboardHelper import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -36,17 +40,13 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.RoomMembersState -import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.join.JoinRule -import io.element.android.libraries.matrix.api.room.powerlevels.canInvite -import io.element.android.libraries.matrix.api.room.powerlevels.canSendState +import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomNotificationSettings -import io.element.android.libraries.matrix.ui.room.canHandleKnockRequestsAsState import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember import io.element.android.libraries.matrix.ui.room.getDirectRoomMember -import io.element.android.libraries.matrix.ui.room.isDmAsState -import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.ui.strings.CommonStrings @@ -77,8 +77,6 @@ class RoomDetailsPresenter( val scope = rememberCoroutineScope() val leaveRoomState = leaveRoomPresenter.present() val roomInfo by room.roomInfoFlow.collectAsState() - val isUserAdmin = room.isOwnUserAdmin() - val syncUpdateFlow = room.syncUpdateFlow.collectAsState() val roomAvatar by remember { derivedStateOf { roomInfo.avatarUrl } } val roomName by remember { derivedStateOf { roomInfo.name?.trim().orEmpty() } } @@ -93,15 +91,11 @@ class RoomDetailsPresenter( observeNotificationSettings() } + val isDm = roomInfo.isDm val membersState by room.membersStateFlow.collectAsState() - val canInvite by getCanInvite(membersState) - + val permissions by getPermissions() val canonicalAlias by remember { derivedStateOf { roomInfo.canonicalAlias } } val isEncrypted by remember { derivedStateOf { roomInfo.isEncrypted == true } } - val isDm by room.isDmAsState() - val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME) - val canEditAvatar by getCanSendState(membersState, StateEventType.ROOM_AVATAR) - val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC) val dmMember by room.getDirectRoomMember(membersState) val currentMember by room.getCurrentRoomMember(membersState) val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember) @@ -109,16 +103,15 @@ class RoomDetailsPresenter( val roomCallState = roomCallStatePresenter.present() val joinedMemberCount by remember { derivedStateOf { roomInfo.joinedMembersCount } } - val topicState = remember(canEditTopic, roomTopic, roomType) { + val topicState = remember(permissions.editDetailsPermissions.canEditTopic, roomTopic, roomType) { val topic = roomTopic when { !topic.isNullOrBlank() -> RoomTopicState.ExistingTopic(topic) - canEditTopic && roomType is RoomDetailsType.Room -> RoomTopicState.CanAddTopic + permissions.editDetailsPermissions.canEditTopic && roomType is RoomDetailsType.Room -> RoomTopicState.CanAddTopic else -> RoomTopicState.Hidden } } - val canHandleKnockRequests by room.canHandleKnockRequestsAsState(syncUpdateFlow.value) val isKnockRequestsEnabled by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock) }.collectAsState(false) @@ -126,7 +119,7 @@ class RoomDetailsPresenter( room.knockRequestsFlow.collect { value = it.size } } val canShowKnockRequests by remember { - derivedStateOf { isKnockRequestsEnabled && canHandleKnockRequests && joinRule == JoinRule.Knock } + derivedStateOf { isKnockRequestsEnabled && permissions.canManageKnockRequests && joinRule == JoinRule.Knock } } val isDeveloperModeEnabled by remember { appPreferencesStore.isDeveloperModeEnabledFlow() @@ -162,13 +155,6 @@ class RoomDetailsPresenter( val roomMemberDetailsState = roomMemberDetailsPresenter?.present() - val securityAndPrivacyPermissions = room.securityAndPrivacyPermissionsAsState(syncUpdateFlow.value) - val canShowSecurityAndPrivacy by remember { - derivedStateOf { - roomType is RoomDetailsType.Room && securityAndPrivacyPermissions.value.hasAny - } - } - val hasMemberVerificationViolations by produceState(false) { room.roomMemberIdentityStateChange(waitForEncryption = true) .onEach { identities -> value = identities.any { it.identityState == IdentityState.VerificationViolation } } @@ -185,22 +171,22 @@ class RoomDetailsPresenter( roomTopic = topicState, memberCount = joinedMemberCount, isEncrypted = isEncrypted, - canInvite = canInvite, - canEdit = (canEditAvatar || canEditName || canEditTopic) && roomType == RoomDetailsType.Room, + canInvite = permissions.canInvite, + canEdit = roomType == RoomDetailsType.Room && permissions.editDetailsPermissions.hasAny, roomCallState = roomCallState, roomType = roomType, roomMemberDetailsState = roomMemberDetailsState, leaveRoomState = leaveRoomState, roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), isFavorite = isFavorite, - displayRolesAndPermissionsSettings = !isDm && isUserAdmin, + displayRolesAndPermissionsSettings = !isDm && permissions.canEditRolesAndPermissions, isPublic = joinRule == JoinRule.Public, heroes = roomInfo.heroes.toImmutableList(), pinnedMessagesCount = pinnedMessagesCount, snackbarMessage = snackbarMessage, canShowKnockRequests = canShowKnockRequests, knockRequestsCount = knockRequestsCount, - canShowSecurityAndPrivacy = canShowSecurityAndPrivacy, + canShowSecurityAndPrivacy = !isDm && permissions.canEditSecurityAndPrivacy, hasMemberVerificationViolations = hasMemberVerificationViolations, canReportRoom = canReportRoom, isTombstoned = roomInfo.successorRoom != null, @@ -232,14 +218,25 @@ class RoomDetailsPresenter( } } - @Composable - private fun getCanInvite(membersState: RoomMembersState) = produceState(false, membersState) { - value = room.canInvite().getOrElse { false } - } + private data class Permissions( + val canInvite: Boolean = false, + val editDetailsPermissions: RoomDetailsEditPermissions = RoomDetailsEditPermissions.DEFAULT, + val canManageKnockRequests: Boolean = false, + val canEditRolesAndPermissions: Boolean = false, + val canEditSecurityAndPrivacy: Boolean = false, + ) @Composable - private fun getCanSendState(membersState: RoomMembersState, type: StateEventType) = produceState(false, membersState) { - value = room.canSendState(type).getOrElse { false } + private fun getPermissions(): State { + return room.permissionsAsState(Permissions()) { perms -> + Permissions( + canInvite = perms.canOwnUserInvite(), + editDetailsPermissions = perms.roomDetailsEditPermissions(), + canManageKnockRequests = perms.knockRequestPermissions().hasAny, + canEditRolesAndPermissions = perms.canEditRolesAndPermissions(), + canEditSecurityAndPrivacy = perms.securityAndPrivacyPermissions().hasAny, + ) + } } private fun CoroutineScope.observeNotificationSettings() { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt index f1d3f61f7e..6917057a06 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt @@ -32,10 +32,10 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.room.toMatrixUser import io.element.android.libraries.matrix.ui.room.PowerLevelRoomMemberComparator -import io.element.android.libraries.matrix.ui.room.canInviteAsState import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentMapOf @@ -58,8 +58,7 @@ class RoomMemberListPresenter( override fun present(): RoomMemberListState { var searchQuery by rememberSaveable { mutableStateOf("") } val membersState by room.membersStateFlow.collectAsState() - val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val canInvite by room.canInviteAsState(syncUpdateFlow.value) + val canInvite by room.permissionsAsState(false) { perms -> perms.canOwnUserInvite() } val roomModerationState = roomMembersModerationPresenter.present() val roomMemberIdentityStates by produceState(persistentMapOf()) { diff --git a/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt b/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt new file mode 100644 index 0000000000..f95f4466f2 --- /dev/null +++ b/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdetailsedit.api + +import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +data class RoomDetailsEditPermissions( + val canEditName: Boolean, + val canEditTopic: Boolean, + val canEditAvatar: Boolean, +){ + val hasAny = canEditName || + canEditTopic || + canEditAvatar + + companion object { + val DEFAULT = RoomDetailsEditPermissions( + canEditName = false, + canEditTopic = false, + canEditAvatar = false, + ) + } +} + +fun RoomPermissions.roomDetailsEditPermissions(): RoomDetailsEditPermissions { + return RoomDetailsEditPermissions( + canEditName = canOwnUserSendState(StateEventType.ROOM_NAME), + canEditTopic = canOwnUserSendState(StateEventType.ROOM_TOPIC), + canEditAvatar = canOwnUserSendState(StateEventType.ROOM_AVATAR), + ) +} diff --git a/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt b/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt index 5e685ff81f..ed729928d8 100644 --- a/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt +++ b/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt @@ -23,6 +23,8 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.core.net.toUri import dev.zacsweers.metro.Inject +import io.element.android.features.roomdetailsedit.api.RoomDetailsEditPermissions +import io.element.android.features.roomdetailsedit.api.roomDetailsEditPermissions import io.element.android.libraries.androidutils.file.TemporaryUriDeleter import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter @@ -30,8 +32,7 @@ import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.StateEventType -import io.element.android.libraries.matrix.api.room.powerlevels.canSendState +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider @@ -93,14 +94,8 @@ class RoomDetailsEditPresenter( } } - var canChangeName by remember { mutableStateOf(false) } - var canChangeTopic by remember { mutableStateOf(false) } - var canChangeAvatar by remember { mutableStateOf(false) } - - LaunchedEffect(roomSyncUpdateFlow.value) { - canChangeName = room.canSendState(StateEventType.ROOM_NAME).getOrElse { false } - canChangeTopic = room.canSendState(StateEventType.ROOM_TOPIC).getOrElse { false } - canChangeAvatar = room.canSendState(StateEventType.ROOM_AVATAR).getOrElse { false } + val permissions by room.permissionsAsState(RoomDetailsEditPermissions.DEFAULT){perms -> + perms.roomDetailsEditPermissions() } val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( @@ -181,11 +176,11 @@ class RoomDetailsEditPresenter( return RoomDetailsEditState( roomId = room.roomId, roomRawName = roomRawNameEdited, - canChangeName = canChangeName, + canChangeName = permissions.canEditName, roomTopic = roomTopicEdited, - canChangeTopic = canChangeTopic, + canChangeTopic = permissions.canEditTopic, roomAvatarUrl = roomAvatarUriEdited, - canChangeAvatar = canChangeAvatar, + canChangeAvatar = permissions.canEditAvatar, avatarActions = avatarActions, saveButtonEnabled = saveButtonEnabled, saveAction = saveAction.value, diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt index 31ff2da2b2..96749ba5ac 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt @@ -30,10 +30,9 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.ui.room.canBanAsState -import io.element.android.libraries.matrix.ui.room.canKickAsState import io.element.android.libraries.matrix.ui.room.userPowerLevelAsState import io.element.android.services.analytics.api.AnalyticsService import kotlinx.collections.immutable.ImmutableList @@ -56,8 +55,12 @@ class RoomMemberModerationPresenter( override fun present(): RoomMemberModerationState { val coroutineScope = rememberCoroutineScope() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val canBan = room.canBanAsState(syncUpdateFlow.value) - val canKick = room.canKickAsState(syncUpdateFlow.value) + val permissions by room.permissionsAsState(Permissions()) { perms -> + Permissions( + canKick = perms.canOwnUserKick(), + canBan = perms.canOwnUserBan(), + ) + } val currentUserMemberPowerLevel = room.userPowerLevelAsState(syncUpdateFlow.value) val kickUserAsyncAction = @@ -80,8 +83,7 @@ class RoomMemberModerationPresenter( } moderationActions.value = computeModerationActions( member = member, - canKick = canKick.value, - canBan = canBan.value, + permissions = permissions, currentUserMemberPowerLevel = currentUserMemberPowerLevel.value, ) } @@ -134,8 +136,8 @@ class RoomMemberModerationPresenter( } return InternalRoomMemberModerationState( - canKick = canKick.value, - canBan = canBan.value, + canKick = permissions.canKick, + canBan = permissions.canBan, selectedUser = selectedUser, actions = moderationActions.value, kickUserAsyncAction = kickUserAsyncAction.value, @@ -147,8 +149,7 @@ class RoomMemberModerationPresenter( private fun computeModerationActions( member: RoomMember?, - canKick: Boolean, - canBan: Boolean, + permissions: Permissions, currentUserMemberPowerLevel: Long, ): ImmutableList { return buildList { @@ -158,11 +159,11 @@ class RoomMemberModerationPresenter( val canModerateThisUser = currentUserMemberPowerLevel > targetMemberPowerLevel // Assume the member is joined when it's unknown val membership = member?.membership ?: RoomMembershipState.JOIN - if (canKick) { + if (permissions.canKick) { val isKickEnabled = canModerateThisUser && membership.isActive() add(ModerationActionState(action = ModerationAction.KickUser, isEnabled = isKickEnabled)) } - if (canBan) { + if (permissions.canBan) { if (membership == RoomMembershipState.BAN) { add(ModerationActionState(action = ModerationAction.UnbanUser, isEnabled = canModerateThisUser)) } else { @@ -208,6 +209,11 @@ class RoomMemberModerationPresenter( ) } + private data class Permissions( + val canKick: Boolean = false, + val canBan: Boolean = false, + ) + private fun CoroutineScope.runActionAndWaitForMembershipChange( action: MutableState>, block: suspend () -> Result diff --git a/features/securityandprivacy/api/src/main/kotlin/io/element/android/features/securityandprivacy/api/SecurityAndPrivacyPermissions.kt b/features/securityandprivacy/api/src/main/kotlin/io/element/android/features/securityandprivacy/api/SecurityAndPrivacyPermissions.kt index 82ab30581e..bacd863ca6 100644 --- a/features/securityandprivacy/api/src/main/kotlin/io/element/android/features/securityandprivacy/api/SecurityAndPrivacyPermissions.kt +++ b/features/securityandprivacy/api/src/main/kotlin/io/element/android/features/securityandprivacy/api/SecurityAndPrivacyPermissions.kt @@ -8,13 +8,8 @@ package io.element.android.features.securityandprivacy.api -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.produceState -import io.element.android.features.securityandprivacy.api.SecurityAndPrivacyPermissions.Companion.DEFAULT -import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.StateEventType -import io.element.android.libraries.matrix.api.room.powerlevels.canSendState +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions data class SecurityAndPrivacyPermissions( val canChangeRoomAccess: Boolean, @@ -37,14 +32,11 @@ data class SecurityAndPrivacyPermissions( } } -@Composable -fun BaseRoom.securityAndPrivacyPermissionsAsState(updateKey: Long): State { - return produceState(DEFAULT, key1 = updateKey) { - value = SecurityAndPrivacyPermissions( - canChangeRoomAccess = canSendState(type = StateEventType.ROOM_JOIN_RULES).getOrElse { false }, - canChangeHistoryVisibility = canSendState(type = StateEventType.ROOM_HISTORY_VISIBILITY).getOrElse { false }, - canChangeEncryption = canSendState(type = StateEventType.ROOM_ENCRYPTION).getOrElse { false }, - canChangeRoomVisibility = canSendState(type = StateEventType.ROOM_CANONICAL_ALIAS).getOrElse { false }, - ) - } +fun RoomPermissions.securityAndPrivacyPermissions(): SecurityAndPrivacyPermissions { + return SecurityAndPrivacyPermissions( + canChangeRoomAccess = canOwnUserSendState(StateEventType.ROOM_JOIN_RULES), + canChangeHistoryVisibility = canOwnUserSendState(StateEventType.ROOM_HISTORY_VISIBILITY), + canChangeEncryption = canOwnUserSendState(StateEventType.ROOM_ENCRYPTION), + canChangeRoomVisibility = canOwnUserSendState(StateEventType.ROOM_CANONICAL_ALIAS), + ) } diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt index b77ad0e7d6..af0f44be38 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt @@ -21,7 +21,8 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject -import io.element.android.features.securityandprivacy.api.securityAndPrivacyPermissionsAsState +import io.element.android.features.securityandprivacy.api.SecurityAndPrivacyPermissions +import io.element.android.features.securityandprivacy.api.securityAndPrivacyPermissions import io.element.android.features.securityandprivacy.impl.SecurityAndPrivacyNavigator import io.element.android.features.securityandprivacy.impl.editroomaddress.matchesServer import io.element.android.libraries.architecture.AsyncAction @@ -37,6 +38,7 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async @@ -106,7 +108,9 @@ class SecurityAndPrivacyPresenter( ) var showEnableEncryptionConfirmation by remember(savedSettings.isEncrypted) { mutableStateOf(false) } - val permissions by room.securityAndPrivacyPermissionsAsState(syncUpdateFlow.value) + val permissions by room.permissionsAsState(SecurityAndPrivacyPermissions.DEFAULT) { perms -> + perms.securityAndPrivacyPermissions() + } fun handleEvent(event: SecurityAndPrivacyEvent) { when (event) { diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt index 9bf31e0b07..8b7eddca54 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt @@ -34,6 +34,8 @@ import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.matrix.api.MatrixClient 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.room.powerlevels.canCall +import io.element.android.libraries.matrix.api.room.powerlevels.use import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.distinctUntilChanged @@ -56,7 +58,7 @@ class UserProfilePresenter( @Composable private fun getDmRoomId(): State { - return produceState(initialValue = null) { + return produceState(initialValue = null) { value = client.findDM(userId).getOrNull() } } @@ -66,7 +68,6 @@ class UserProfilePresenter( val isElementCallAvailable by produceState(initialValue = false, roomId) { value = sessionEnterpriseService.isElementCallAvailable() } - return produceState(initialValue = false, isElementCallAvailable, roomId) { value = when { isElementCallAvailable.not() -> false @@ -75,7 +76,7 @@ class UserProfilePresenter( roomId ?.let { client.getRoom(it) } ?.use { room -> - room.canUserJoinCall(client.sessionId).getOrNull() + room.roomPermissions().use(false){ perms -> perms.canCall()} } .orFalse() } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt index cde3a5eff7..481171ace0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt @@ -130,57 +130,6 @@ interface BaseRoom : Closeable { */ suspend fun forget(): Result - /** - * Returns `true` if the user with the provided [userId] can invite other users to the room. - */ - suspend fun canUserInvite(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can kick other users from the room. - */ - suspend fun canUserKick(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can ban other users from the room. - */ - suspend fun canUserBan(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can redact their own messages. - */ - suspend fun canUserRedactOwn(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can redact messages from other users. - */ - suspend fun canUserRedactOther(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can send state events. - */ - suspend fun canUserSendState(userId: UserId, type: StateEventType): Result - - /** - * Returns `true` if the user with the provided [userId] can send messages. - */ - suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result - - /** - * Returns `true` if the user with the provided [userId] can trigger an `@room` notification. - */ - suspend fun canUserTriggerRoomNotification(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can pin or unpin messages. - */ - suspend fun canUserPinUnpin(userId: UserId): Result - - /** - * Returns `true` if the user with the provided [userId] can join or starts calls. - */ - suspend fun canUserJoinCall(userId: UserId): Result = - canUserSendState(userId, StateEventType.CALL_MEMBER) - /** * Sets the room as favorite or not, based on the [isFavorite] parameter. */ diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt index cdc735b819..735627e10e 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt @@ -7,9 +7,18 @@ package io.element.android.libraries.matrix.api.room.powerlevels +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.remember import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import timber.log.Timber /** * Provides information about the permissions of users in a room. @@ -120,23 +129,38 @@ interface RoomPermissions : AutoCloseable { fun canUserTriggerRoomNotification(userId: UserId): Boolean } -fun RoomPermissions.canEditRoomDetails(): Boolean { - return canOwnUserSendState(StateEventType.ROOM_NAME) || - canOwnUserSendState(StateEventType.ROOM_TOPIC) || - canOwnUserSendState(StateEventType.ROOM_AVATAR) -} - -fun RoomPermissions.canManageKnockRequests(): Boolean { - return canOwnUserInvite() || canOwnUserBan() || canOwnUserKick() -} - -fun RoomPermissions.canEditSecurityAndPrivacy(): Boolean { - return canOwnUserSendState(StateEventType.ROOM_JOIN_RULES) || - canOwnUserSendState(StateEventType.ROOM_HISTORY_VISIBILITY) || - canOwnUserSendState(StateEventType.ROOM_CANONICAL_ALIAS) || - canOwnUserSendState(StateEventType.ROOM_ENCRYPTION) -} - fun RoomPermissions.canEditRolesAndPermissions(): Boolean { return canOwnUserSendState(StateEventType.ROOM_POWER_LEVELS) } + +fun RoomPermissions.canCall(): Boolean { + return canOwnUserSendState(StateEventType.CALL_MEMBER) +} + +fun Result.use(default: T, block: (RoomPermissions) -> T): T { + return fold( + onSuccess = { perms -> + perms.use(block) + }, + onFailure = { + default + } + ) +} + +fun BaseRoom.permissionsFlow(default: T, block: (RoomPermissions) -> T): Flow { + return roomInfoFlow + .map { info -> info.roomPowerLevels } + .distinctUntilChanged() + .map { + roomPermissions().use(default, block) + } +} + +@Composable +fun BaseRoom.permissionsAsState(default: T, block: (RoomPermissions) -> T): State { + return remember(this, default, block) { + Timber.d("Computing permissionsAsState for room $roomId with default=$default") + permissionsFlow(default, block) + }.collectAsState(default) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt index d20b6141eb..a7eebbb99c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt @@ -8,11 +8,6 @@ package io.element.android.libraries.matrix.api.room.powerlevels -import io.element.android.libraries.core.extensions.runCatchingExceptions -import io.element.android.libraries.matrix.api.room.BaseRoom -import io.element.android.libraries.matrix.api.room.MessageEventType -import io.element.android.libraries.matrix.api.room.StateEventType - data class RoomPowerLevelsValues( val ban: Long, val invite: Long, @@ -24,50 +19,3 @@ data class RoomPowerLevelsValues( val roomTopic: Long, val spaceChild: Long, ) - -/** - * Shortcut for calling [BaseRoom.canUserInvite] with our own user. - */ -suspend fun BaseRoom.canInvite(): Result = canUserInvite(sessionId) - -/** - * Shortcut for calling [BaseRoom.canUserKick] with our own user. - */ -suspend fun BaseRoom.canKick(): Result = canUserKick(sessionId) - -/** - * Shortcut for calling [BaseRoom.canUserBan] with our own user. - */ -suspend fun BaseRoom.canBan(): Result = canUserBan(sessionId) - -/** - * Shortcut for calling [BaseRoom.canUserSendState] with our own user. - */ -suspend fun BaseRoom.canSendState(type: StateEventType): Result = canUserSendState(sessionId, type) - -/** - * Shortcut for calling [BaseRoom.canUserSendMessage] with our own user. - */ -suspend fun BaseRoom.canSendMessage(type: MessageEventType): Result = canUserSendMessage(sessionId, type) - -/** - * Shortcut for calling [BaseRoom.canUserRedactOwn] with our own user. - */ -suspend fun BaseRoom.canRedactOwn(): Result = canUserRedactOwn(sessionId) - -/** - * Shortcut for calling [BaseRoom.canRedactOther] with our own user. - */ -suspend fun BaseRoom.canRedactOther(): Result = canUserRedactOther(sessionId) - -/** - * Shortcut for checking if current user can handle knock requests. - */ -suspend fun BaseRoom.canHandleKnockRequests(): Result = runCatchingExceptions { - canInvite().getOrThrow() || canBan().getOrThrow() || canKick().getOrThrow() -} - -/** - * Shortcut for calling [BaseRoom.canUserPinUnpin] with our own user. - */ -suspend fun BaseRoom.canPinUnpin(): Result = canUserPinUnpin(sessionId) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index aee9af82b7..e5e493ee63 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -30,8 +30,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarM import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.room.BaseRoom -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryDataSource @@ -39,8 +38,10 @@ import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetSta import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems import io.element.android.libraries.mediaviewer.impl.model.MediaItem +import io.element.android.libraries.mediaviewer.impl.model.MediaPermissions import io.element.android.libraries.mediaviewer.impl.model.eventId import io.element.android.libraries.mediaviewer.impl.model.mediaInfo +import io.element.android.libraries.mediaviewer.impl.model.mediaPermissions import io.element.android.libraries.mediaviewer.impl.model.mediaSource import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.coroutines.launch @@ -80,6 +81,10 @@ class MediaGalleryPresenter( mediaGalleryDataSource.start() } + val permissions by room.permissionsAsState(MediaPermissions.DEFAULT) { perms -> + perms.mediaPermissions() + } + val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() localMediaActions.Configure() @@ -119,8 +124,8 @@ class MediaGalleryPresenter( eventId = event.mediaItem.eventId(), canDelete = when (event.mediaItem.mediaInfo().senderId) { null -> false - room.sessionId -> room.canRedactOwn().getOrElse { false } && event.mediaItem.eventId() != null - else -> room.canRedactOther().getOrElse { false } && event.mediaItem.eventId() != null + room.sessionId -> permissions.canRedactOwn && event.mediaItem.eventId() != null + else -> permissions.canRedactOther && event.mediaItem.eventId() != null }, mediaInfo = event.mediaItem.mediaInfo(), thumbnailSource = when (event.mediaItem) { @@ -202,6 +207,7 @@ class MediaGalleryPresenter( CommonStrings.error_unknown } } + } private fun GroupedMediaItems?.find(eventId: EventId?): MediaItem.Event? { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaPermissions.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaPermissions.kt new file mode 100644 index 0000000000..4a111965e9 --- /dev/null +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaPermissions.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl.model + +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +data class MediaPermissions( + val canRedactOwn: Boolean, + val canRedactOther: Boolean, +) { + companion object { + val DEFAULT = MediaPermissions( + canRedactOwn = false, + canRedactOther = false, + ) + } +} + +fun RoomPermissions.mediaPermissions(): MediaPermissions { + return MediaPermissions( + canRedactOwn = canOwnUserRedactOwn(), + canRedactOther = canOwnUserRedactOther(), + ) +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt index 4709a4ec51..dc0feb70cf 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt @@ -32,8 +32,7 @@ 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.core.EventId import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint @@ -41,6 +40,8 @@ import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions +import io.element.android.libraries.mediaviewer.impl.model.MediaPermissions +import io.element.android.libraries.mediaviewer.impl.model.mediaPermissions import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope @@ -81,6 +82,9 @@ class MediaViewerPresenter( NoMoreItemsBackwardSnackBarDisplayer(currentIndex, data) NoMoreItemsForwardSnackBarDisplayer(currentIndex, data) + val permissions by room.permissionsAsState(MediaPermissions.DEFAULT) { perms -> + perms.mediaPermissions() + } var mediaBottomSheetState by remember { mutableStateOf(MediaBottomSheetState.Hidden) } DisposableEffect(Unit) { @@ -131,8 +135,8 @@ class MediaViewerPresenter( eventId = event.data.eventId, canDelete = when (event.data.mediaInfo.senderId) { null -> false - room.sessionId -> room.canRedactOwn().getOrElse { false } && event.data.eventId != null - else -> room.canRedactOther().getOrElse { false } && event.data.eventId != null + room.sessionId -> permissions.canRedactOwn && event.data.eventId != null + else -> permissions.canRedactOther && event.data.eventId != null }, mediaInfo = event.data.mediaInfo, thumbnailSource = event.data.thumbnailSource, From 29c1f33638b53b484d0cf2cae29924c8a13c0ba3 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Dec 2025 22:23:17 +0100 Subject: [PATCH 54/64] misc(power level) : remove old api --- .../matrix/impl/room/RustBaseRoom.kt | 54 ------------- .../matrix/ui/room/MatrixRoomState.kt | 79 ------------------- 2 files changed, 133 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index eec9591e32..141957d1ed 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -186,60 +186,6 @@ class RustBaseRoom( } } - override suspend fun canUserInvite(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserInvite(userId.value) } - } - } - - override suspend fun canUserKick(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserKick(userId.value) } - } - } - - override suspend fun canUserBan(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserBan(userId.value) } - } - } - - override suspend fun canUserRedactOwn(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserRedactOwn(userId.value) } - } - } - - override suspend fun canUserRedactOther(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserRedactOther(userId.value) } - } - } - - override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserSendState(userId.value, type.map()) } - } - } - - override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserSendMessage(userId.value, type.map()) } - } - } - - override suspend fun canUserTriggerRoomNotification(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserTriggerRoomNotification(userId.value) } - } - } - - override suspend fun canUserPinUnpin(userId: UserId): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.getPowerLevels().use { it.canUserPinUnpin(userId.value) } - } - } - override suspend fun clearEventCacheStorage(): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.clearEventCacheStorage() diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt index 03e0e5bea1..d4e6127b69 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt @@ -14,88 +14,9 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import io.element.android.libraries.matrix.api.room.BaseRoom -import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.isDm -import io.element.android.libraries.matrix.api.room.powerlevels.canBan -import io.element.android.libraries.matrix.api.room.powerlevels.canHandleKnockRequests -import io.element.android.libraries.matrix.api.room.powerlevels.canInvite -import io.element.android.libraries.matrix.api.room.powerlevels.canKick -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther -import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn -import io.element.android.libraries.matrix.api.room.powerlevels.canSendMessage import io.element.android.libraries.matrix.ui.model.roleOf -@Composable -fun BaseRoom.canSendMessageAsState(type: MessageEventType, updateKey: Long): State { - return produceState(initialValue = true, key1 = updateKey) { - value = canSendMessage(type).getOrElse { true } - } -} - -@Composable -fun BaseRoom.canInviteAsState(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canInvite().getOrElse { false } - } -} - -@Composable -fun BaseRoom.canRedactOwnAsState(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canRedactOwn().getOrElse { false } - } -} - -@Composable -fun BaseRoom.canRedactOtherAsState(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canRedactOther().getOrElse { false } - } -} - -@Composable -fun BaseRoom.canCall(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canUserJoinCall(sessionId).getOrElse { false } - } -} - -@Composable -fun BaseRoom.canPinUnpin(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canUserPinUnpin(sessionId).getOrElse { false } - } -} - -@Composable -fun BaseRoom.isDmAsState(): State { - return produceState(initialValue = false) { - roomInfoFlow.collect { value = it.isDm } - } -} - -@Composable -fun BaseRoom.canKickAsState(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canKick().getOrElse { false } - } -} - -@Composable -fun BaseRoom.canBanAsState(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canBan().getOrElse { false } - } -} - -@Composable -fun BaseRoom.canHandleKnockRequestsAsState(updateKey: Long): State { - return produceState(initialValue = false, key1 = updateKey) { - value = canHandleKnockRequests().getOrElse { false } - } -} - @Composable fun BaseRoom.userPowerLevelAsState(updateKey: Long): State { return produceState(initialValue = 0, key1 = updateKey) { From 5c8fd831e31a27fda1a104cf2077c8cc69bbfef0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 9 Dec 2025 20:50:31 +0100 Subject: [PATCH 55/64] misc(power level) : update tests following api change --- .../MessageComposerPresenter.kt | 3 +- .../impl/timeline/TimelinePresenter.kt | 2 +- .../messages/impl/MessagesPresenterTest.kt | 196 +++++--------- .../MessageComposerPresenterTest.kt | 45 +++- .../list/PinnedMessagesListPresenterTest.kt | 43 ++- .../impl/timeline/TimelinePresenterTest.kt | 151 +++++------ .../impl/RoomCallStatePresenterTest.kt | 28 +- .../roomdetails/impl/MatrixRoomFixture.kt | 27 +- .../impl/RoomDetailsPresenterTest.kt | 246 ++++++------------ .../members/RoomMemberListPresenterTest.kt | 23 +- .../api/RoomDetailsEditPermissions.kt | 2 +- .../impl/RoomDetailsEditPresenter.kt | 3 +- .../impl/RoomDetailsEditPresenterTest.kt | 65 ++--- .../impl/RoomMemberModerationPresenterTest.kt | 7 +- .../impl/root/SecurityAndPrivacyPresenter.kt | 1 - .../impl/SecurityAndPrivacyPresenterTest.kt | 39 ++- .../impl/root/UserProfilePresenter.kt | 2 +- .../impl/UserProfilePresenterTest.kt | 24 +- .../api/room/powerlevels/RoomPermissions.kt | 12 +- .../matrix/impl/room/RustBaseRoom.kt | 2 - .../matrix/test/room/FakeBaseRoom.kt | 56 +--- .../room/powerlevels/FakeRoomPermissions.kt | 72 ++--- .../impl/gallery/MediaGalleryPresenter.kt | 1 - .../impl/gallery/MediaGalleryPresenterTest.kt | 17 +- .../impl/viewer/MediaViewerPresenterTest.kt | 45 +++- 25 files changed, 475 insertions(+), 637 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index b2c5182a0a..fd803109c7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -99,6 +99,7 @@ import timber.log.Timber import kotlin.time.Duration.Companion.seconds import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes +@Suppress("LargeClass") @AssistedInject class MessageComposerPresenter( @Assisted private val navigator: MessagesNavigator, @@ -397,7 +398,7 @@ class MessageComposerPresenter( val currentUserId = room.sessionId suspend fun canSendRoomMention(): Boolean { - val userCanSendAtRoom = room.roomPermissions().use(false){ perms -> + val userCanSendAtRoom = room.roomPermissions().use(false) { perms -> perms.canOwnUserTriggerRoomNotification() } return !room.isDm() && userCanSendAtRoom diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index 4815602c8e..289ec2924d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -39,7 +39,6 @@ import io.element.android.features.poll.api.actions.EndPollAction import io.element.android.features.poll.api.actions.SendPollResponseAction import io.element.android.features.roomcall.api.RoomCallState import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.featureflag.api.FeatureFlagService @@ -96,6 +95,7 @@ class TimelinePresenter( private val analyticsService: AnalyticsService, ) : Presenter { private val tag = "TimelinePresenter" + @AssistedFactory interface Factory { fun create( 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 de2c8a81c9..cd5bcf8a6d 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 @@ -64,6 +64,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo @@ -86,6 +87,7 @@ import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.aTimelineItemDebugInfo import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails @@ -143,11 +145,7 @@ class MessagesPresenterTest { fun `present - check that the room's unread flag is removed`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), markAsReadResult = { lambdaError() } ), typingNoticeResult = { Result.success(Unit) }, @@ -173,11 +171,7 @@ class MessagesPresenterTest { } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), liveTimeline = timeline, typingNoticeResult = { Result.success(Unit) }, @@ -223,11 +217,7 @@ class MessagesPresenterTest { } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), liveTimeline = timeline, typingNoticeResult = { Result.success(Unit) }, @@ -288,11 +278,7 @@ class MessagesPresenterTest { val event = aMessageEvent() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), eventPermalinkResult = { Result.success("a link") }, ), typingNoticeResult = { Result.success(Unit) }, @@ -514,11 +500,7 @@ class MessagesPresenterTest { val liveTimeline = FakeTimeline() val joinedRoom = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), liveTimeline = liveTimeline, typingNoticeResult = { Result.success(Unit) }, @@ -586,11 +568,7 @@ class MessagesPresenterTest { fun `present - shows prompt to reinvite users in DM`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1)) }, @@ -619,11 +597,7 @@ class MessagesPresenterTest { fun `present - doesn't show reinvite prompt in non-direct room`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(isDirect = false, joinedMembersCount = 1, activeMembersCount = 1)) }, @@ -645,11 +619,7 @@ class MessagesPresenterTest { fun `present - doesn't show reinvite prompt if other party is present`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 2, activeMembersCount = 2)) }, @@ -672,11 +642,7 @@ class MessagesPresenterTest { val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), typingNoticeResult = { Result.success(Unit) }, inviteUserResult = inviteUserResult, @@ -707,11 +673,7 @@ class MessagesPresenterTest { val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), typingNoticeResult = { Result.success(Unit) }, inviteUserResult = inviteUserResult, @@ -744,11 +706,7 @@ class MessagesPresenterTest { fun `present - handle reinviting other user when memberlist is not ready`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), typingNoticeResult = { Result.success(Unit) }, ) @@ -769,11 +727,7 @@ class MessagesPresenterTest { fun `present - handle reinviting other user when inviting fails`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), typingNoticeResult = { Result.success(Unit) }, inviteUserResult = { Result.failure(RuntimeException("Oops!")) }, @@ -807,17 +761,7 @@ class MessagesPresenterTest { fun `present - permission to post`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - canUserSendMessageResult = { _, messageEventType -> - when (messageEventType) { - MessageEventType.RoomMessage -> Result.success(true) - MessageEventType.Reaction -> Result.success(true) - else -> lambdaError() - } - }, + roomPermissions = roomPermissions(), ), typingNoticeResult = { Result.success(Unit) }, ) @@ -833,17 +777,9 @@ class MessagesPresenterTest { fun `present - no permission to post`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - canUserSendMessageResult = { _, messageEventType -> - when (messageEventType) { - MessageEventType.RoomMessage -> Result.success(false) - MessageEventType.Reaction -> Result.success(false) - else -> lambdaError() - } - }, + roomPermissions = roomPermissions( + canSendMessage = false + ), ), typingNoticeResult = { Result.success(Unit) }, ) @@ -859,11 +795,9 @@ class MessagesPresenterTest { fun `present - permission to redact own`() = runTest { val joinedRoom = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOtherResult = { Result.success(false) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions( + canRedactOther = false + ), ), typingNoticeResult = { Result.success(Unit) }, ) @@ -880,11 +814,9 @@ class MessagesPresenterTest { fun `present - permission to redact other`() = runTest { val joinedRoom = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOtherResult = { Result.success(true) }, - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(false) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions( + canRedactOwn = false + ), ), typingNoticeResult = { Result.success(Unit) }, ) @@ -929,11 +861,7 @@ class MessagesPresenterTest { val timeline = FakeTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), liveTimeline = timeline, typingNoticeResult = { Result.success(Unit) }, @@ -973,11 +901,7 @@ class MessagesPresenterTest { val analyticsService = FakeAnalyticsService() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), liveTimeline = timeline, typingNoticeResult = { Result.success(Unit) }, @@ -1074,11 +998,7 @@ class MessagesPresenterTest { } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ), liveTimeline = timeline, typingNoticeResult = { Result.success(Unit) }, @@ -1115,11 +1035,7 @@ class MessagesPresenterTest { val successorReason = "This room has been moved to a new location" val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), initialRoomInfo = aRoomInfo( successorRoom = SuccessorRoom( roomId = successorRoomId, @@ -1143,11 +1059,7 @@ class MessagesPresenterTest { fun `present - room without successor room has null successor info in state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), initialRoomInfo = aRoomInfo(successorRoom = null) ), typingNoticeResult = { Result.success(Unit) }, @@ -1165,11 +1077,13 @@ class MessagesPresenterTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( sessionId = A_SESSION_ID, - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canSendState = { true }, + canSendMessage = { true }, + canRedactOther = true, + canRedactOwn = true, + canPinUnpin = true, + ), initialRoomInfo = aRoomInfo(isDirect = true, isEncrypted = true) ).apply { givenRoomMembersState(RoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2)))) @@ -1312,16 +1226,44 @@ class MessagesPresenterTest { } } + private fun roomPermissions( + canStartCall: Boolean = true, + canRedactOther: Boolean = true, + canRedactOwn: Boolean = true, + canSendMessage: Boolean = true, + canSendReaction: Boolean = true, + canPinUnpin: Boolean = true, + ) = FakeRoomPermissions( + canSendState = { type -> + when (type) { + StateEventType.CALL_MEMBER -> canStartCall + else -> lambdaError() + } + }, + canSendMessage = { type -> + when (type) { + MessageEventType.RoomMessage -> canSendMessage + MessageEventType.Reaction -> canSendReaction + else -> lambdaError() + } + }, + canRedactOther = canRedactOther, + canRedactOwn = canRedactOwn, + canPinUnpin = canPinUnpin, + ) + private fun TestScope.createMessagesPresenter( coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), timeline: Timeline = FakeTimeline(), joinedRoom: FakeJoinedRoom = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canSendState = { true }, + canSendMessage = { true }, + canRedactOther = true, + canRedactOwn = true, + canPinUnpin = true, + ), ).apply { givenRoomInfo(aRoomInfo(id = roomId, name = "")) }, 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 4a6e777116..2feafbc9e5 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 @@ -69,6 +69,7 @@ import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.mediapickers.api.PickerProvider @@ -991,9 +992,12 @@ class MessageComposerPresenterTest { val invitedUser = aRoomMember(userId = A_USER_ID_3, membership = RoomMembershipState.INVITE) val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN) val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN) - var canUserTriggerRoomNotificationResult = true val room = FakeJoinedRoom( - baseRoom = FakeBaseRoom(canUserTriggerRoomNotificationResult = { Result.success(canUserTriggerRoomNotificationResult) }), + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canTriggerRoomNotification = true, + ) + ), typingNoticeResult = { Result.success(Unit) } ).apply { givenRoomMembersState( @@ -1033,10 +1037,38 @@ class MessageComposerPresenterTest { // If the suggestion isn't a mention, no suggestions are returned initialState.eventSink(MessageComposerEvent.SuggestionReceived(Suggestion(0, 0, SuggestionType.Command, ""))) assertThat(awaitItem().suggestions).isEmpty() + } + } - // If user has no permission to send `@room` mentions, `RoomMemberSuggestion.Room` is not returned - canUserTriggerRoomNotificationResult = false + @Test + fun `present - room mention suggestions no permission`() = runTest { + val currentUser = aRoomMember(userId = A_USER_ID, membership = RoomMembershipState.JOIN) + val invitedUser = aRoomMember(userId = A_USER_ID_3, membership = RoomMembershipState.INVITE) + val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN) + val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN) + val room = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canTriggerRoomNotification = false, + ) + ), + typingNoticeResult = { Result.success(Unit) } + ).apply { + givenRoomMembersState( + RoomMembersState.Ready( + persistentListOf(currentUser, invitedUser, bob, david), + ) + ) + givenRoomInfo(aRoomInfo(isDirect = false)) + } + val presenter = createPresenter(room) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + // An empty suggestion returns the joined members that are not the current user, but not the room initialState.eventSink(MessageComposerEvent.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) + skipItems(1) assertThat(awaitItem().suggestions) .containsExactly(ResolvedSuggestion.Member(bob), ResolvedSuggestion.Member(david)) } @@ -1049,7 +1081,9 @@ class MessageComposerPresenterTest { val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN) val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN) val room = FakeJoinedRoom( - baseRoom = FakeBaseRoom(canUserTriggerRoomNotificationResult = { Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions(canTriggerRoomNotification = true), + ), typingNoticeResult = { Result.success(Unit) } ).apply { givenRoomMembersState( @@ -1069,7 +1103,6 @@ class MessageComposerPresenterTest { presenter.present() }.test { val initialState = awaitItem() - // An empty suggestion returns the joined members that are not the current user, but not the room initialState.eventSink(MessageComposerEvent.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) skipItems(1) 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 8807951d9d..351f841fcf 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 @@ -31,6 +31,7 @@ import io.element.android.libraries.matrix.test.A_UNIQUE_ID import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.sync.FakeSyncService import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.aMessageContent @@ -55,9 +56,7 @@ class PinnedMessagesListPresenterTest { fun `present - initial state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) } @@ -74,9 +73,7 @@ class PinnedMessagesListPresenterTest { fun `present - timeline failure state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) }, @@ -95,9 +92,7 @@ class PinnedMessagesListPresenterTest { fun `present - empty state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf())) }, @@ -117,9 +112,7 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) }, @@ -146,9 +139,7 @@ class PinnedMessagesListPresenterTest { val analyticsService = FakeAnalyticsService() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) }, @@ -194,9 +185,7 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) }, @@ -225,9 +214,7 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) }, @@ -256,9 +243,7 @@ class PinnedMessagesListPresenterTest { val pinnedEventsTimeline = createPinnedMessagesTimeline() val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) }, @@ -295,6 +280,16 @@ class PinnedMessagesListPresenterTest { ) } + private fun roomPermissions( + canRedactOther: Boolean = true, + canRedactOwn: Boolean = true, + canPinUnpin: Boolean = true, + ) = FakeRoomPermissions( + canRedactOther = canRedactOther, + canRedactOwn = canRedactOwn, + canPinUnpin = canPinUnpin, + ) + private fun TestScope.createPinnedMessagesListPresenter( navigator: PinnedMessagesListNavigator = FakePinnedMessagesListNavigator(), room: JoinedRoom = FakeJoinedRoom(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 13c28da6e9..b84975c6a5 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -8,8 +8,6 @@ package io.element.android.features.messages.impl.timeline -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow import app.cash.turbine.ReceiveTurbine import app.cash.turbine.test import com.google.common.truth.Truth.assertThat @@ -35,6 +33,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.asEventId +import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem @@ -55,6 +54,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.aMessageContent import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem @@ -66,6 +66,7 @@ import io.element.android.tests.testutils.awaitLastSequentialItem import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.assert +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 @@ -97,9 +98,7 @@ class TimelinePresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createTimelinePresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.timelineItems).isEmpty() assertThat(initialState.isLive).isTrue() @@ -118,9 +117,7 @@ class TimelinePresenterTest { this.paginateLambda = paginateLambda } val presenter = createTimelinePresenter(timeline = timeline) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS)) initialState.eventSink.invoke(TimelineEvents.LoadMore(Timeline.PaginationDirection.FORWARDS)) @@ -166,9 +163,6 @@ class TimelinePresenterTest { ) val room = FakeJoinedRoom( liveTimeline = timeline, - baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, - ) ) val sessionPreferencesStore = InMemorySessionPreferencesStore(isSendPublicReadReceiptsEnabled = isSendPublicReadReceiptsEnabled) val presenter = createTimelinePresenter( @@ -176,9 +170,7 @@ class TimelinePresenterTest { room = room, sessionPreferencesStore = sessionPreferencesStore, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0)) runCurrent() @@ -211,9 +203,7 @@ class TimelinePresenterTest { this.sendReadReceiptLambda = sendReadReceiptsLambda } val presenter = createTimelinePresenter(timeline) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) awaitItem().run { eventSink.invoke(TimelineEvents.OnScrollFinished(1)) @@ -252,9 +242,7 @@ class TimelinePresenterTest { timeline = timeline, sessionPreferencesStore = sessionPreferencesStore, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) awaitItem().run { eventSink.invoke(TimelineEvents.OnScrollFinished(0)) @@ -290,9 +278,7 @@ class TimelinePresenterTest { this.sendReadReceiptLambda = sendReadReceiptsLambda } val presenter = createTimelinePresenter(timeline) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) awaitItem().run { eventSink.invoke(TimelineEvents.OnScrollFinished(1)) @@ -320,9 +306,7 @@ class TimelinePresenterTest { this.sendReadReceiptLambda = sendReadReceiptsLambda } val presenter = createTimelinePresenter(timeline) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(1)) @@ -339,9 +323,7 @@ class TimelinePresenterTest { markAsReadResult = { Result.success(Unit) }, ) val presenter = createTimelinePresenter(timeline) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.newEventState).isEqualTo(NewEventState.None) assertThat(initialState.timelineItems.size).isEqualTo(0) @@ -390,9 +372,7 @@ class TimelinePresenterTest { timelineItems = timelineItems, ) val presenter = createTimelinePresenter(timeline) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.newEventState).isEqualTo(NewEventState.None) assertThat(initialState.timelineItems.size).isEqualTo(0) @@ -446,9 +426,7 @@ class TimelinePresenterTest { val presenter = createTimelinePresenter( sendPollResponseAction = sendPollResponseAction, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.SelectPollAnswer(AN_EVENT_ID, "anAnswerId")) } @@ -462,9 +440,7 @@ class TimelinePresenterTest { val presenter = createTimelinePresenter( endPollAction = endPollAction, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.EndPoll(AN_EVENT_ID)) } @@ -481,9 +457,7 @@ class TimelinePresenterTest { val presenter = createTimelinePresenter( messagesNavigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitFirstItem().eventSink(TimelineEvents.EditPoll(AN_EVENT_ID)) onEditPollClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) } @@ -500,9 +474,7 @@ class TimelinePresenterTest { ), redactedVoiceMessageManager = redactedVoiceMessageManager, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { assertThat(redactedVoiceMessageManager.invocations.size).isEqualTo(0) skipItems(2) assertThat(redactedVoiceMessageManager.invocations.size).isEqualTo(1) @@ -528,16 +500,14 @@ class TimelinePresenterTest { liveTimeline = liveTimeline, createTimelineResult = { Result.success(detachedTimeline) }, baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), threadRootIdForEventResult = { _ -> Result.success(null) }, ), ) val presenter = createTimelinePresenter( room = room, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> @@ -579,15 +549,13 @@ class TimelinePresenterTest { ) ), baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), threadRootIdForEventResult = { Result.success(null) }, ), ), timelineItemIndexer = timelineItemIndexer, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() advanceUntilIdle() @@ -619,14 +587,12 @@ class TimelinePresenterTest { ), createTimelineResult = { Result.failure(RuntimeException("An error")) }, baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), threadRootIdForEventResult = { _ -> Result.success(null) }, ), ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> @@ -668,7 +634,7 @@ class TimelinePresenterTest { liveTimeline = liveTimeline, createTimelineResult = { Result.success(detachedTimeline) }, baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), threadRootIdForEventResult = { _ -> Result.success(threadId) }, ), ) @@ -679,9 +645,7 @@ class TimelinePresenterTest { timeline = liveTimeline, messagesNavigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) @@ -729,7 +693,7 @@ class TimelinePresenterTest { liveTimeline = liveTimeline, createTimelineResult = { Result.success(detachedTimeline) }, baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), threadRootIdForEventResult = { _ -> Result.success(threadId) }, ), ) @@ -740,9 +704,7 @@ class TimelinePresenterTest { timeline = liveTimeline, messagesNavigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) @@ -785,7 +747,7 @@ class TimelinePresenterTest { liveTimeline = liveTimeline, createTimelineResult = { Result.success(detachedTimeline) }, baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), // Use a different thread id threadRootIdForEventResult = { _ -> Result.success(A_THREAD_ID_2) }, ), @@ -797,9 +759,7 @@ class TimelinePresenterTest { timeline = liveTimeline, messagesNavigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) @@ -846,7 +806,7 @@ class TimelinePresenterTest { liveTimeline = liveTimeline, createTimelineResult = { Result.success(detachedTimeline) }, baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), // The event is in the main timeline, not in a thread threadRootIdForEventResult = { _ -> Result.success(null) }, ), @@ -858,9 +818,7 @@ class TimelinePresenterTest { timeline = liveTimeline, messagesNavigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) @@ -891,9 +849,7 @@ class TimelinePresenterTest { fun `present - show shield hide shield`() = runTest { val presenter = createTimelinePresenter() val shield = aCriticalShield() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.messageShield).isNull() initialState.eventSink(TimelineEvents.ShowShieldDialog(shield)) @@ -929,7 +885,9 @@ class TimelinePresenterTest { ) val room = FakeJoinedRoom( liveTimeline = timeline, - baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + ), ).apply { givenRoomMembersState(RoomMembersState.Unknown) } @@ -937,9 +895,7 @@ class TimelinePresenterTest { val avatarUrl = "https://domain.com/avatar.jpg" val presenter = createTimelinePresenter(timeline, room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = consumeItemsUntilPredicate(30.seconds) { it.timelineItems.isNotEmpty() }.last() val event = initialState.timelineItems.first() as TimelineItem.Event assertThat(event.senderAvatar.url).isNull() @@ -963,15 +919,13 @@ class TimelinePresenterTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), predecessorRoomResult = { predecessorRoom } ), ) val presenter = createTimelinePresenter(room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.timelineRoomInfo.predecessorRoom).isNotNull() assertThat(initialState.timelineRoomInfo.predecessorRoom?.roomId).isEqualTo(predecessorRoomId) @@ -982,14 +936,12 @@ class TimelinePresenterTest { fun `present - timeline room info no predecessor`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), predecessorRoomResult = { null } ), ) val presenter = createTimelinePresenter(room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.timelineRoomInfo.predecessorRoom).isNull() } @@ -999,7 +951,7 @@ class TimelinePresenterTest { fun `present - timeline event navigate to room`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserSendMessageResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ), ) val onNavigateToRoomLambda = lambdaRecorder, Unit> { _, _, _ -> } @@ -1025,11 +977,32 @@ class TimelinePresenterTest { return awaitItem() } + private fun roomPermissions( + canRedactOther: Boolean = false, + canRedactOwn: Boolean = true, + canSendMessage: Boolean = true, + canSendReaction: Boolean = true, + canPinUnpin: Boolean = false, + ) = FakeRoomPermissions( + canSendMessage = { type -> + when (type) { + MessageEventType.RoomMessage -> canSendMessage + MessageEventType.Reaction -> canSendReaction + else -> lambdaError() + } + }, + canRedactOther = canRedactOther, + canRedactOwn = canRedactOwn, + canPinUnpin = canPinUnpin, + ) + private fun TestScope.createTimelinePresenter( timeline: Timeline = FakeTimeline(), room: FakeJoinedRoom = FakeJoinedRoom( liveTimeline = timeline, - baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + ), ), redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(), messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(), diff --git a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt index 1aceee227a..bb0dc04c18 100644 --- a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt +++ b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt @@ -15,9 +15,12 @@ import io.element.android.features.call.test.FakeCurrentCallService import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.roomcall.api.RoomCallState import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.test import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest @@ -28,7 +31,7 @@ class RoomCallStatePresenterTest { fun `present - initial state`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(false) }, + roomPermissions = roomPermissions(false), ) ) val presenter = createRoomCallStatePresenter(joinedRoom = room) @@ -47,7 +50,7 @@ class RoomCallStatePresenterTest { fun `present - element call not available`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(false) }, + roomPermissions = roomPermissions(false), ) ) val presenter = createRoomCallStatePresenter( @@ -66,7 +69,7 @@ class RoomCallStatePresenterTest { fun `present - initial state - user can join call`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions(true), ) ) val presenter = createRoomCallStatePresenter(joinedRoom = room) @@ -85,7 +88,7 @@ class RoomCallStatePresenterTest { fun `present - call is disabled if user cannot join it even if there is an ongoing call`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(false) }, + roomPermissions = roomPermissions(false), initialRoomInfo = aRoomInfo(hasRoomCall = true), ) ) @@ -106,7 +109,7 @@ class RoomCallStatePresenterTest { fun `present - user has joined the call on another session`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions(true), ).apply { givenRoomInfo( aRoomInfo( @@ -133,7 +136,7 @@ class RoomCallStatePresenterTest { fun `present - user has joined the call locally`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions(true), ).apply { givenRoomInfo( aRoomInfo( @@ -163,7 +166,7 @@ class RoomCallStatePresenterTest { fun `present - user leaves the call`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions(true), ).apply { givenRoomInfo( aRoomInfo( @@ -223,6 +226,17 @@ class RoomCallStatePresenterTest { } } + private fun roomPermissions(canJoinCall: Boolean): FakeRoomPermissions { + return FakeRoomPermissions( + canSendState = { stateEvent -> + when (stateEvent) { + StateEventType.CALL_MEMBER -> canJoinCall + else -> lambdaError() + } + } + ) + } + private fun createRoomCallStatePresenter( joinedRoom: JoinedRoom, currentCallService: CurrentCallService = FakeCurrentCallService(), diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt index 5043aea88c..2d85744345 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt @@ -13,8 +13,8 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.tests.testutils.lambda.lambdaError fun aRoom( @@ -35,6 +36,7 @@ fun aRoom( topic: String? = A_ROOM_TOPIC, avatarUrl: String? = AN_AVATAR_URL, canonicalAlias: RoomAlias? = A_ROOM_ALIAS, + roomPermissions: RoomPermissions = FakeRoomPermissions(), isEncrypted: Boolean = true, isPublic: Boolean = true, isDirect: Boolean = false, @@ -42,29 +44,20 @@ fun aRoom( activeMemberCount: Long = 1, joinedMemberCount: Long = 1, invitedMemberCount: Long = 0, - canInviteResult: (UserId) -> Result = { lambdaError() }, - canBanResult: (UserId) -> Result = { lambdaError() }, - canKickResult: (UserId) -> Result = { lambdaError() }, - canSendStateResult: (UserId, StateEventType) -> Result = { _, _ -> lambdaError() }, userDisplayNameResult: (UserId) -> Result = { lambdaError() }, userAvatarUrlResult: () -> Result = { lambdaError() }, - canUserJoinCallResult: (UserId) -> Result = { lambdaError() }, getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, userRoleResult: () -> Result = { lambdaError() }, setIsFavoriteResult: (Boolean) -> Result = { lambdaError() }, ) = FakeBaseRoom( sessionId = sessionId, roomId = roomId, - canInviteResult = canInviteResult, - canBanResult = canBanResult, - canKickResult = canKickResult, - canSendStateResult = canSendStateResult, userDisplayNameResult = userDisplayNameResult, userAvatarUrlResult = userAvatarUrlResult, - canUserJoinCallResult = canUserJoinCallResult, getUpdatedMemberResult = getUpdatedMemberResult, userRoleResult = userRoleResult, setIsFavoriteResult = setIsFavoriteResult, + roomPermissions = roomPermissions, initialRoomInfo = aRoomInfo( name = displayName, rawName = rawName, @@ -89,6 +82,7 @@ fun aJoinedRoom( topic: String? = A_ROOM_TOPIC, avatarUrl: String? = AN_AVATAR_URL, canonicalAlias: RoomAlias? = A_ROOM_ALIAS, + roomPermissions: RoomPermissions = FakeRoomPermissions(), isEncrypted: Boolean = true, isPublic: Boolean = true, isDirect: Boolean = false, @@ -97,17 +91,12 @@ fun aJoinedRoom( joinedMemberCount: Long = 1, invitedMemberCount: Long = 0, notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), - canInviteResult: (UserId) -> Result = { lambdaError() }, - canBanResult: (UserId) -> Result = { lambdaError() }, - canKickResult: (UserId) -> Result = { lambdaError() }, - canSendStateResult: (UserId, StateEventType) -> Result = { _, _ -> lambdaError() }, userDisplayNameResult: (UserId) -> Result = { lambdaError() }, userAvatarUrlResult: () -> Result = { lambdaError() }, setNameResult: (String) -> Result = { lambdaError() }, setTopicResult: (String) -> Result = { lambdaError() }, updateAvatarResult: (String, ByteArray) -> Result = { _, _ -> lambdaError() }, removeAvatarResult: () -> Result = { lambdaError() }, - canUserJoinCallResult: (UserId) -> Result = { lambdaError() }, getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, userRoleResult: () -> Result = { lambdaError() }, kickUserResult: (UserId, String?) -> Result = { _, _ -> lambdaError() }, @@ -132,13 +121,9 @@ fun aJoinedRoom( baseRoom = aRoom( sessionId = sessionId, roomId = roomId, - canInviteResult = canInviteResult, - canBanResult = canBanResult, - canKickResult = canKickResult, - canSendStateResult = canSendStateResult, + roomPermissions = roomPermissions, userDisplayNameResult = userDisplayNameResult, userAvatarUrlResult = userAvatarUrlResult, - canUserJoinCallResult = canUserJoinCallResult, getUpdatedMemberResult = getUpdatedMemberResult, userRoleResult = userRoleResult, setIsFavoriteResult = setIsFavoriteResult, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index 9cf46c41c0..7d6219004e 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME @@ -41,6 +42,7 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.services.analytics.api.AnalyticsService @@ -119,9 +121,7 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state is created from initial room info`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -148,9 +148,7 @@ class RoomDetailsPresenterTest { pinnedEventIds = listOf(AN_EVENT_ID), ) val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(roomInfo) } @@ -170,9 +168,7 @@ class RoomDetailsPresenterTest { fun `present - initial state with no room name`() = runTest { val room = aJoinedRoom( displayName = "", - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -188,9 +184,7 @@ class RoomDetailsPresenterTest { val myRoomMember = aRoomMember(A_SESSION_ID) val otherRoomMember = aRoomMember(A_USER_ID_2) val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), getUpdatedMemberResult = { userId -> when (userId) { A_SESSION_ID -> Result.success(myRoomMember) @@ -225,9 +219,9 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can invite others to room`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions( + canInvite = true, + ), ) val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -243,26 +237,9 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can not invite others to room`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(false) }, - canKickResult = { Result.success(false) }, - canBanResult = { Result.success(false) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, - ) - val presenter = createRoomDetailsPresenter(room) - presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { - assertThat(awaitItem().canInvite).isFalse() - - cancelAndIgnoreRemainingEvents() - } - } - - @Test - fun `present - initial state when canInvite errors`() = runTest { - val room = aJoinedRoom( - canInviteResult = { Result.failure(RuntimeException("Whoops")) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions( + canInvite = false, + ), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -275,17 +252,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can edit one attribute`() = runTest { val room = aJoinedRoom( - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_TOPIC -> Result.success(true) - StateEventType.ROOM_NAME -> Result.success(false) - else -> Result.failure(RuntimeException("Whelp")) - } - }, - canBanResult = { Result.success(false) }, - canKickResult = { Result.success(false) }, - canInviteResult = { Result.success(false) }, - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions( + canChangeName = true, + canChangeTopic = false, + canChangeAvatar = false, + ), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -303,18 +274,7 @@ class RoomDetailsPresenterTest { val myRoomMember = aRoomMember(A_SESSION_ID) val otherRoomMember = aRoomMember(A_USER_ID_2) val room = aJoinedRoom( - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_TOPIC, - StateEventType.ROOM_NAME, - StateEventType.ROOM_AVATAR -> Result.success(true) - else -> Result.failure(RuntimeException("Whelp")) - } - }, - canKickResult = { Result.success(false) }, - canBanResult = { Result.success(false) }, - canInviteResult = { Result.success(false) }, - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions(), getUpdatedMemberResult = { userId -> when (userId) { A_SESSION_ID -> Result.success(myRoomMember) @@ -354,18 +314,9 @@ class RoomDetailsPresenterTest { val room = aJoinedRoom( isDirect = true, topic = null, - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_AVATAR, - StateEventType.ROOM_TOPIC, - StateEventType.ROOM_NAME -> Result.success(true) - else -> Result.failure(RuntimeException("Whelp")) - } - }, + roomPermissions = roomPermissions(), userDisplayNameResult = { Result.success(A_USER_NAME) }, userAvatarUrlResult = { Result.success(AN_AVATAR_URL) }, - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, getUpdatedMemberResult = { userId -> when (userId) { A_SESSION_ID -> Result.success(myRoomMember) @@ -400,24 +351,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can edit all attributes`() = runTest { val room = aJoinedRoom( - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_TOPIC, - StateEventType.ROOM_NAME, - StateEventType.ROOM_AVATAR -> Result.success(true) - else -> Result.failure(RuntimeException("Whelp")) - } - }, - canKickResult = { - Result.success(false) - }, - canBanResult = { - Result.success(false) - }, - canInviteResult = { - Result.success(false) - }, - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions( + canChangeAvatar = true, + canChangeName = true, + canChangeTopic = true, + ), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -433,24 +371,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can edit no attributes`() = runTest { val room = aJoinedRoom( - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_TOPIC, - StateEventType.ROOM_NAME, - StateEventType.ROOM_AVATAR -> Result.success(false) - else -> Result.failure(RuntimeException("Whelp")) - } - }, - canBanResult = { - Result.success(false) - }, - canKickResult = { - Result.success(false) - }, - canInviteResult = { - Result.success(false) - }, - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions( + canChangeAvatar = false, + canChangeName = false, + canChangeTopic = false, + ), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -465,24 +390,9 @@ class RoomDetailsPresenterTest { fun `present - topic state is hidden when no topic and user has no permission`() = runTest { val room = aJoinedRoom( topic = null, - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_AVATAR, - StateEventType.ROOM_NAME -> Result.success(true) - StateEventType.ROOM_TOPIC -> Result.success(false) - else -> Result.failure(RuntimeException("Whelp")) - } - }, - canKickResult = { - Result.success(false) - }, - canBanResult = { - Result.success(false) - }, - canInviteResult = { - Result.success(false) - }, - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions( + canChangeTopic = false + ), ) val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -497,24 +407,7 @@ class RoomDetailsPresenterTest { fun `present - topic state is 'can add topic' when no topic and user has permission`() = runTest { val room = aJoinedRoom( topic = null, - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_AVATAR, - StateEventType.ROOM_TOPIC, - StateEventType.ROOM_NAME -> Result.success(true) - else -> Result.failure(RuntimeException("Whelp")) - } - }, - canKickResult = { - Result.success(false) - }, - canBanResult = { - Result.success(false) - }, - canInviteResult = { - Result.success(false) - }, - canUserJoinCallResult = { Result.success(true) }, + roomPermissions = roomPermissions(), ).apply { givenRoomInfo(aRoomInfo(topic = null)) } @@ -534,9 +427,7 @@ class RoomDetailsPresenterTest { fun `present - leave room event is passed on to leave room presenter`() = runTest { val leaveRoomEventRecorder = EventsRecorder() val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter( room = room, @@ -555,9 +446,7 @@ class RoomDetailsPresenterTest { val notificationSettingsService = FakeNotificationSettingsService() val room = aJoinedRoom( notificationSettingsService = notificationSettingsService, - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter( room = room, @@ -584,9 +473,7 @@ class RoomDetailsPresenterTest { FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) val room = aJoinedRoom( notificationSettingsService = notificationSettingsService, - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter( room = room, @@ -612,9 +499,7 @@ class RoomDetailsPresenterTest { ) val room = aJoinedRoom( notificationSettingsService = notificationSettingsService, - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter( room = room, @@ -637,9 +522,7 @@ class RoomDetailsPresenterTest { val setIsFavoriteResult = lambdaRecorder> { _ -> Result.success(Unit) } val room = aJoinedRoom( setIsFavoriteResult = setIsFavoriteResult, - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val analyticsService = FakeAnalyticsService() val presenter = @@ -665,9 +548,7 @@ class RoomDetailsPresenterTest { @Test fun `present - changes in room info updates the is favorite flag`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val presenter = createRoomDetailsPresenter(room = room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { @@ -686,9 +567,7 @@ class RoomDetailsPresenterTest { @Test fun `present - show knock requests`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), joinRule = JoinRule.Knock, ) val featureFlagService = FakeFeatureFlagService( @@ -712,9 +591,7 @@ class RoomDetailsPresenterTest { @Test fun `present - show security and privacy`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val featureFlagService = FakeFeatureFlagService() val presenter = createRoomDetailsPresenter(room = room, featureFlagService = featureFlagService) @@ -729,9 +606,7 @@ class RoomDetailsPresenterTest { @Test fun `present - show debug info`() = runTest { val room = aJoinedRoom( - canInviteResult = { Result.success(true) }, - canUserJoinCallResult = { Result.success(true) }, - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), ) val inMemoryAppPreferencesStore = InMemoryAppPreferencesStore( isDeveloperModeEnabled = true, @@ -744,4 +619,41 @@ class RoomDetailsPresenterTest { } } } + + private fun roomPermissions( + canInvite: Boolean = true, + canKick: Boolean = true, + canBan: Boolean = true, + canRedactOther: Boolean = true, + canRedactOwn: Boolean = true, + canChangeRoomAccess: Boolean = true, + canChangeHistoryVisibility: Boolean = true, + canChangeEncryption: Boolean = true, + canChangeRoomVisibility: Boolean = true, + canChangeName: Boolean = true, + canChangeTopic: Boolean = true, + canChangeAvatar: Boolean = true, + canChangePowerLevels: Boolean = true, + ): RoomPermissions { + return FakeRoomPermissions( + canInvite = canInvite, + canKick = canKick, + canBan = canBan, + canRedactOther = canRedactOther, + canRedactOwn = canRedactOwn, + canSendState = { eventType -> + when (eventType) { + StateEventType.ROOM_JOIN_RULES -> canChangeRoomAccess + StateEventType.ROOM_HISTORY_VISIBILITY -> canChangeHistoryVisibility + StateEventType.ROOM_ENCRYPTION -> canChangeEncryption + StateEventType.ROOM_CANONICAL_ALIAS -> canChangeRoomVisibility + StateEventType.ROOM_AVATAR -> canChangeAvatar + StateEventType.ROOM_NAME -> canChangeName + StateEventType.ROOM_TOPIC -> canChangeTopic + StateEventType.ROOM_POWER_LEVELS -> canChangePowerLevels + else -> lambdaError() + } + } + ) + } } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenterTest.kt index 8d3d0e35e3..f1cab1524a 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenterTest.kt @@ -12,7 +12,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState @@ -20,6 +19,7 @@ import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test import io.element.android.tests.testutils.testCoroutineDispatchers @@ -171,20 +171,7 @@ class RoomMemberListPresenterTest { fun `present - asynchronously sets canInvite when user does not have correct power level`() = runTest { val presenter = createPresenter( joinedRoom = createFakeJoinedRoom( - canInviteResult = { Result.success(false) }, - ) - ) - presenter.test { - val loadedState = awaitItem() - assertThat(loadedState.canInvite).isFalse() - } - } - - @Test - fun `present - asynchronously sets canInvite when power level check fails`() = runTest { - val presenter = createPresenter( - joinedRoom = createFakeJoinedRoom( - canInviteResult = { Result.failure(RuntimeException("Eek")) }, + canInvite = false, ) ) presenter.test { @@ -207,12 +194,14 @@ class RoomMemberListPresenterTest { private fun createFakeJoinedRoom( updateMembersResult: () -> Unit = { }, - canInviteResult: (UserId) -> Result = { Result.success(true) }, + canInvite: Boolean = true, ): FakeJoinedRoom { return FakeJoinedRoom( baseRoom = FakeBaseRoom( updateMembersResult = updateMembersResult, - canInviteResult = canInviteResult, + roomPermissions = FakeRoomPermissions( + canInvite = canInvite, + ), ).apply { // Needed to avoid discarding the loaded members as a partial and invalid result givenRoomInfo(aRoomInfo(joinedMembersCount = 2)) diff --git a/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt b/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt index f95f4466f2..c400ec1220 100644 --- a/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt +++ b/features/roomdetailsedit/api/src/main/kotlin/io/element/android/features/roomdetailsedit/api/RoomDetailsEditPermissions.kt @@ -14,7 +14,7 @@ data class RoomDetailsEditPermissions( val canEditName: Boolean, val canEditTopic: Boolean, val canEditAvatar: Boolean, -){ +) { val hasAny = canEditName || canEditTopic || canEditAvatar diff --git a/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt b/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt index ed729928d8..24f8f49e81 100644 --- a/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt +++ b/features/roomdetailsedit/impl/src/main/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenter.kt @@ -59,7 +59,6 @@ class RoomDetailsEditPresenter( @Composable override fun present(): RoomDetailsEditState { val cameraPermissionState = cameraPermissionPresenter.present() - val roomSyncUpdateFlow = room.syncUpdateFlow.collectAsState() val roomInfo by room.roomInfoFlow.collectAsState() val roomAvatarUri = roomInfo.avatarUrl var roomAvatarUriEdited by rememberSaveable { mutableStateOf(null) } @@ -94,7 +93,7 @@ class RoomDetailsEditPresenter( } } - val permissions by room.permissionsAsState(RoomDetailsEditPermissions.DEFAULT){perms -> + val permissions by room.permissionsAsState(RoomDetailsEditPermissions.DEFAULT) { perms -> perms.roomDetailsEditPermissions() } diff --git a/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenterTest.kt b/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenterTest.kt index e438cecf50..9c7f840af2 100644 --- a/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenterTest.kt +++ b/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditPresenterTest.kt @@ -13,7 +13,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.file.TemporaryUriDeleter import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.core.mimetype.MimeTypes -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.test.AN_AVATAR_URL @@ -23,6 +22,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_TOPIC import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaUploadInfo @@ -102,7 +102,6 @@ class RoomDetailsEditPresenterTest { avatarUrl = AN_AVATAR_URL, displayName = A_ROOM_NAME, rawName = A_ROOM_RAW_NAME, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -127,17 +126,15 @@ class RoomDetailsEditPresenterTest { @Test fun `present - sets canChangeName if user has permission`() = runTest { - val room = FakeJoinedRoom( - FakeBaseRoom( - canSendStateResult = { _, stateEventType -> - when (stateEventType) { - StateEventType.ROOM_NAME -> Result.success(true) - StateEventType.ROOM_AVATAR -> Result.success(false) - StateEventType.ROOM_TOPIC -> Result.failure(RuntimeException("Oops")) - else -> lambdaError() - } - }, - ) + val room = aJoinedRoom( + canSendState = { stateEventType -> + when (stateEventType) { + StateEventType.ROOM_NAME -> true + StateEventType.ROOM_AVATAR -> false + StateEventType.ROOM_TOPIC -> false + else -> lambdaError() + } + } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -163,11 +160,11 @@ class RoomDetailsEditPresenterTest { fun `present - sets canChangeAvatar if user has permission`() = runTest { val room = aJoinedRoom( avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, stateEventType -> + canSendState = { stateEventType -> when (stateEventType) { - StateEventType.ROOM_NAME -> Result.success(false) - StateEventType.ROOM_AVATAR -> Result.success(true) - StateEventType.ROOM_TOPIC -> Result.failure(RuntimeException("Oops")) + StateEventType.ROOM_NAME -> false + StateEventType.ROOM_AVATAR -> true + StateEventType.ROOM_TOPIC -> false else -> lambdaError() } } @@ -195,11 +192,11 @@ class RoomDetailsEditPresenterTest { fun `present - sets canChangeTopic if user has permission`() = runTest { val room = aJoinedRoom( avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, stateEventType -> + canSendState = { stateEventType -> when (stateEventType) { - StateEventType.ROOM_NAME -> Result.success(false) - StateEventType.ROOM_AVATAR -> Result.failure(RuntimeException("Oops")) - StateEventType.ROOM_TOPIC -> Result.success(true) + StateEventType.ROOM_NAME -> false + StateEventType.ROOM_AVATAR -> false + StateEventType.ROOM_TOPIC -> true else -> lambdaError() } } @@ -229,7 +226,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -274,7 +270,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(anotherAvatarUri) val deleteCallback = lambdaRecorder {} @@ -298,7 +293,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(anotherAvatarUri) val fakePermissionsPresenter = FakePermissionsPresenter() @@ -339,7 +333,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(roomAvatarUri) val deleteCallback = lambdaRecorder {} @@ -389,7 +382,6 @@ class RoomDetailsEditPresenterTest { topic = null, displayName = "fallback", avatarUrl = null, - canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(roomAvatarUri) val deleteCallback = lambdaRecorder {} @@ -445,7 +437,6 @@ class RoomDetailsEditPresenterTest { setNameResult = setNameResult, setTopicResult = setTopicResult, removeAvatarResult = removeAvatarResult, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -471,7 +462,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -493,7 +483,6 @@ class RoomDetailsEditPresenterTest { topic = null, displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -515,7 +504,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -539,7 +527,6 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, updateAvatarResult = updateAvatarResult, - canSendStateResult = { _, _ -> Result.success(true) } ) givenPickerReturnsFile() val deleteCallback = lambdaRecorder {} @@ -566,7 +553,6 @@ class RoomDetailsEditPresenterTest { topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, - canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(anotherAvatarUri) fakeMediaPreProcessor.givenResult(Result.failure(RuntimeException("Oh no"))) @@ -591,7 +577,6 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, setNameResult = { Result.failure(RuntimeException("!")) }, - canSendStateResult = { _, _ -> Result.success(true) } ) saveAndAssertFailure(room, RoomDetailsEditEvent.UpdateRoomName("New name"), deleteCallbackNumberOfInvocation = 1) } @@ -603,7 +588,6 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, setTopicResult = { Result.failure(RuntimeException("!")) }, - canSendStateResult = { _, _ -> Result.success(true) } ) saveAndAssertFailure(room, RoomDetailsEditEvent.UpdateRoomTopic("New topic"), deleteCallbackNumberOfInvocation = 1) } @@ -615,7 +599,6 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, removeAvatarResult = { Result.failure(RuntimeException("!")) }, - canSendStateResult = { _, _ -> Result.success(true) } ) saveAndAssertFailure(room, RoomDetailsEditEvent.HandleAvatarAction(AvatarAction.Remove), deleteCallbackNumberOfInvocation = 2) } @@ -628,7 +611,6 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, updateAvatarResult = { _, _ -> Result.failure(RuntimeException("!")) }, - canSendStateResult = { _, _ -> Result.success(true) } ) saveAndAssertFailure(room, RoomDetailsEditEvent.HandleAvatarAction(AvatarAction.ChoosePhoto), deleteCallbackNumberOfInvocation = 2) } @@ -641,7 +623,6 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, setTopicResult = { Result.failure(RuntimeException("!")) }, - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -663,7 +644,6 @@ class RoomDetailsEditPresenterTest { fun `present - leave without saving - cancel`() = runTest { val room = aJoinedRoom( displayName = "Name", - canSendStateResult = { _, _ -> Result.success(true) } ) val deleteCallback = lambdaRecorder {} val presenter = createRoomDetailsEditPresenter( @@ -693,7 +673,6 @@ class RoomDetailsEditPresenterTest { fun `present - leave no changes, no confirmation`() = runTest { val room = aJoinedRoom( displayName = "Name", - canSendStateResult = { _, _ -> Result.success(true) } ) val presenter = createRoomDetailsEditPresenter( room = room, @@ -711,7 +690,7 @@ class RoomDetailsEditPresenterTest { fun `present - leave without saving - confirm`() = runTest { val room = aJoinedRoom( displayName = "Name", - canSendStateResult = { _, _ -> Result.success(true) } + canSendState = { _ -> true } ) val presenter = createRoomDetailsEditPresenter( room = room, @@ -782,11 +761,13 @@ class RoomDetailsEditPresenterTest { setTopicResult: (String) -> Result = { Result.success(Unit) }, updateAvatarResult: (String, ByteArray) -> Result = { _, _ -> Result.success(Unit) }, removeAvatarResult: () -> Result = { Result.success(Unit) }, - canSendStateResult: (UserId, StateEventType) -> Result, + canSendState: (StateEventType) -> Boolean = { true }, ): JoinedRoom { return FakeJoinedRoom( baseRoom = FakeBaseRoom( - canSendStateResult = canSendStateResult, + roomPermissions = FakeRoomPermissions( + canSendState = canSendState, + ), initialRoomInfo = aRoomInfo( name = displayName, topic = topic, diff --git a/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt b/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt index 2b3f71e770..4ce50a2488 100644 --- a/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt +++ b/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt @@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule @@ -355,8 +356,10 @@ class RoomMemberModerationPresenterTest { banUserResult = { _, _ -> banUserResult }, unBanUserResult = { _, _ -> unBanUserResult }, baseRoom = FakeBaseRoom( - canBanResult = { _ -> Result.success(canBan) }, - canKickResult = { _ -> Result.success(canKick) }, + roomPermissions = FakeRoomPermissions( + canBan = canBan, + canKick = canKick + ), userRoleResult = { Result.success(myUserRole) }, updateMembersResult = { Result.success(Unit) } ), diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt index af0f44be38..81bfe22697 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt @@ -67,7 +67,6 @@ class SecurityAndPrivacyPresenter( }.collectAsState(false) val saveAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } val homeserverName = remember { matrixClient.userIdServerName() } - val syncUpdateFlow = room.syncUpdateFlow.collectAsState() val roomInfo by room.roomInfoFlow.collectAsState() val savedIsVisibleInRoomDirectory = remember { mutableStateOf>(AsyncData.Uninitialized) } diff --git a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/SecurityAndPrivacyPresenterTest.kt b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/SecurityAndPrivacyPresenterTest.kt index 7d88706996..a4542b02a1 100644 --- a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/SecurityAndPrivacyPresenterTest.kt +++ b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/SecurityAndPrivacyPresenterTest.kt @@ -18,15 +18,19 @@ import io.element.android.libraries.architecture.AsyncData 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.room.StateEventType import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest @@ -66,7 +70,7 @@ class SecurityAndPrivacyPresenterTest { fun `present - room info change updates saved and edited settings`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), initialRoomInfo = aRoomInfo( joinRule = JoinRule.Public, historyVisibility = RoomHistoryVisibility.WorldReadable, @@ -173,7 +177,7 @@ class SecurityAndPrivacyPresenterTest { fun `present - room visibility loading and change`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), getRoomVisibilityResult = { Result.success(RoomVisibility.Private) }, initialRoomInfo = aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared) ) @@ -222,7 +226,7 @@ class SecurityAndPrivacyPresenterTest { val updateRoomHistoryVisibilityLambda = lambdaRecorder> { Result.success(Unit) } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), getRoomVisibilityResult = { Result.success(RoomVisibility.Private) }, initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite, historyVisibility = RoomHistoryVisibility.Shared) ), @@ -272,8 +276,8 @@ class SecurityAndPrivacyPresenterTest { isEncrypted = true, ) ) - // Saved settings are updated 3 times to match the edited settings - skipItems(3) + // Saved settings are updated 2 times to match the edited settings + skipItems(2) with(awaitItem()) { assertThat(saveAction).isEqualTo(AsyncAction.Success(Unit)) assertThat(savedSettings).isEqualTo(editedSettings) @@ -297,7 +301,7 @@ class SecurityAndPrivacyPresenterTest { val updateRoomHistoryVisibilityLambda = lambdaRecorder> { Result.success(Unit) } val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), getRoomVisibilityResult = { Result.success(RoomVisibility.Private) }, initialRoomInfo = aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared, joinRule = JoinRule.Private) ), @@ -340,7 +344,7 @@ class SecurityAndPrivacyPresenterTest { ) ) // Saved settings are updated 2 times to match the edited settings - skipItems(3) + skipItems(2) val state = awaitItem() with(state) { assertThat(saveAction).isInstanceOf(AsyncAction.Failure::class.java) @@ -374,11 +378,30 @@ class SecurityAndPrivacyPresenterTest { } } + private fun roomPermissions( + canChangeRoomAccess: Boolean = true, + canChangeHistoryVisibility: Boolean = true, + canChangeEncryption: Boolean = true, + canChangeRoomVisibility: Boolean = true, + ): RoomPermissions { + return FakeRoomPermissions( + canSendState = { eventType -> + when (eventType) { + StateEventType.ROOM_JOIN_RULES -> canChangeRoomAccess + StateEventType.ROOM_HISTORY_VISIBILITY -> canChangeHistoryVisibility + StateEventType.ROOM_ENCRYPTION -> canChangeEncryption + StateEventType.ROOM_CANONICAL_ALIAS -> canChangeRoomVisibility + else -> lambdaError() + } + } + ) + } + private fun createSecurityAndPrivacyPresenter( serverName: String = "matrix.org", room: FakeJoinedRoom = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canSendStateResult = { _, _ -> Result.success(true) }, + roomPermissions = roomPermissions(), getRoomVisibilityResult = { Result.success(RoomVisibility.Private) }, initialRoomInfo = aRoomInfo(historyVisibility = RoomHistoryVisibility.Shared, joinRule = JoinRule.Private) ), diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt index 8b7eddca54..7e09a03ec3 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt @@ -76,7 +76,7 @@ class UserProfilePresenter( roomId ?.let { client.getRoom(it) } ?.use { room -> - room.roomPermissions().use(false){ perms -> perms.canCall()} + room.roomPermissions().use(false) { perms -> perms.canCall() } } .orFalse() } diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt index aa984f0066..b10cf3e48d 100644 --- a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt @@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.MatrixClient 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.encryption.identity.IdentityState +import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -36,9 +37,11 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.room.FakeBaseRoom +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.tests.testutils.WarmUpRule 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 @@ -89,15 +92,7 @@ class UserProfilePresenterTest { @Test fun `present - canCall is false when canUserJoinCall returns false`() { testCanCall( - canUserJoinCallResult = Result.success(false), - expectedResult = false, - ) - } - - @Test - fun `present - canCall is false when canUserJoinCall fails`() { - testCanCall( - canUserJoinCallResult = Result.failure(AN_EXCEPTION), + canUserJoinCall = false, expectedResult = false, ) } @@ -128,7 +123,7 @@ class UserProfilePresenterTest { private fun testCanCall( isElementCallAvailable: Boolean = true, - canUserJoinCallResult: Result = Result.success(true), + canUserJoinCall: Boolean = true, dmRoom: RoomId? = A_ROOM_ID, canFindRoom: Boolean = true, expectedResult: Boolean, @@ -136,7 +131,14 @@ class UserProfilePresenterTest { checkThatRoomIsDestroyed: Boolean = false, ) = runTest { val room = FakeBaseRoom( - canUserJoinCallResult = { canUserJoinCallResult }, + roomPermissions = FakeRoomPermissions( + canSendState = { type -> + when (type) { + StateEventType.CALL_MEMBER -> canUserJoinCall + else -> lambdaError() + } + } + ), ) val client = createFakeMatrixClient().apply { if (canFindRoom) { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt index 735627e10e..638bf5449c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPermissions.kt @@ -18,7 +18,6 @@ import io.element.android.libraries.matrix.api.room.StateEventType import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map -import timber.log.Timber /** * Provides information about the permissions of users in a room. @@ -150,7 +149,15 @@ fun Result.use(default: T, block: (RoomPermissions) -> T): fun BaseRoom.permissionsFlow(default: T, block: (RoomPermissions) -> T): Flow { return roomInfoFlow - .map { info -> info.roomPowerLevels } + .map { info -> + // If the user is a privileged creator, we return a constant hashcode to avoid recomputing permissions + // each time the power levels change (as they have all permissions). + if (info.privilegedCreatorRole && info.creators.contains(sessionId)) { + Long.MAX_VALUE + } else { + info.roomPowerLevels?.hashCode() ?: 0L + } + } .distinctUntilChanged() .map { roomPermissions().use(default, block) @@ -160,7 +167,6 @@ fun BaseRoom.permissionsFlow(default: T, block: (RoomPermissions) -> T): Flo @Composable fun BaseRoom.permissionsAsState(default: T, block: (RoomPermissions) -> T): State { return remember(this, default, block) { - Timber.d("Computing permissionsAsState for room $roomId with default=$default") permissionsFlow(default, block) }.collectAsState(default) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index 141957d1ed..1aeb8f445d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -18,12 +18,10 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.BaseRoom -import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipObserver -import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt index b05eff77e2..b56066af73 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt @@ -15,11 +15,9 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.BaseRoom -import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState -import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues @@ -42,6 +40,7 @@ class FakeBaseRoom( override val sessionId: SessionId = A_SESSION_ID, override val roomId: RoomId = A_ROOM_ID, initialRoomInfo: RoomInfo = aRoomInfo(), + private val roomPermissions: RoomPermissions = FakeRoomPermissions(), override val roomCoroutineScope: CoroutineScope = TestScope(), private var roomPermalinkResult: () -> Result = { lambdaError() }, private var eventPermalinkResult: (EventId) -> Result = { lambdaError() }, @@ -50,17 +49,6 @@ class FakeBaseRoom( private val userRoleResult: () -> Result = { lambdaError() }, private val getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, private val joinRoomResult: () -> Result = { lambdaError() }, - private val roomPermissionsResult: () -> Result = { Result.success(FakeRoomPermissions()) }, - private val canInviteResult: (UserId) -> Result = { lambdaError() }, - private val canKickResult: (UserId) -> Result = { lambdaError() }, - private val canBanResult: (UserId) -> Result = { lambdaError() }, - private val canRedactOwnResult: (UserId) -> Result = { lambdaError() }, - private val canRedactOtherResult: (UserId) -> Result = { lambdaError() }, - private val canSendStateResult: (UserId, StateEventType) -> Result = { _, _ -> lambdaError() }, - private val canUserSendMessageResult: (UserId, MessageEventType) -> Result = { _, _ -> lambdaError() }, - private val canUserTriggerRoomNotificationResult: (UserId) -> Result = { lambdaError() }, - private val canUserJoinCallResult: (UserId) -> Result = { lambdaError() }, - private val canUserPinUnpinResult: (UserId) -> Result = { lambdaError() }, private val setIsFavoriteResult: (Boolean) -> Result = { lambdaError() }, private val markAsReadResult: (ReceiptType) -> Result = { Result.success(Unit) }, private val powerLevelsResult: () -> Result = { lambdaError() }, @@ -133,7 +121,7 @@ class FakeBaseRoom( } override suspend fun roomPermissions(): Result { - return roomPermissionsResult() + return Result.success(roomPermissions) } override suspend fun getPermalink(): Result { @@ -160,46 +148,6 @@ class FakeBaseRoom( return forgetResult() } - override suspend fun canUserBan(userId: UserId): Result { - return canBanResult(userId) - } - - override suspend fun canUserKick(userId: UserId): Result { - return canKickResult(userId) - } - - override suspend fun canUserInvite(userId: UserId): Result { - return canInviteResult(userId) - } - - override suspend fun canUserRedactOwn(userId: UserId): Result { - return canRedactOwnResult(userId) - } - - override suspend fun canUserRedactOther(userId: UserId): Result { - return canRedactOtherResult(userId) - } - - override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result { - return canSendStateResult(userId, type) - } - - override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result { - return canUserSendMessageResult(userId, type) - } - - override suspend fun canUserTriggerRoomNotification(userId: UserId): Result { - return canUserTriggerRoomNotificationResult(userId) - } - - override suspend fun canUserJoinCall(userId: UserId): Result { - return canUserJoinCallResult(userId) - } - - override suspend fun canUserPinUnpin(userId: UserId): Result { - return canUserPinUnpinResult(userId) - } - override suspend fun setIsFavorite(isFavorite: Boolean): Result { return setIsFavoriteResult(isFavorite) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt index 04ecb1f60b..b78dc9ba1b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/powerlevels/FakeRoomPermissions.kt @@ -13,44 +13,44 @@ import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions data class FakeRoomPermissions( - val ownerCanBan: Boolean = false, - val ownerCanInvite: Boolean = false, - val ownerCanKick: Boolean = false, - val ownerCanPinUnpin: Boolean = false, - val ownerCanRedactOther: Boolean = false, - val ownerCanRedactOwn: Boolean = false, - val ownerCanTriggerRoomNotification: Boolean = false, - val ownerCanSendMessage: (MessageEventType) -> Boolean = { false }, - val ownerCanSendState: (StateEventType) -> Boolean = { false }, - val userCanBan: (UserId) -> Boolean = { false }, - val userCanInvite: (UserId) -> Boolean = { false }, - val userCanKick: (UserId) -> Boolean = { false }, - val userCanPinUnpin: (UserId) -> Boolean = { false }, - val userCanRedactOther: (UserId) -> Boolean = { false }, - val userCanRedactOwn: (UserId) -> Boolean = { false }, - val userCanTriggerRoomNotification: (UserId) -> Boolean = { false }, - val userCanSendMessage: (UserId, MessageEventType) -> Boolean = { _, _ -> false }, - val userCanSendState: (UserId, StateEventType) -> Boolean = { _, _ -> false }, + private val canBan: Boolean = false, + private val canInvite: Boolean = false, + private val canKick: Boolean = false, + private val canPinUnpin: Boolean = false, + private val canRedactOther: Boolean = false, + private val canRedactOwn: Boolean = false, + private val canTriggerRoomNotification: Boolean = false, + private val canSendMessage: (MessageEventType) -> Boolean = { false }, + private val canSendState: (StateEventType) -> Boolean = { false }, + private val canUserBan: (UserId) -> Boolean = { false }, + private val canUserInvite: (UserId) -> Boolean = { false }, + private val canUserKick: (UserId) -> Boolean = { false }, + private val canUserPinUnpin: (UserId) -> Boolean = { false }, + private val canUserRedactOther: (UserId) -> Boolean = { false }, + private val canUserRedactOwn: (UserId) -> Boolean = { false }, + private val canUserTriggerRoomNotification: (UserId) -> Boolean = { false }, + private val canUserSendMessage: (UserId, MessageEventType) -> Boolean = { _, _ -> false }, + private val canUserSendState: (UserId, StateEventType) -> Boolean = { _, _ -> false }, ) : RoomPermissions { + override fun canOwnUserBan(): Boolean = canBan + override fun canOwnUserInvite(): Boolean = canInvite + override fun canOwnUserKick(): Boolean = canKick + override fun canOwnUserPinUnpin(): Boolean = canPinUnpin + override fun canOwnUserRedactOther(): Boolean = canRedactOther + override fun canOwnUserRedactOwn(): Boolean = canRedactOwn + override fun canOwnUserSendMessage(message: MessageEventType): Boolean = canSendMessage(message) + override fun canOwnUserSendState(stateEvent: StateEventType): Boolean = canSendState(stateEvent) - override fun canOwnUserBan(): Boolean = ownerCanBan - override fun canOwnUserInvite(): Boolean = ownerCanInvite - override fun canOwnUserKick(): Boolean = ownerCanKick - override fun canOwnUserPinUnpin(): Boolean = ownerCanPinUnpin - override fun canOwnUserRedactOther(): Boolean = ownerCanRedactOther - override fun canOwnUserRedactOwn(): Boolean = ownerCanRedactOwn - override fun canOwnUserSendMessage(message: MessageEventType): Boolean = ownerCanSendMessage(message) - override fun canOwnUserSendState(stateEvent: StateEventType): Boolean = ownerCanSendState(stateEvent) - override fun canOwnUserTriggerRoomNotification(): Boolean = ownerCanTriggerRoomNotification - override fun canUserBan(userId: UserId): Boolean = userCanBan(userId) - override fun canUserInvite(userId: UserId): Boolean = userCanInvite(userId) - override fun canUserKick(userId: UserId): Boolean = userCanKick(userId) - override fun canUserPinUnpin(userId: UserId): Boolean = userCanPinUnpin(userId) - override fun canUserRedactOther(userId: UserId): Boolean = userCanRedactOther(userId) - override fun canUserRedactOwn(userId: UserId): Boolean = userCanRedactOwn(userId) - override fun canUserSendMessage(userId: UserId, message: MessageEventType): Boolean = userCanSendMessage(userId, message) - override fun canUserSendState(userId: UserId, stateEvent: StateEventType): Boolean = userCanSendState(userId, stateEvent) - override fun canUserTriggerRoomNotification(userId: UserId): Boolean = userCanTriggerRoomNotification(userId) + override fun canOwnUserTriggerRoomNotification(): Boolean = canTriggerRoomNotification + override fun canUserBan(userId: UserId): Boolean = canUserBan(userId) + override fun canUserInvite(userId: UserId): Boolean = canUserInvite(userId) + override fun canUserKick(userId: UserId): Boolean = canUserKick(userId) + override fun canUserPinUnpin(userId: UserId): Boolean = canUserPinUnpin(userId) + override fun canUserRedactOther(userId: UserId): Boolean = canUserRedactOther(userId) + override fun canUserRedactOwn(userId: UserId): Boolean = canUserRedactOwn(userId) + override fun canUserSendMessage(userId: UserId, message: MessageEventType): Boolean = canUserSendMessage(userId, message) + override fun canUserSendState(userId: UserId, stateEvent: StateEventType): Boolean = canUserSendState(userId, stateEvent) + override fun canUserTriggerRoomNotification(userId: UserId): Boolean = canUserTriggerRoomNotification(userId) override fun close() { // no-op for the fake diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index e5e493ee63..cc26e69c33 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -207,7 +207,6 @@ class MediaGalleryPresenter( CommonStrings.error_unknown } } - } private fun GroupedMediaItems?.find(eventId: EventId?): MediaItem.Event? { diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt index e890b7f036..3069a4fd9d 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt @@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.mediaviewer.impl.datasource.FakeMediaGalleryDataSource import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryDataSource @@ -109,7 +110,9 @@ class MediaGalleryPresenterTest { baseRoom = FakeBaseRoom( sessionId = A_USER_ID, initialRoomInfo = aRoomInfo(name = A_ROOM_NAME), - canRedactOwnResult = { Result.success(canDeleteOwn) } + roomPermissions = FakeRoomPermissions( + canRedactOwn = canDeleteOwn + ), ), ) ) @@ -153,7 +156,9 @@ class MediaGalleryPresenterTest { baseRoom = FakeBaseRoom( sessionId = A_USER_ID, initialRoomInfo = aRoomInfo(name = A_ROOM_NAME), - canRedactOtherResult = { Result.success(canDeleteOther) }, + roomPermissions = FakeRoomPermissions( + canRedactOther = canDeleteOther + ), ), createTimelineResult = { Result.success(FakeTimeline()) } ) @@ -355,7 +360,9 @@ class MediaGalleryPresenterTest { room = FakeJoinedRoom( createTimelineResult = { Result.success(FakeTimeline()) }, baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), ), ), navigator = navigator, @@ -386,7 +393,9 @@ class MediaGalleryPresenterTest { room = FakeJoinedRoom( createTimelineResult = { Result.success(FakeTimeline()) }, baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), ), ), navigator = navigator, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt index d9769aac13..a9d1704bdc 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader import io.element.android.libraries.matrix.test.media.aMediaSource import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.anApkMediaInfo @@ -83,7 +84,9 @@ class MediaViewerPresenterTest { localMediaFactory = localMediaFactory, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), ) ) ) @@ -104,7 +107,9 @@ class MediaViewerPresenterTest { canShowInfo = false, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), ) ) ) @@ -125,7 +130,9 @@ class MediaViewerPresenterTest { eventId = AN_EVENT_ID, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), ) ) ) @@ -147,7 +154,9 @@ class MediaViewerPresenterTest { room = FakeJoinedRoom( baseRoom = FakeBaseRoom( sessionId = A_SESSION_ID_2, - canRedactOtherResult = { Result.success(false) }, + roomPermissions = FakeRoomPermissions( + canRedactOther = false + ), ) ) ) @@ -236,7 +245,9 @@ class MediaViewerPresenterTest { mediaGalleryDataSource = mediaGalleryDataSource, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), ) ) ) @@ -460,7 +471,11 @@ class MediaViewerPresenterTest { localMediaFactory = localMediaFactory, room = FakeJoinedRoom( liveTimeline = timeline, - baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), + ), ), mediaGalleryDataSource = mediaGalleryDataSource, mediaViewerNavigator = FakeMediaViewerNavigator( @@ -769,7 +784,11 @@ class MediaViewerPresenterTest { localMediaFactory = localMediaFactory, mediaViewerNavigator = navigator, room = FakeJoinedRoom( - baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), + ), ) ) presenter.test { @@ -794,7 +813,11 @@ class MediaViewerPresenterTest { localMediaFactory = localMediaFactory, mediaViewerNavigator = navigator, room = FakeJoinedRoom( - baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), + ), ), ) presenter.test { @@ -821,7 +844,11 @@ class MediaViewerPresenterTest { localMediaFactory = localMediaFactory, mediaViewerNavigator = navigator, room = FakeJoinedRoom( - baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), + ), ), ) presenter.test { From 6791890bf98299eab941138f7c2ba5225d985d2a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Dec 2025 12:20:13 +0100 Subject: [PATCH 56/64] Import Compound tokens from release v6.4.2 https://github.com/element-hq/compound-design-tokens/releases/tag/v6.4.2 --- .../compound/src/main/assets/theme.iife.js | 39 +------------------ .../tokens/generated/CompoundIcons.kt | 39 ++++++++++++------- .../tokens/generated/SemanticColors.kt | 38 ++++++++---------- .../tokens/generated/SemanticColorsDark.kt | 18 ++++----- .../tokens/generated/SemanticColorsDarkHc.kt | 18 ++++----- .../tokens/generated/SemanticColorsLight.kt | 18 ++++----- .../tokens/generated/SemanticColorsLightHc.kt | 18 ++++----- .../tokens/generated/TypographyTokens.kt | 4 -- .../generated/internal/DarkColorTokens.kt | 3 -- .../generated/internal/DarkHcColorTokens.kt | 3 -- .../generated/internal/LightColorTokens.kt | 3 -- .../generated/internal/LightHcColorTokens.kt | 3 -- .../drawable/ic_compound_exit_full_screen.xml | 9 +++++ .../res/drawable/ic_compound_full_screen.xml | 9 +++++ .../drawable/ic_compound_left_panel_close.xml | 9 +++++ .../main/res/drawable/ic_compound_space.xml | 9 +++++ .../res/drawable/ic_compound_space_solid.xml | 9 +++++ .../main/res/drawable/ic_compound_threads.xml | 12 +++--- .../drawable/ic_compound_threads_solid.xml | 6 +-- .../res/drawable/ic_compound_workspace.xml | 9 ----- .../drawable/ic_compound_workspace_solid.xml | 9 ----- 21 files changed, 132 insertions(+), 153 deletions(-) create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_exit_full_screen.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_full_screen.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_left_panel_close.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_space.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_space_solid.xml delete mode 100644 libraries/compound/src/main/res/drawable/ic_compound_workspace.xml delete mode 100644 libraries/compound/src/main/res/drawable/ic_compound_workspace_solid.xml diff --git a/libraries/compound/src/main/assets/theme.iife.js b/libraries/compound/src/main/assets/theme.iife.js index 4be509b11c..71ce6b0013 100644 --- a/libraries/compound/src/main/assets/theme.iife.js +++ b/libraries/compound/src/main/assets/theme.iife.js @@ -1,38 +1 @@ -var CompoundTheme=(function(Fe){"use strict";const Xe=(e,t=0,r=1)=>Zt(Jt(t,e),r),Yt=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=Xe(e[t],0,255)):t===3&&(e[t]=Xe(e[t],0,1));return e},co={};for(let e of["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"])co[`[object ${e}]`]=e.toLowerCase();function S(e){return co[Object.prototype.toString.call(e)]||"object"}const P=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):S(e[0])=="object"&&t?t.split("").filter(r=>e[0][r]!==void 0).map(r=>e[0][r]):e[0],pt=e=>{if(e.length<2)return null;const t=e.length-1;return S(e[t])=="string"?e[t].toLowerCase():null},{PI:mt,min:Zt,max:Jt}=Math,we=mt*2,Wt=mt/3,Ac=mt/180,Lc=180/mt,L={format:{},autodetect:[]};let C=class{constructor(...t){const r=this;if(S(t[0])==="object"&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];let n=pt(t),o=!1;if(!n){o=!0,L.sorted||(L.autodetect=L.autodetect.sort((a,s)=>s.p-a.p),L.sorted=!0);for(let a of L.autodetect)if(n=a.test(...t),n)break}if(L.format[n]){const a=L.format[n].apply(null,o?t:t.slice(0,-1));r._rgb=Yt(a)}else throw new Error("unknown format: "+t);r._rgb.length===3&&r._rgb.push(1)}toString(){return S(this.hex)=="function"?this.hex():`[${this._rgb.join(",")}]`}};const Ec="2.6.0",O=(...e)=>new O.Color(...e);O.Color=C,O.version=Ec;const Tc=(...e)=>{e=P(e,"cmyk");const[t,r,n,o]=e,a=e.length>4?e[4]:1;return o===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-o),r>=1?0:255*(1-r)*(1-o),n>=1?0:255*(1-n)*(1-o),a]},{max:io}=Math,Sc=(...e)=>{let[t,r,n]=P(e,"rgb");t=t/255,r=r/255,n=n/255;const o=1-io(t,io(r,n)),a=o<1?1/(1-o):0,s=(1-t-o)*a,c=(1-r-o)*a,i=(1-n-o)*a;return[s,c,i,o]};C.prototype.cmyk=function(){return Sc(this._rgb)},O.cmyk=(...e)=>new C(...e,"cmyk"),L.format.cmyk=Tc,L.autodetect.push({p:2,test:(...e)=>{if(e=P(e,"cmyk"),S(e)==="array"&&e.length===4)return"cmyk"}});const Ut=e=>Math.round(e*100)/100,Pc=(...e)=>{const t=P(e,"hsla");let r=pt(e)||"lsa";return t[0]=Ut(t[0]||0),t[1]=Ut(t[1]*100)+"%",t[2]=Ut(t[2]*100)+"%",r==="hsla"||t.length>3&&t[3]<1?(t[3]=t.length>3?t[3]:1,r="hsla"):t.length=3,`${r}(${t.join(",")})`},uo=(...e)=>{e=P(e,"rgba");let[t,r,n]=e;t/=255,r/=255,n/=255;const o=Zt(t,r,n),a=Jt(t,r,n),s=(a+o)/2;let c,i;return a===o?(c=0,i=Number.NaN):c=s<.5?(a-o)/(a+o):(a-o)/(2-a-o),t==a?i=(r-n)/(a-o):r==a?i=2+(n-t)/(a-o):n==a&&(i=4+(t-r)/(a-o)),i*=60,i<0&&(i+=360),e.length>3&&e[3]!==void 0?[i,c,s,e[3]]:[i,c,s]},{round:Qt}=Math,jc=(...e)=>{const t=P(e,"rgba");let r=pt(e)||"rgb";return r.substr(0,3)=="hsl"?Pc(uo(t),r):(t[0]=Qt(t[0]),t[1]=Qt(t[1]),t[2]=Qt(t[2]),(r==="rgba"||t.length>3&&t[3]<1)&&(t[3]=t.length>3?t[3]:1,r="rgba"),`${r}(${t.slice(0,r==="rgb"?3:4).join(",")})`)},{round:er}=Math,tr=(...e)=>{e=P(e,"hsl");const[t,r,n]=e;let o,a,s;if(r===0)o=a=s=n*255;else{const c=[0,0,0],i=[0,0,0],u=n<.5?n*(1+r):n+r-n*r,f=2*n-u,l=t/360;c[0]=l+1/3,c[1]=l,c[2]=l-1/3;for(let h=0;h<3;h++)c[h]<0&&(c[h]+=1),c[h]>1&&(c[h]-=1),6*c[h]<1?i[h]=f+(u-f)*6*c[h]:2*c[h]<1?i[h]=u:3*c[h]<2?i[h]=f+(u-f)*(2/3-c[h])*6:i[h]=f;[o,a,s]=[er(i[0]*255),er(i[1]*255),er(i[2]*255)]}return e.length>3?[o,a,s,e[3]]:[o,a,s,1]},fo=/^rgb\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*\)$/,lo=/^rgba\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*([01]|[01]?\.\d+)\)$/,ho=/^rgb\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,bo=/^rgba\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,po=/^hsl\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,mo=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,{round:go}=Math,rr=e=>{e=e.toLowerCase().trim();let t;if(L.format.named)try{return L.format.named(e)}catch{}if(t=e.match(fo)){const r=t.slice(1,4);for(let n=0;n<3;n++)r[n]=+r[n];return r[3]=1,r}if(t=e.match(lo)){const r=t.slice(1,5);for(let n=0;n<4;n++)r[n]=+r[n];return r}if(t=e.match(ho)){const r=t.slice(1,4);for(let n=0;n<3;n++)r[n]=go(r[n]*2.55);return r[3]=1,r}if(t=e.match(bo)){const r=t.slice(1,5);for(let n=0;n<3;n++)r[n]=go(r[n]*2.55);return r[3]=+r[3],r}if(t=e.match(po)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=tr(r);return n[3]=1,n}if(t=e.match(mo)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=tr(r);return n[3]=+t[4],n}};rr.test=e=>fo.test(e)||lo.test(e)||ho.test(e)||bo.test(e)||po.test(e)||mo.test(e),C.prototype.css=function(e){return jc(this._rgb,e)},O.css=(...e)=>new C(...e,"css"),L.format.css=rr,L.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&S(e)==="string"&&rr.test(e))return"css"}}),L.format.gl=(...e)=>{const t=P(e,"rgba");return t[0]*=255,t[1]*=255,t[2]*=255,t},O.gl=(...e)=>new C(...e,"gl"),C.prototype.gl=function(){const e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]};const{floor:Bc}=Math,Gc=(...e)=>{e=P(e,"hcg");let[t,r,n]=e,o,a,s;n=n*255;const c=r*255;if(r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const i=Bc(t),u=t-i,f=n*(1-r),l=f+c*(1-u),h=f+c*u,d=f+c;switch(i){case 0:[o,a,s]=[d,h,f];break;case 1:[o,a,s]=[l,d,f];break;case 2:[o,a,s]=[f,d,h];break;case 3:[o,a,s]=[f,l,d];break;case 4:[o,a,s]=[h,f,d];break;case 5:[o,a,s]=[d,f,l];break}}return[o,a,s,e.length>3?e[3]:1]},Ic=(...e)=>{const[t,r,n]=P(e,"rgb"),o=Zt(t,r,n),a=Jt(t,r,n),s=a-o,c=s*100/255,i=o/(255-s)*100;let u;return s===0?u=Number.NaN:(t===a&&(u=(r-n)/s),r===a&&(u=2+(n-t)/s),n===a&&(u=4+(t-r)/s),u*=60,u<0&&(u+=360)),[u,c,i]};C.prototype.hcg=function(){return Ic(this._rgb)},O.hcg=(...e)=>new C(...e,"hcg"),L.format.hcg=Gc,L.autodetect.push({p:1,test:(...e)=>{if(e=P(e,"hcg"),S(e)==="array"&&e.length===3)return"hcg"}});const zc=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,Fc=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,vo=e=>{if(e.match(zc)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const t=parseInt(e,16),r=t>>16,n=t>>8&255,o=t&255;return[r,n,o,1]}if(e.match(Fc)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);const t=parseInt(e,16),r=t>>24&255,n=t>>16&255,o=t>>8&255,a=Math.round((t&255)/255*100)/100;return[r,n,o,a]}throw new Error(`unknown hex color: ${e}`)},{round:gt}=Math,_o=(...e)=>{let[t,r,n,o]=P(e,"rgba"),a=pt(e)||"auto";o===void 0&&(o=1),a==="auto"&&(a=o<1?"rgba":"rgb"),t=gt(t),r=gt(r),n=gt(n);let c="000000"+(t<<16|r<<8|n).toString(16);c=c.substr(c.length-6);let i="0"+gt(o*255).toString(16);switch(i=i.substr(i.length-2),a.toLowerCase()){case"rgba":return`#${c}${i}`;case"argb":return`#${i}${c}`;default:return`#${c}`}};C.prototype.hex=function(e){return _o(this._rgb,e)},O.hex=(...e)=>new C(...e,"hex"),L.format.hex=vo,L.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&S(e)==="string"&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return"hex"}});const{cos:Ke}=Math,Xc=(...e)=>{e=P(e,"hsi");let[t,r,n]=e,o,a,s;return isNaN(t)&&(t=0),isNaN(r)&&(r=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(s=(1-r)/3,o=(1+r*Ke(we*t)/Ke(Wt-we*t))/3,a=1-(s+o)):t<2/3?(t-=1/3,o=(1-r)/3,a=(1+r*Ke(we*t)/Ke(Wt-we*t))/3,s=1-(o+a)):(t-=2/3,a=(1-r)/3,s=(1+r*Ke(we*t)/Ke(Wt-we*t))/3,o=1-(a+s)),o=Xe(n*o*3),a=Xe(n*a*3),s=Xe(n*s*3),[o*255,a*255,s*255,e.length>3?e[3]:1]},{min:Kc,sqrt:Dc,acos:Vc}=Math,Yc=(...e)=>{let[t,r,n]=P(e,"rgb");t/=255,r/=255,n/=255;let o;const a=Kc(t,r,n),s=(t+r+n)/3,c=s>0?1-a/s:0;return c===0?o=NaN:(o=(t-r+(t-n))/2,o/=Dc((t-r)*(t-r)+(t-n)*(r-n)),o=Vc(o),n>r&&(o=we-o),o/=we),[o*360,c,s]};C.prototype.hsi=function(){return Yc(this._rgb)},O.hsi=(...e)=>new C(...e,"hsi"),L.format.hsi=Xc,L.autodetect.push({p:2,test:(...e)=>{if(e=P(e,"hsi"),S(e)==="array"&&e.length===3)return"hsi"}}),C.prototype.hsl=function(){return uo(this._rgb)},O.hsl=(...e)=>new C(...e,"hsl"),L.format.hsl=tr,L.autodetect.push({p:2,test:(...e)=>{if(e=P(e,"hsl"),S(e)==="array"&&e.length===3)return"hsl"}});const{floor:Zc}=Math,Jc=(...e)=>{e=P(e,"hsv");let[t,r,n]=e,o,a,s;if(n*=255,r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const c=Zc(t),i=t-c,u=n*(1-r),f=n*(1-r*i),l=n*(1-r*(1-i));switch(c){case 0:[o,a,s]=[n,l,u];break;case 1:[o,a,s]=[f,n,u];break;case 2:[o,a,s]=[u,n,l];break;case 3:[o,a,s]=[u,f,n];break;case 4:[o,a,s]=[l,u,n];break;case 5:[o,a,s]=[n,u,f];break}}return[o,a,s,e.length>3?e[3]:1]},{min:Wc,max:Uc}=Math,Qc=(...e)=>{e=P(e,"rgb");let[t,r,n]=e;const o=Wc(t,r,n),a=Uc(t,r,n),s=a-o;let c,i,u;return u=a/255,a===0?(c=Number.NaN,i=0):(i=s/a,t===a&&(c=(r-n)/s),r===a&&(c=2+(n-t)/s),n===a&&(c=4+(t-r)/s),c*=60,c<0&&(c+=360)),[c,i,u]};C.prototype.hsv=function(){return Qc(this._rgb)},O.hsv=(...e)=>new C(...e,"hsv"),L.format.hsv=Jc,L.autodetect.push({p:2,test:(...e)=>{if(e=P(e,"hsv"),S(e)==="array"&&e.length===3)return"hsv"}});const se={Kn:18,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452},{pow:e0}=Math,yo=(...e)=>{e=P(e,"lab");const[t,r,n]=e;let o,a,s,c,i,u;return a=(t+16)/116,o=isNaN(r)?a:a+r/500,s=isNaN(n)?a:a-n/200,a=se.Yn*or(a),o=se.Xn*or(o),s=se.Zn*or(s),c=nr(3.2404542*o-1.5371385*a-.4985314*s),i=nr(-.969266*o+1.8760108*a+.041556*s),u=nr(.0556434*o-.2040259*a+1.0572252*s),[c,i,u,e.length>3?e[3]:1]},nr=e=>255*(e<=.00304?12.92*e:1.055*e0(e,1/2.4)-.055),or=e=>e>se.t1?e*e*e:se.t2*(e-se.t0),{pow:wo}=Math,ko=(...e)=>{const[t,r,n]=P(e,"rgb"),[o,a,s]=t0(t,r,n),c=116*a-16;return[c<0?0:c,500*(o-a),200*(a-s)]},sr=e=>(e/=255)<=.04045?e/12.92:wo((e+.055)/1.055,2.4),ar=e=>e>se.t3?wo(e,1/3):e/se.t2+se.t0,t0=(e,t,r)=>{e=sr(e),t=sr(t),r=sr(r);const n=ar((.4124564*e+.3575761*t+.1804375*r)/se.Xn),o=ar((.2126729*e+.7151522*t+.072175*r)/se.Yn),a=ar((.0193339*e+.119192*t+.9503041*r)/se.Zn);return[n,o,a]};C.prototype.lab=function(){return ko(this._rgb)},O.lab=(...e)=>new C(...e,"lab"),L.format.lab=yo,L.autodetect.push({p:2,test:(...e)=>{if(e=P(e,"lab"),S(e)==="array"&&e.length===3)return"lab"}});const{sin:r0,cos:n0}=Math,$o=(...e)=>{let[t,r,n]=P(e,"lch");return isNaN(n)&&(n=0),n=n*Ac,[t,n0(n)*r,r0(n)*r]},Co=(...e)=>{e=P(e,"lch");const[t,r,n]=e,[o,a,s]=$o(t,r,n),[c,i,u]=yo(o,a,s);return[c,i,u,e.length>3?e[3]:1]},o0=(...e)=>{const t=P(e,"hcl").reverse();return Co(...t)},{sqrt:s0,atan2:a0,round:c0}=Math,xo=(...e)=>{const[t,r,n]=P(e,"lab"),o=s0(r*r+n*n);let a=(a0(n,r)*Lc+360)%360;return c0(o*1e4)===0&&(a=Number.NaN),[t,o,a]},Ro=(...e)=>{const[t,r,n]=P(e,"rgb"),[o,a,s]=ko(t,r,n);return xo(o,a,s)};C.prototype.lch=function(){return Ro(this._rgb)},C.prototype.hcl=function(){return Ro(this._rgb).reverse()},O.lch=(...e)=>new C(...e,"lch"),O.hcl=(...e)=>new C(...e,"hcl"),L.format.lch=Co,L.format.hcl=o0,["lch","hcl"].forEach(e=>L.autodetect.push({p:2,test:(...t)=>{if(t=P(t,e),S(t)==="array"&&t.length===3)return e}}));const De={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};C.prototype.name=function(){const e=_o(this._rgb,"rgb");for(let t of Object.keys(De))if(De[t]===e)return t.toLowerCase();return e},L.format.named=e=>{if(e=e.toLowerCase(),De[e])return vo(De[e]);throw new Error("unknown color name: "+e)},L.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&S(e)==="string"&&De[e.toLowerCase()])return"named"}});const i0=e=>{if(S(e)=="number"&&e>=0&&e<=16777215){const t=e>>16,r=e>>8&255,n=e&255;return[t,r,n,1]}throw new Error("unknown num color: "+e)},u0=(...e)=>{const[t,r,n]=P(e,"rgb");return(t<<16)+(r<<8)+n};C.prototype.num=function(){return u0(this._rgb)},O.num=(...e)=>new C(...e,"num"),L.format.num=i0,L.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&S(e[0])==="number"&&e[0]>=0&&e[0]<=16777215)return"num"}});const{round:Ho}=Math;C.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Ho)},C.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,r)=>r<3?e===!1?t:Ho(t):t)},O.rgb=(...e)=>new C(...e,"rgb"),L.format.rgb=(...e)=>{const t=P(e,"rgba");return t[3]===void 0&&(t[3]=1),t},L.autodetect.push({p:3,test:(...e)=>{if(e=P(e,"rgba"),S(e)==="array"&&(e.length===3||e.length===4&&S(e[3])=="number"&&e[3]>=0&&e[3]<=1))return"rgb"}});const{log:vt}=Math,qo=e=>{const t=e/100;let r,n,o;return t<66?(r=255,n=t<6?0:-155.25485562709179-.44596950469579133*(n=t-2)+104.49216199393888*vt(n),o=t<20?0:-254.76935184120902+.8274096064007395*(o=t-10)+115.67994401066147*vt(o)):(r=351.97690566805693+.114206453784165*(r=t-55)-40.25366309332127*vt(r),n=325.4494125711974+.07943456536662342*(n=t-50)-28.0852963507957*vt(n),o=255),[r,n,o,1]},{round:f0}=Math,l0=(...e)=>{const t=P(e,"rgb"),r=t[0],n=t[2];let o=1e3,a=4e4;const s=.4;let c;for(;a-o>s;){c=(a+o)*.5;const i=qo(c);i[2]/i[0]>=n/r?a=c:o=c}return f0(c)};C.prototype.temp=C.prototype.kelvin=C.prototype.temperature=function(){return l0(this._rgb)},O.temp=O.kelvin=O.temperature=(...e)=>new C(...e,"temp"),L.format.temp=L.format.kelvin=L.format.temperature=qo;const{pow:_t,sign:h0}=Math,Mo=(...e)=>{e=P(e,"lab");const[t,r,n]=e,o=_t(t+.3963377774*r+.2158037573*n,3),a=_t(t-.1055613458*r-.0638541728*n,3),s=_t(t-.0894841775*r-1.291485548*n,3);return[255*cr(4.0767416621*o-3.3077115913*a+.2309699292*s),255*cr(-1.2684380046*o+2.6097574011*a-.3413193965*s),255*cr(-.0041960863*o-.7034186147*a+1.707614701*s),e.length>3?e[3]:1]};function cr(e){const t=Math.abs(e);return t>.0031308?(h0(e)||1)*(1.055*_t(t,.4166666666666667)-.055):e*12.92}const{cbrt:ir,pow:d0,sign:b0}=Math,Oo=(...e)=>{const[t,r,n]=P(e,"rgb"),[o,a,s]=[ur(t/255),ur(r/255),ur(n/255)],c=ir(.4122214708*o+.5363325363*a+.0514459929*s),i=ir(.2119034982*o+.6806995451*a+.1073969566*s),u=ir(.0883024619*o+.2817188376*a+.6299787005*s);return[.2104542553*c+.793617785*i-.0040720468*u,1.9779984951*c-2.428592205*i+.4505937099*u,.0259040371*c+.7827717662*i-.808675766*u]};function ur(e){const t=Math.abs(e);return t<.04045?e/12.92:(b0(e)||1)*d0((t+.055)/1.055,2.4)}C.prototype.oklab=function(){return Oo(this._rgb)},O.oklab=(...e)=>new C(...e,"oklab"),L.format.oklab=Mo,L.autodetect.push({p:3,test:(...e)=>{if(e=P(e,"oklab"),S(e)==="array"&&e.length===3)return"oklab"}});const p0=(...e)=>{e=P(e,"lch");const[t,r,n]=e,[o,a,s]=$o(t,r,n),[c,i,u]=Mo(o,a,s);return[c,i,u,e.length>3?e[3]:1]},m0=(...e)=>{const[t,r,n]=P(e,"rgb"),[o,a,s]=Oo(t,r,n);return xo(o,a,s)};C.prototype.oklch=function(){return m0(this._rgb)},O.oklch=(...e)=>new C(...e,"oklch"),L.format.oklch=p0,L.autodetect.push({p:3,test:(...e)=>{if(e=P(e,"oklch"),S(e)==="array"&&e.length===3)return"oklch"}}),C.prototype.alpha=function(e,t=!1){return e!==void 0&&S(e)==="number"?t?(this._rgb[3]=e,this):new C([this._rgb[0],this._rgb[1],this._rgb[2],e],"rgb"):this._rgb[3]},C.prototype.clipped=function(){return this._rgb._clipped||!1},C.prototype.darken=function(e=1){const t=this,r=t.lab();return r[0]-=se.Kn*e,new C(r,"lab").alpha(t.alpha(),!0)},C.prototype.brighten=function(e=1){return this.darken(-e)},C.prototype.darker=C.prototype.darken,C.prototype.brighter=C.prototype.brighten,C.prototype.get=function(e){const[t,r]=e.split("."),n=this[t]();if(r){const o=t.indexOf(r)-(t.substr(0,2)==="ok"?2:0);if(o>-1)return n[o];throw new Error(`unknown channel ${r} in mode ${t}`)}else return n};const{pow:g0}=Math,v0=1e-7,_0=20;C.prototype.luminance=function(e,t="rgb"){if(e!==void 0&&S(e)==="number"){if(e===0)return new C([0,0,0,this._rgb[3]],"rgb");if(e===1)return new C([255,255,255,this._rgb[3]],"rgb");let r=this.luminance(),n=_0;const o=(s,c)=>{const i=s.interpolate(c,.5,t),u=i.luminance();return Math.abs(e-u)e?o(s,i):o(i,c)},a=(r>e?o(new C([0,0,0]),this):o(this,new C([255,255,255]))).rgb();return new C([...a,this._rgb[3]])}return y0(...this._rgb.slice(0,3))};const y0=(e,t,r)=>(e=fr(e),t=fr(t),r=fr(r),.2126*e+.7152*t+.0722*r),fr=e=>(e/=255,e<=.03928?e/12.92:g0((e+.055)/1.055,2.4)),re={},ct=(e,t,r=.5,...n)=>{let o=n[0]||"lrgb";if(!re[o]&&!n.length&&(o=Object.keys(re)[0]),!re[o])throw new Error(`interpolation mode ${o} is not defined`);return S(e)!=="object"&&(e=new C(e)),S(t)!=="object"&&(t=new C(t)),re[o](e,t,r).alpha(e.alpha()+r*(t.alpha()-e.alpha()))};C.prototype.mix=C.prototype.interpolate=function(e,t=.5,...r){return ct(this,e,t,...r)},C.prototype.premultiply=function(e=!1){const t=this._rgb,r=t[3];return e?(this._rgb=[t[0]*r,t[1]*r,t[2]*r,r],this):new C([t[0]*r,t[1]*r,t[2]*r,r],"rgb")},C.prototype.saturate=function(e=1){const t=this,r=t.lch();return r[1]+=se.Kn*e,r[1]<0&&(r[1]=0),new C(r,"lch").alpha(t.alpha(),!0)},C.prototype.desaturate=function(e=1){return this.saturate(-e)},C.prototype.set=function(e,t,r=!1){const[n,o]=e.split("."),a=this[n]();if(o){const s=n.indexOf(o)-(n.substr(0,2)==="ok"?2:0);if(s>-1){if(S(t)=="string")switch(t.charAt(0)){case"+":a[s]+=+t;break;case"-":a[s]+=+t;break;case"*":a[s]*=+t.substr(1);break;case"/":a[s]/=+t.substr(1);break;default:a[s]=+t}else if(S(t)==="number")a[s]=t;else throw new Error("unsupported value for Color.set");const c=new C(a,n);return r?(this._rgb=c._rgb,this):c}throw new Error(`unknown channel ${o} in mode ${n}`)}else return a},C.prototype.tint=function(e=.5,...t){return ct(this,"white",e,...t)},C.prototype.shade=function(e=.5,...t){return ct(this,"black",e,...t)};const w0=(e,t,r)=>{const n=e._rgb,o=t._rgb;return new C(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"rgb")};re.rgb=w0;const{sqrt:lr,pow:Ve}=Math,k0=(e,t,r)=>{const[n,o,a]=e._rgb,[s,c,i]=t._rgb;return new C(lr(Ve(n,2)*(1-r)+Ve(s,2)*r),lr(Ve(o,2)*(1-r)+Ve(c,2)*r),lr(Ve(a,2)*(1-r)+Ve(i,2)*r),"rgb")};re.lrgb=k0;const $0=(e,t,r)=>{const n=e.lab(),o=t.lab();return new C(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"lab")};re.lab=$0;const Ye=(e,t,r,n)=>{let o,a;n==="hsl"?(o=e.hsl(),a=t.hsl()):n==="hsv"?(o=e.hsv(),a=t.hsv()):n==="hcg"?(o=e.hcg(),a=t.hcg()):n==="hsi"?(o=e.hsi(),a=t.hsi()):n==="lch"||n==="hcl"?(n="hcl",o=e.hcl(),a=t.hcl()):n==="oklch"&&(o=e.oklch().reverse(),a=t.oklch().reverse());let s,c,i,u,f,l;(n.substr(0,1)==="h"||n==="oklch")&&([s,i,f]=o,[c,u,l]=a);let h,d,p,v;return!isNaN(s)&&!isNaN(c)?(c>s&&c-s>180?v=c-(s+360):c180?v=c+360-s:v=c-s,d=s+r*v):isNaN(s)?isNaN(c)?d=Number.NaN:(d=c,(f==1||f==0)&&n!="hsv"&&(h=u)):(d=s,(l==1||l==0)&&n!="hsv"&&(h=i)),h===void 0&&(h=i+r*(u-i)),p=f+r*(l-f),n==="oklch"?new C([p,h,d],n):new C([d,h,p],n)},No=(e,t,r)=>Ye(e,t,r,"lch");re.lch=No,re.hcl=No;const C0=(e,t,r)=>{const n=e.num(),o=t.num();return new C(n+r*(o-n),"num")};re.num=C0;const x0=(e,t,r)=>Ye(e,t,r,"hcg");re.hcg=x0;const R0=(e,t,r)=>Ye(e,t,r,"hsi");re.hsi=R0;const H0=(e,t,r)=>Ye(e,t,r,"hsl");re.hsl=H0;const q0=(e,t,r)=>Ye(e,t,r,"hsv");re.hsv=q0;const M0=(e,t,r)=>{const n=e.oklab(),o=t.oklab();return new C(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"oklab")};re.oklab=M0;const O0=(e,t,r)=>Ye(e,t,r,"oklch");re.oklch=O0;const{pow:hr,sqrt:dr,PI:br,cos:Ao,sin:Lo,atan2:N0}=Math,A0=(e,t="lrgb",r=null)=>{const n=e.length;r||(r=Array.from(new Array(n)).map(()=>1));const o=n/r.reduce(function(l,h){return l+h});if(r.forEach((l,h)=>{r[h]*=o}),e=e.map(l=>new C(l)),t==="lrgb")return L0(e,r);const a=e.shift(),s=a.get(t),c=[];let i=0,u=0;for(let l=0;l{const d=l.get(t);f+=l.alpha()*r[h+1];for(let p=0;p=360;)h-=360;s[l]=h}else s[l]=s[l]/c[l];return f/=n,new C(s,t).alpha(f>.99999?1:f,!0)},L0=(e,t)=>{const r=e.length,n=[0,0,0,0];for(let o=0;o.9999999&&(n[3]=1),new C(Yt(n))},{pow:E0}=Math;function yt(e){let t="rgb",r=O("#ccc"),n=0,o=[0,1],a=[],s=[0,0],c=!1,i=[],u=!1,f=0,l=1,h=!1,d={},p=!0,v=1;const m=function(b){if(b=b||["#fff","#000"],b&&S(b)==="string"&&O.brewer&&O.brewer[b.toLowerCase()]&&(b=O.brewer[b.toLowerCase()]),S(b)==="array"){b.length===1&&(b=[b[0],b[0]]),b=b.slice(0);for(let _=0;_=c[k];)k++;return k-1}return 0};let R=b=>b,x=b=>b;const M=function(b,_){let k,y;if(_==null&&(_=!1),isNaN(b)||b===null)return r;_?y=b:c&&c.length>2?y=g(b)/(c.length-2):l!==f?y=(b-f)/(l-f):y=1,y=x(y),_||(y=R(y)),v!==1&&(y=E0(y,v)),y=s[0]+y*(1-s[0]-s[1]),y=Xe(y,0,1);const q=Math.floor(y*1e4);if(p&&d[q])k=d[q];else{if(S(i)==="array")for(let H=0;H=A&&H===a.length-1){k=i[H];break}if(y>A&&yd={};m(e);const w=function(b){const _=O(M(b));return u&&_[u]?_[u]():_};return w.classes=function(b){if(b!=null){if(S(b)==="array")c=b,o=[b[0],b[b.length-1]];else{const _=O.analyze(o);b===0?c=[_.min,_.max]:c=O.limits(_,"e",b)}return w}return c},w.domain=function(b){if(!arguments.length)return o;f=b[0],l=b[b.length-1],a=[];const _=i.length;if(b.length===_&&f!==l)for(let k of Array.from(b))a.push((k-f)/(l-f));else{for(let k=0;k<_;k++)a.push(k/(_-1));if(b.length>2){const k=b.map((q,H)=>H/(b.length-1)),y=b.map(q=>(q-f)/(l-f));y.every((q,H)=>k[H]===q)||(x=q=>{if(q<=0||q>=1)return q;let H=0;for(;q>=y[H+1];)H++;const A=(q-y[H])/(y[H+1]-y[H]);return k[H]+A*(k[H+1]-k[H])})}}return o=[f,l],w},w.mode=function(b){return arguments.length?(t=b,N(),w):t},w.range=function(b,_){return m(b),w},w.out=function(b){return u=b,w},w.spread=function(b){return arguments.length?(n=b,w):n},w.correctLightness=function(b){return b==null&&(b=!0),h=b,N(),h?R=function(_){const k=M(0,!0).lab()[0],y=M(1,!0).lab()[0],q=k>y;let H=M(_,!0).lab()[0];const A=k+(y-k)*_;let I=H-A,K=0,D=1,U=20;for(;Math.abs(I)>.01&&U-- >0;)(function(){return q&&(I*=-1),I<0?(K=_,_+=(D-_)*.5):(D=_,_+=(K-_)*.5),H=M(_,!0).lab()[0],I=H-A})();return _}:R=_=>_,w},w.padding=function(b){return b!=null?(S(b)==="number"&&(b=[b,b]),s=b,w):s},w.colors=function(b,_){arguments.length<2&&(_="hex");let k=[];if(arguments.length===0)k=i.slice(0);else if(b===1)k=[w(.5)];else if(b>1){const y=o[0],q=o[1]-y;k=T0(0,b).map(H=>w(y+H/(b-1)*q))}else{e=[];let y=[];if(c&&c.length>2)for(let q=1,H=c.length,A=1<=H;A?qH;A?q++:q--)y.push((c[q-1]+c[q])*.5);else y=o;k=y.map(q=>w(q))}return O[_]&&(k=k.map(y=>y[_]())),k},w.cache=function(b){return b!=null?(p=b,w):p},w.gamma=function(b){return b!=null?(v=b,w):v},w.nodata=function(b){return b!=null?(r=O(b),w):r},w}function T0(e,t,r){let n=[],o=ea;o?s++:s--)n.push(s);return n}const S0=function(e){let t=[1,1];for(let r=1;rnew C(a)),e.length===2)[r,n]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>r[c]+a*(n[c]-r[c]));return new C(s,"lab")};else if(e.length===3)[r,n,o]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>(1-a)*(1-a)*r[c]+2*(1-a)*a*n[c]+a*a*o[c]);return new C(s,"lab")};else if(e.length===4){let a;[r,n,o,a]=e.map(s=>s.lab()),t=function(s){const c=[0,1,2].map(i=>(1-s)*(1-s)*(1-s)*r[i]+3*(1-s)*(1-s)*s*n[i]+3*(1-s)*s*s*o[i]+s*s*s*a[i]);return new C(c,"lab")}}else if(e.length>=5){let a,s,c;a=e.map(i=>i.lab()),c=e.length-1,s=S0(c),t=function(i){const u=1-i,f=[0,1,2].map(l=>a.reduce((h,d,p)=>h+s[p]*u**(c-p)*i**p*d[l],0));return new C(f,"lab")}}else throw new RangeError("No point in running bezier with only one color.");return t},j0=e=>{const t=P0(e);return t.scale=()=>yt(t),t},he=(e,t,r)=>{if(!he[r])throw new Error("unknown blend mode "+r);return he[r](e,t)},Ne=e=>(t,r)=>{const n=O(r).rgb(),o=O(t).rgb();return O.rgb(e(n,o))},Ae=e=>(t,r)=>{const n=[];return n[0]=e(t[0],r[0]),n[1]=e(t[1],r[1]),n[2]=e(t[2],r[2]),n},B0=e=>e,G0=(e,t)=>e*t/255,I0=(e,t)=>e>t?t:e,z0=(e,t)=>e>t?e:t,F0=(e,t)=>255*(1-(1-e/255)*(1-t/255)),X0=(e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)),K0=(e,t)=>255*(1-(1-t/255)/(e/255)),D0=(e,t)=>e===255?255:(e=255*(t/255)/(1-e/255),e>255?255:e);he.normal=Ne(Ae(B0)),he.multiply=Ne(Ae(G0)),he.screen=Ne(Ae(F0)),he.overlay=Ne(Ae(X0)),he.darken=Ne(Ae(I0)),he.lighten=Ne(Ae(z0)),he.dodge=Ne(Ae(D0)),he.burn=Ne(Ae(K0));const{pow:V0,sin:Y0,cos:Z0}=Math;function J0(e=300,t=-1.5,r=1,n=1,o=[0,1]){let a=0,s;S(o)==="array"?s=o[1]-o[0]:(s=0,o=[o,o]);const c=function(i){const u=we*((e+120)/360+t*i),f=V0(o[0]+s*i,n),h=(a!==0?r[0]+i*a:r)*f*(1-f)/2,d=Z0(u),p=Y0(u),v=f+h*(-.14861*d+1.78277*p),m=f+h*(-.29227*d-.90649*p),g=f+h*(1.97294*d);return O(Yt([v*255,m*255,g*255,1]))};return c.start=function(i){return i==null?e:(e=i,c)},c.rotations=function(i){return i==null?t:(t=i,c)},c.gamma=function(i){return i==null?n:(n=i,c)},c.hue=function(i){return i==null?r:(r=i,S(r)==="array"?(a=r[1]-r[0],a===0&&(r=r[1])):a=0,c)},c.lightness=function(i){return i==null?o:(S(i)==="array"?(o=i,s=i[1]-i[0]):(o=[i,i],s=0),c)},c.scale=()=>O.scale(c),c.hue(r),c}const W0="0123456789abcdef",{floor:U0,random:Q0}=Math,ei=()=>{let e="#";for(let t=0;t<6;t++)e+=W0.charAt(U0(Q0()*16));return new C(e,"hex")},{log:Eo,pow:ti,floor:ri,abs:ni}=Math;function To(e,t=null){const r={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return S(e)==="object"&&(e=Object.values(e)),e.forEach(n=>{t&&S(n)==="object"&&(n=n[t]),n!=null&&!isNaN(n)&&(r.values.push(n),r.sum+=n,nr.max&&(r.max=n),r.count+=1)}),r.domain=[r.min,r.max],r.limits=(n,o)=>So(r,n,o),r}function So(e,t="equal",r=7){S(e)=="array"&&(e=To(e));const{min:n,max:o}=e,a=e.values.sort((c,i)=>c-i);if(r===1)return[n,o];const s=[];if(t.substr(0,1)==="c"&&(s.push(n),s.push(o)),t.substr(0,1)==="e"){s.push(n);for(let c=1;c 0");const c=Math.LOG10E*Eo(n),i=Math.LOG10E*Eo(o);s.push(n);for(let u=1;u200&&(l=!1)}const p={};for(let m=0;mm-g),s.push(v[0]);for(let m=1;m{e=new C(e),t=new C(t);const r=e.luminance(),n=t.luminance();return r>n?(r+.05)/(n+.05):(n+.05)/(r+.05)},{sqrt:ke,pow:V,min:si,max:ai,atan2:Po,abs:jo,cos:wt,sin:Bo,exp:ci,PI:Go}=Math;function ii(e,t,r=1,n=1,o=1){var a=function(le){return 360*le/(2*Go)},s=function(le){return 2*Go*le/360};e=new C(e),t=new C(t);const[c,i,u]=Array.from(e.lab()),[f,l,h]=Array.from(t.lab()),d=(c+f)/2,p=ke(V(i,2)+V(u,2)),v=ke(V(l,2)+V(h,2)),m=(p+v)/2,g=.5*(1-ke(V(m,7)/(V(m,7)+V(25,7)))),R=i*(1+g),x=l*(1+g),M=ke(V(R,2)+V(u,2)),N=ke(V(x,2)+V(h,2)),w=(M+N)/2,b=a(Po(u,R)),_=a(Po(h,x)),k=b>=0?b:b+360,y=_>=0?_:_+360,q=jo(k-y)>180?(k+y+360)/2:(k+y)/2,H=1-.17*wt(s(q-30))+.24*wt(s(2*q))+.32*wt(s(3*q+6))-.2*wt(s(4*q-63));let A=y-k;A=jo(A)<=180?A:y<=k?A+360:A-360,A=2*ke(M*N)*Bo(s(A)/2);const I=f-c,K=N-M,D=1+.015*V(d-50,2)/ke(20+V(d-50,2)),U=1+.045*w,ge=1+.015*w*H,ye=30*ci(-V((q-275)/25,2)),fe=-(2*ke(V(w,7)/(V(w,7)+V(25,7))))*Bo(2*s(ye)),qe=ke(V(I/(r*D),2)+V(K/(n*U),2)+V(A/(o*ge),2)+fe*(K/(n*U))*(A/(o*ge)));return ai(0,si(100,qe))}function ui(e,t,r="lab"){e=new C(e),t=new C(t);const n=e.get(r),o=t.get(r);let a=0;for(let s in n){const c=(n[s]||0)-(o[s]||0);a+=c*c}return Math.sqrt(a)}const fi=(...e)=>{try{return new C(...e),!0}catch{return!1}},li={cool(){return yt([O.hsl(180,1,.9),O.hsl(250,.7,.4)])},hot(){return yt(["#000","#f00","#ff0","#fff"]).mode("rgb")}},kt={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]};for(let e of Object.keys(kt))kt[e.toLowerCase()]=kt[e];Object.assign(O,{average:A0,bezier:j0,blend:he,cubehelix:J0,mix:ct,interpolate:ct,random:ei,scale:yt,analyze:To,contrast:oi,deltaE:ii,distance:ui,limits:So,valid:fi,scales:li,input:L,colors:De,brewer:kt});function pr(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var mr,Io;function hi(){if(Io)return mr;Io=1;var e=e||{};e.Geometry=function(){},e.Geometry.intersectLineLine=function(r,n){var o=(r.intercept-n.intercept)/(n.slope-r.slope),a=r.slope*o+r.intercept;return{x:o,y:a}},e.Geometry.distanceFromOrigin=function(r){return Math.sqrt(Math.pow(r.x,2)+Math.pow(r.y,2))},e.Geometry.distanceLineFromOrigin=function(r){return Math.abs(r.intercept)/Math.sqrt(Math.pow(r.slope,2)+1)},e.Geometry.perpendicularThroughPoint=function(r,n){var o=-1/r.slope,a=n.y-o*n.x;return{slope:o,intercept:a}},e.Geometry.angleFromOrigin=function(r){return Math.atan2(r.y,r.x)},e.Geometry.normalizeAngle=function(r){var n=2*Math.PI;return(r%n+n)%n},e.Geometry.lengthOfRayUntilIntersect=function(r,n){return n.intercept/(Math.sin(r)-n.slope*Math.cos(r))},e.Hsluv=function(){},e.Hsluv.getBounds=function(r){for(var n=[],o=Math.pow(r+16,3)/1560896,a=o>e.Hsluv.epsilon?o:r/e.Hsluv.kappa,s=0;s<3;)for(var c=s++,i=e.Hsluv.m[c][0],u=e.Hsluv.m[c][1],f=e.Hsluv.m[c][2],l=0;l<2;){var h=l++,d=(284517*i-94839*f)*a,p=(838422*f+769860*u+731718*i)*r*a-769860*h*r,v=(632260*f-126452*u)*a+126452*h;n.push({slope:d/v,intercept:p/v})}return n},e.Hsluv.maxSafeChromaForL=function(r){for(var n=e.Hsluv.getBounds(r),o=1/0,a=0;a=0&&(s=Math.min(s,u))}return s},e.Hsluv.dotProduct=function(r,n){for(var o=0,a=0,s=r.length;a.04045?Math.pow((r+.055)/1.055,2.4):r/12.92},e.Hsluv.xyzToRgb=function(r){return[e.Hsluv.fromLinear(e.Hsluv.dotProduct(e.Hsluv.m[0],r)),e.Hsluv.fromLinear(e.Hsluv.dotProduct(e.Hsluv.m[1],r)),e.Hsluv.fromLinear(e.Hsluv.dotProduct(e.Hsluv.m[2],r))]},e.Hsluv.rgbToXyz=function(r){var n=[e.Hsluv.toLinear(r[0]),e.Hsluv.toLinear(r[1]),e.Hsluv.toLinear(r[2])];return[e.Hsluv.dotProduct(e.Hsluv.minv[0],n),e.Hsluv.dotProduct(e.Hsluv.minv[1],n),e.Hsluv.dotProduct(e.Hsluv.minv[2],n)]},e.Hsluv.yToL=function(r){return r<=e.Hsluv.epsilon?r/e.Hsluv.refY*e.Hsluv.kappa:116*Math.pow(r/e.Hsluv.refY,.3333333333333333)-16},e.Hsluv.lToY=function(r){return r<=8?e.Hsluv.refY*r/e.Hsluv.kappa:e.Hsluv.refY*Math.pow((r+16)/116,3)},e.Hsluv.xyzToLuv=function(r){var n=r[0],o=r[1],a=r[2],s=n+15*o+3*a,c=4*n,i=9*o;s!=0?(c/=s,i/=s):(c=NaN,i=NaN);var u=e.Hsluv.yToL(o);if(u==0)return[0,0,0];var f=13*u*(c-e.Hsluv.refU),l=13*u*(i-e.Hsluv.refV);return[u,f,l]},e.Hsluv.luvToXyz=function(r){var n=r[0],o=r[1],a=r[2];if(n==0)return[0,0,0];var s=o/(13*n)+e.Hsluv.refU,c=a/(13*n)+e.Hsluv.refV,i=e.Hsluv.lToY(n),u=0-9*i*s/((s-4)*c-s*c),f=(9*i-15*c*i-c*u)/(3*c);return[u,i,f]},e.Hsluv.luvToLch=function(r){var n=r[0],o=r[1],a=r[2],s=Math.sqrt(o*o+a*a),c;if(s<1e-8)c=0;else{var i=Math.atan2(a,o);c=i*180/Math.PI,c<0&&(c=360+c)}return[n,s,c]},e.Hsluv.lchToLuv=function(r){var n=r[0],o=r[1],a=r[2],s=a/360*2*Math.PI,c=Math.cos(s)*o,i=Math.sin(s)*o;return[n,c,i]},e.Hsluv.hsluvToLch=function(r){var n=r[0],o=r[1],a=r[2];if(a>99.9999999)return[100,0,n];if(a<1e-8)return[0,0,n];var s=e.Hsluv.maxChromaForLH(a,n),c=s/100*o;return[a,c,n]},e.Hsluv.lchToHsluv=function(r){var n=r[0],o=r[1],a=r[2];if(n>99.9999999)return[a,0,100];if(n<1e-8)return[a,0,0];var s=e.Hsluv.maxChromaForLH(n,a),c=o/s*100;return[a,c,n]},e.Hsluv.hpluvToLch=function(r){var n=r[0],o=r[1],a=r[2];if(a>99.9999999)return[100,0,n];if(a<1e-8)return[0,0,n];var s=e.Hsluv.maxSafeChromaForL(a),c=s/100*o;return[a,c,n]},e.Hsluv.lchToHpluv=function(r){var n=r[0],o=r[1],a=r[2];if(n>99.9999999)return[a,0,100];if(n<1e-8)return[a,0,0];var s=e.Hsluv.maxSafeChromaForL(n),c=o/s*100;return[a,c,n]},e.Hsluv.rgbToHex=function(r){for(var n="#",o=0;o<3;){var a=o++,s=r[a],c=Math.round(s*255),i=c%16,u=(c-i)/16|0;n+=e.Hsluv.hexChars.charAt(u)+e.Hsluv.hexChars.charAt(i)}return n},e.Hsluv.hexToRgb=function(r){r=r.toLowerCase();for(var n=[],o=0;o<3;){var a=o++,s=e.Hsluv.hexChars.indexOf(r.charAt(a*2+1)),c=e.Hsluv.hexChars.indexOf(r.charAt(a*2+2)),i=s*16+c;n.push(i/255)}return n},e.Hsluv.lchToRgb=function(r){return e.Hsluv.xyzToRgb(e.Hsluv.luvToXyz(e.Hsluv.lchToLuv(r)))},e.Hsluv.rgbToLch=function(r){return e.Hsluv.luvToLch(e.Hsluv.xyzToLuv(e.Hsluv.rgbToXyz(r)))},e.Hsluv.hsluvToRgb=function(r){return e.Hsluv.lchToRgb(e.Hsluv.hsluvToLch(r))},e.Hsluv.rgbToHsluv=function(r){return e.Hsluv.lchToHsluv(e.Hsluv.rgbToLch(r))},e.Hsluv.hpluvToRgb=function(r){return e.Hsluv.lchToRgb(e.Hsluv.hpluvToLch(r))},e.Hsluv.rgbToHpluv=function(r){return e.Hsluv.lchToHpluv(e.Hsluv.rgbToLch(r))},e.Hsluv.hsluvToHex=function(r){return e.Hsluv.rgbToHex(e.Hsluv.hsluvToRgb(r))},e.Hsluv.hpluvToHex=function(r){return e.Hsluv.rgbToHex(e.Hsluv.hpluvToRgb(r))},e.Hsluv.hexToHsluv=function(r){return e.Hsluv.rgbToHsluv(e.Hsluv.hexToRgb(r))},e.Hsluv.hexToHpluv=function(r){return e.Hsluv.rgbToHpluv(e.Hsluv.hexToRgb(r))},e.Hsluv.m=[[3.240969941904521,-1.537383177570093,-.498610760293],[-.96924363628087,1.87596750150772,.041555057407175],[.055630079696993,-.20397695888897,1.056971514242878]],e.Hsluv.minv=[[.41239079926595,.35758433938387,.18048078840183],[.21263900587151,.71516867876775,.072192315360733],[.019330818715591,.11919477979462,.95053215224966]],e.Hsluv.refY=1,e.Hsluv.refU=.19783000664283,e.Hsluv.refV=.46831999493879,e.Hsluv.kappa=903.2962962,e.Hsluv.epsilon=.0088564516,e.Hsluv.hexChars="0123456789abcdef";var t={hsluvToRgb:e.Hsluv.hsluvToRgb,rgbToHsluv:e.Hsluv.rgbToHsluv,hpluvToRgb:e.Hsluv.hpluvToRgb,rgbToHpluv:e.Hsluv.rgbToHpluv,hsluvToHex:e.Hsluv.hsluvToHex,hexToHsluv:e.Hsluv.hexToHsluv,hpluvToHex:e.Hsluv.hpluvToHex,hexToHpluv:e.Hsluv.hexToHpluv,lchToHpluv:e.Hsluv.lchToHpluv,hpluvToLch:e.Hsluv.hpluvToLch,lchToHsluv:e.Hsluv.lchToHsluv,hsluvToLch:e.Hsluv.hsluvToLch,lchToLuv:e.Hsluv.lchToLuv,luvToLch:e.Hsluv.luvToLch,xyzToLuv:e.Hsluv.xyzToLuv,luvToXyz:e.Hsluv.luvToXyz,xyzToRgb:e.Hsluv.xyzToRgb,rgbToXyz:e.Hsluv.rgbToXyz,lchToRgb:e.Hsluv.lchToRgb,rgbToLch:e.Hsluv.rgbToLch};return mr=t,mr}var di=hi();const gr=pr(di);var $t={exports:{}},vr,zo;function it(){if(zo)return vr;zo=1;function e(t,r){return Object.prototype.hasOwnProperty.call(t,r)}return vr=e,vr}var _r,Fo;function yr(){if(Fo)return _r;Fo=1;var e=it(),t,r;function n(){r=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],t=!0;for(var s in{toString:null})t=!1}function o(s,c,i){var u,f=0;t==null&&n();for(u in s)if(a(c,s,u,i)===!1)break;if(t)for(var l=s.constructor,h=!!l&&s===l.prototype;(u=r[f++])&&!((u!=="constructor"||!h&&e(s,u))&&s[u]!==Object.prototype[u]&&a(c,s,u,i)===!1););}function a(s,c,i,u){return s.call(u,c[i],i,c)}return _r=o,_r}var wr,Xo;function Ko(){if(Xo)return wr;Xo=1;var e=yr();function t(r){var n=[];return e(r,function(o,a){typeof o=="function"&&n.push(a)}),n.sort()}return wr=t,wr}var kr,Do;function ut(){if(Do)return kr;Do=1;function e(t,r,n){var o=t.length;r==null?r=0:r<0?r=Math.max(o+r,0):r=Math.min(r,o),n==null?n=o:n<0?n=Math.max(o+n,0):n=Math.min(n,o);for(var a=[];r1?n(arguments,1):e(a);r(c,function(i){a[i]=t(a[i],a)})}return Rr=o,Rr}var Hr,Jo;function Q(){if(Jo)return Hr;Jo=1;var e=it(),t=yr();function r(n,o,a){t(n,function(s,c){if(e(n,c))return o.call(a,n[c],c,n)})}return Hr=r,Hr}var qr,Wo;function mi(){if(Wo)return qr;Wo=1;function e(t){return t}return qr=e,qr}var Mr,Uo;function Qo(){if(Uo)return Mr;Uo=1;function e(t){return function(r){return r[t]}}return Mr=e,Mr}var Or,es;function Nr(){if(es)return Or;es=1;var e=/^\[object (.*)\]$/,t=Object.prototype.toString,r;function n(o){return o===null?"Null":o===r?"Undefined":e.exec(t.call(o))[1]}return Or=n,Or}var Ar,ts;function Lr(){if(ts)return Ar;ts=1;var e=Nr();function t(r,n){return e(r)===n}return Ar=t,Ar}var Er,rs;function gi(){if(rs)return Er;rs=1;var e=Lr(),t=Array.isArray||function(r){return e(r,"Array")};return Er=t,Er}var Tr,ns;function os(){if(ns)return Tr;ns=1;var e=Q(),t=gi();function r(s,c){for(var i=-1,u=s.length;++is&&(s=i,a=c);return a}return rn=t,rn}var nn,Ns;function on(){if(Ns)return nn;Ns=1;var e=Q();function t(r){var n=[];return e(r,function(o,a){n.push(o)}),n}return nn=t,nn}var sn,As;function Mi(){if(As)return sn;As=1;var e=qi(),t=on();function r(n,o){return e(t(n),o)}return sn=r,sn}var an,Ls;function Es(){if(Ls)return an;Ls=1;var e=Q();function t(n,o){for(var a=0,s=arguments.length,c;++a2;if(!t(n)&&!c)throw new Error("reduce of empty object with no initial value");return e(n,function(i,u,f){c?a=o.call(s,a,i,u,f):(a=i,c=!0)}),a}return yn=r,yn}var wn,Js;function Ii(){if(Js)return wn;Js=1;var e=_s(),t=Le();function r(n,o,a){return o=t(o,a),e(n,function(s,c,i){return!o(s,c,i)},a)}return wn=r,wn}var kn,Ws;function zi(){if(Ws)return kn;Ws=1;var e=Lr();function t(r){return e(r,"Function")}return kn=t,kn}var $n,Us;function Fi(){if(Us)return $n;Us=1;var e=zi();function t(r,n){var o=r[n];if(o!==void 0)return e(o)?o.call(r):o}return $n=t,$n}var Cn,Qs;function Xi(){if(Qs)return Cn;Qs=1;var e=Is();function t(r,n,o){var a=/^(.+)\.(.+)$/.exec(n);a?e(r,a[1])[a[2]]=o:r[n]=o}return Cn=t,Cn}var xn,ea;function Ki(){if(ea)return xn;ea=1;var e=xs();function t(r,n){if(e(r,n)){for(var o=n.split("."),a=o.pop();n=o.shift();)r=r[n];return delete r[a]}else return!0}return xn=t,xn}var Rn,ta;function Hn(){return ta||(ta=1,Rn={bindAll:pi(),contains:vi(),deepFillIn:_i(),deepMatches:os(),deepMixIn:yi(),equals:ki(),every:hs(),fillIn:$i(),filter:_s(),find:Ci(),flatten:xi(),forIn:yr(),forOwn:Q(),functions:Ko(),get:$s(),has:xs(),hasOwn:it(),keys:Ri(),map:qs(),matches:Hi(),max:Mi(),merge:Ai(),min:Ei(),mixIn:Es(),namespace:Is(),omit:Pi(),pick:ji(),pluck:Bi(),reduce:Gi(),reject:Ii(),result:Fi(),set:Xi(),size:Ys(),some:jr(),unset:Ki(),values:on()}),Rn}var ra;function na(){return ra||(ra=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Hn(),n={A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},o=(0,r.map)(n,function(a){var s=100*(a.x/a.y),c=100,i=100*(1-a.x-a.y)/a.y;return[s,c,i]});t.default=o,e.exports=t.default})($t,$t.exports)),$t.exports}var Ct={exports:{}},oa;function sa(){return oa||(oa=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Math,n=r.pow,o=r.sign,a=r.abs,s={decode:function(l){return l<=.04045?l/12.92:n((l+.055)/1.055,2.4)},encode:function(l){return l<=.0031308?12.92*l:1.055*n(l,1/2.4)-.055}},c={encode:function(l){return l<.001953125?16*l:n(l,1/1.8)},decode:function(l){return l<16*.001953125?l/16:n(l,1.8)}};function i(f){return{decode:function(h){return o(h)*n(a(h),f)},encode:function(h){return o(h)*n(a(h),1/f)}}}var u={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:s},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:i(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:i(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:c}};t.default=u,e.exports=t.default})(Ct,Ct.exports)),Ct.exports}var $e={},aa;function ca(){if(aa)return $e;aa=1,Object.defineProperty($e,"__esModule",{value:!0});function e(s){return[[s[0][0],s[1][0],s[2][0]],[s[0][1],s[1][1],s[2][1]],[s[0][2],s[1][2],s[2][2]]]}function t(s){return s[0][0]*(s[2][2]*s[1][1]-s[2][1]*s[1][2])+s[1][0]*(s[2][1]*s[0][2]-s[2][2]*s[0][1])+s[2][0]*(s[1][2]*s[0][1]-s[1][1]*s[0][2])}function r(s){var c=1/t(s);return[[(s[2][2]*s[1][1]-s[2][1]*s[1][2])*c,(s[2][1]*s[0][2]-s[2][2]*s[0][1])*c,(s[1][2]*s[0][1]-s[1][1]*s[0][2])*c],[(s[2][0]*s[1][2]-s[2][2]*s[1][0])*c,(s[2][2]*s[0][0]-s[2][0]*s[0][2])*c,(s[1][0]*s[0][2]-s[1][2]*s[0][0])*c],[(s[2][1]*s[1][0]-s[2][0]*s[1][1])*c,(s[2][0]*s[0][1]-s[2][1]*s[0][0])*c,(s[1][1]*s[0][0]-s[1][0]*s[0][1])*c]]}function n(s,c){return[s[0][0]*c[0]+s[0][1]*c[1]+s[0][2]*c[2],s[1][0]*c[0]+s[1][1]*c[1]+s[1][2]*c[2],s[2][0]*c[0]+s[2][1]*c[1]+s[2][2]*c[2]]}function o(s,c){return[[s[0][0]*c[0],s[0][1]*c[1],s[0][2]*c[2]],[s[1][0]*c[0],s[1][1]*c[1],s[1][2]*c[2]],[s[2][0]*c[0],s[2][1]*c[1],s[2][2]*c[2]]]}function a(s,c){return[[s[0][0]*c[0][0]+s[0][1]*c[1][0]+s[0][2]*c[2][0],s[0][0]*c[0][1]+s[0][1]*c[1][1]+s[0][2]*c[2][1],s[0][0]*c[0][2]+s[0][1]*c[1][2]+s[0][2]*c[2][2]],[s[1][0]*c[0][0]+s[1][1]*c[1][0]+s[1][2]*c[2][0],s[1][0]*c[0][1]+s[1][1]*c[1][1]+s[1][2]*c[2][1],s[1][0]*c[0][2]+s[1][1]*c[1][2]+s[1][2]*c[2][2]],[s[2][0]*c[0][0]+s[2][1]*c[1][0]+s[2][2]*c[2][0],s[2][0]*c[0][1]+s[2][1]*c[1][1]+s[2][2]*c[2][1],s[2][0]*c[0][2]+s[2][1]*c[1][2]+s[2][2]*c[2][2]]]}return $e.transpose=e,$e.determinant=t,$e.inverse=r,$e.multiply=n,$e.scalar=o,$e.product=a,$e}var lt={},ia;function Di(){if(ia)return lt;ia=1,Object.defineProperty(lt,"__esModule",{value:!0});var e=Math,t=e.PI;function r(o){for(var a=o*180/t;a<0;)a+=360;for(;a>360;)a-=360;return a}function n(o){for(var a=t*o/180;a<0;)a+=2*t;for(;a>2*t;)a-=2*t;return a}return lt.fromRadian=r,lt.toRadian=n,lt}var ht={},ua;function Vi(){if(ua)return ht;ua=1,Object.defineProperty(ht,"__esModule",{value:!0});var e=Math,t=e.round;function r(o){return o[0]=="#"&&(o=o.slice(1)),o.length<6&&(o=o.split("").map(function(a){return a+a}).join("")),o.match(/../g).map(function(a){return parseInt(a,16)/255})}function n(o){var a=o.map(function(s){return s=t(255*s).toString(16),s.length<2&&(s="0"+s),s}).join("");return"#"+a}return ht.fromHex=r,ht.toHex=n,ht}var xt={exports:{}},fa;function Yi(){return fa||(fa=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=ca(),n=u(r),o=na(),a=i(o),s=sa(),c=i(s);function i(l){return l&&l.__esModule?l:{default:l}}function u(l){if(l&&l.__esModule)return l;var h={};if(l!=null)for(var d in l)Object.prototype.hasOwnProperty.call(l,d)&&(h[d]=l[d]);return h.default=l,h}function f(){var l=arguments.length<=0||arguments[0]===void 0?c.default.sRGB:arguments[0],h=arguments.length<=1||arguments[1]===void 0?a.default.D65:arguments[1],d=[l.r,l.g,l.b],p=n.transpose(d.map(function(x){var M=x.x/x.y,N=1,w=(1-x.x-x.y)/x.y;return[M,N,w]})),v=l.gamma,m=n.multiply(n.inverse(p),h),g=n.scalar(p,m),R=n.inverse(g);return{fromRgb:function(M){return n.multiply(g,M.map(v.decode))},toRgb:function(M){return n.multiply(R,M).map(v.encode)}}}t.default=f,e.exports=t.default})(xt,xt.exports)),xt.exports}var qn,la;function Rt(){if(la)return qn;la=1;var e=na(),t=sa(),r=ca(),n=Di(),o=Vi(),a=Yi();return qn={illuminant:e,workspace:t,matrix:r,degree:n,rgb:o,xyz:a},qn}var Zi=Rt();const Ht=pr(Zi);var de={},ha;function qt(){if(ha)return de;ha=1,Object.defineProperty(de,"__esModule",{value:!0}),de.cfs=de.distance=de.lerp=de.corLerp=void 0;var e=Hn();function t(h,d,p){return d in h?Object.defineProperty(h,d,{value:p,enumerable:!0,configurable:!0,writable:!0}):h[d]=p,h}function r(h){if(Array.isArray(h)){for(var d=0,p=Array(h.length);dm/2&&(h>d?d+=m:h+=m)}return((1-p)*h+p*d)%(m||1/0)}function u(h,d,p){var v={};for(var m in h)v[m]=i(h[m],d[m],p,m);return v}function f(h,d){var p=0;for(var v in h)p+=a(h[v]-d[v],2);return s(p)}function l(h){return e.merge.apply(void 0,r(h.split("").map(function(d){return t({},d,!0)})))}return de.corLerp=i,de.lerp=u,de.distance=f,de.cfs=l,de}var Mt={exports:{}},da;function Ji(){return da||(da=1,(function(e,t){var r=(function(){function s(c,i){var u=[],f=!0,l=!1,h=void 0;try{for(var d=c[Symbol.iterator](),p;!(f=(p=d.next()).done)&&(u.push(p.value),!(i&&u.length===i));f=!0);}catch(v){l=!0,h=v}finally{try{!f&&d.return&&d.return()}finally{if(l)throw h}}return u}return function(c,i){if(Array.isArray(c))return c;if(Symbol.iterator in Object(c))return s(c,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(t,"__esModule",{value:!0});var n=Rt(),o=qt();function a(s,c){var i=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],u=-i,f=1+i,l=Math,h=l.min,d=l.max,p=["000","fff"].map(function(w){return c.fromXyz(s.fromRgb(n.rgb.fromHex(w)))}),v=r(p,2),m=v[0],g=v[1];function R(w){var b=s.toRgb(c.toXyz(w)),_=b.map(function(k){return k>=u&&k<=f}).reduce(function(k,y){return k&&y},!0);return[_,b]}function x(w,b){for(var _=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,o.distance)(w,b)>_;){var k=(0,o.lerp)(w,b,.5),y=R(k),q=r(y,1),H=q[0];H?w=k:b=k}return w}function M(w){return(0,o.lerp)(m,g,w)}function N(w){return w.map(function(b){return d(u,h(f,b))})}return{contains:R,limit:x,spine:M,crop:N}}t.default=a,e.exports=t.default})(Mt,Mt.exports)),Mt.exports}var Ot={exports:{}},be={},ba;function pa(){if(ba)return be;ba=1;var e=(function(){function l(h,d){var p=[],v=!0,m=!1,g=void 0;try{for(var R=h[Symbol.iterator](),x;!(v=(x=R.next()).done)&&(p.push(x.value),!(d&&p.length===d));v=!0);}catch(M){m=!0,g=M}finally{try{!v&&R.return&&R.return()}finally{if(m)throw g}}return p}return function(h,d){if(Array.isArray(h))return h;if(Symbol.iterator in Object(h))return l(h,d);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(be,"__esModule",{value:!0}),be.toNotation=be.fromNotation=be.toHue=be.fromHue=void 0;var t=qt(),r=Math,n=r.floor,o=[{s:"R",h:20.14,e:.8,H:0},{s:"Y",h:90,e:.7,H:100},{s:"G",h:164.25,e:1,H:200},{s:"B",h:237.53,e:1.2,H:300},{s:"R",h:380.14,e:.8,H:400}],a=o.map(function(l){return l.s}).slice(0,-1).join("");function s(l){l50){var v=[d,h];h=v[0],d=v[1],p=100-p}return p<1?a[h]:a[h]+p.toFixed()+a[d]}return be.fromHue=s,be.toHue=c,be.fromNotation=u,be.toNotation=f,be}var ma;function Wi(){return ma||(ma=1,(function(e,t){var r=(function(){function I(K,D){var U=[],ge=!0,ye=!1,st=void 0;try{for(var fe=K[Symbol.iterator](),qe;!(ge=(qe=fe.next()).done)&&(U.push(qe.value),!(D&&U.length===D));ge=!0);}catch(le){ye=!0,st=le}finally{try{!ge&&fe.return&&fe.return()}finally{if(ye)throw st}}return U}return function(K,D){if(Array.isArray(K))return K;if(Symbol.iterator in Object(K))return I(K,D);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(t,"__esModule",{value:!0});var n=Rt(),o=pa(),a=i(o),s=qt(),c=Hn();function i(I){if(I&&I.__esModule)return I;var K={};if(I!=null)for(var D in I)Object.prototype.hasOwnProperty.call(I,D)&&(K[D]=I[D]);return K.default=I,K}var u=Math,f=u.pow,l=u.sqrt,h=u.exp,d=u.abs,p=u.sign,v=Math,m=v.sin,g=v.cos,R=v.atan2,x={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},M=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],N=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],w=M,b=n.matrix.inverse(M),_=n.matrix.product(N,n.matrix.inverse(M)),k=n.matrix.product(M,n.matrix.inverse(N)),y={whitePoint:n.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:"average",discounting:!1},q=(0,s.cfs)("QJMCshH"),H=(0,s.cfs)("JCh");function A(){var I=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],K=arguments.length<=1||arguments[1]===void 0?q:arguments[1];I=(0,c.merge)(y,I);var D=I.whitePoint,U=I.adaptingLuminance,ge=I.backgroundLuminance,ye=x[I.surroundType],st=ye.F,fe=ye.c,qe=ye.N_c,le=D[1],wc=1/(5*U+1),Ge=.2*f(wc,4)*5*U+.1*f(1-f(wc,4),2)*f(5*U,1/3),Xt=ge/le,no=.725*f(1/Xt,.2),kc=no,$c=1.48+l(Xt),Cc=I.discounting?1:st*(1-1/3.6*h(-(U+42)/92)),$l=n.matrix.multiply(M,D),Cl=$l.map(function(G){return Cc*le/G+1-Cc}),oo=r(Cl,3),xc=oo[0],Rc=oo[1],Hc=oo[2],xl=qc(D),Rl=Mc(xl),Kt=Oc(Rl);function qc(G){var z=n.matrix.multiply(w,G),F=r(z,3),ee=F[0],W=F[1],ce=F[2];return[xc*ee,Rc*W,Hc*ce]}function Hl(G){var z=r(G,3),F=z[0],ee=z[1],W=z[2];return n.matrix.multiply(b,[F/xc,ee/Rc,W/Hc])}function Mc(G){return n.matrix.multiply(_,G).map(function(z){var F=f(Ge*d(z)/100,.42);return p(z)*400*F/(27.13+F)+.1})}function ql(G){return n.matrix.multiply(k,G.map(function(z){var F=z-.1;return p(F)*100/Ge*f(27.13*d(F)/(400-d(F)),2.380952380952381)}))}function Oc(G){var z=r(G,3),F=z[0],ee=z[1],W=z[2];return(F*2+ee+W/20-.305)*no}function so(G){return 4/fe*l(G/100)*(Kt+4)*f(Ge,.25)}function Ml(G){return 6.25*f(fe*G/((Kt+4)*f(Ge,.25)),2)}function Nc(G){return G*f(Ge,.25)}function Ol(G,z){return f(G/100,2)*z/f(Ge,.25)}function Nl(G){return G/f(Ge,.25)}function Al(G,z){return 100*l(G/z)}function ao(G,z){var F=z.Q,ee=z.J,W=z.M,ce=z.C,ve=z.s,Me=z.h,Oe=z.H,te={};return G.J&&(te.J=isNaN(ee)?Ml(F):ee),G.C&&(isNaN(ce)?isNaN(W)?(F=isNaN(F)?so(ee):F,te.C=Ol(ve,F)):te.C=Nl(W):te.C=z.C),G.h&&(te.h=isNaN(Me)?a.toHue(Oe):Me),G.Q&&(te.Q=isNaN(F)?so(ee):F),G.M&&(te.M=isNaN(W)?Nc(ce):W),G.s&&(isNaN(ve)?(F=isNaN(F)?so(ee):F,W=isNaN(W)?Nc(ce):W,te.s=Al(W,F)):te.s=ve),G.H&&(te.H=isNaN(Oe)?a.fromHue(Me):Oe),te}function Ll(G){var z=qc(G),F=Mc(z),ee=r(F,3),W=ee[0],ce=ee[1],ve=ee[2],Me=W-ce*12/11+ve/11,Oe=(W+ce-2*ve)/9,te=R(Oe,Me),at=n.degree.fromRadian(te),Dt=1/4*(g(te+2)+3.8),Vt=Oc(F),bt=100*f(Vt/Kt,fe*$c),Pe=5e4/13*qe*kc*Dt*l(Me*Me+Oe*Oe)/(W+ce+21/20*ve),je=f(Pe,.9)*l(bt/100)*f(1.64-f(.29,Xt),.73);return ao(K,{J:bt,C:je,h:at})}function El(G){var z=ao(H,G),F=z.J,ee=z.C,W=z.h,ce=n.degree.toRadian(W),ve=f(ee/(l(F/100)*f(1.64-f(.29,Xt),.73)),10/9),Me=1/4*(g(ce+2)+3.8),Oe=Kt*f(F/100,1/fe/$c),te=5e4/13*qe*kc*Me/ve,at=Oe/no+.305,Dt=at*61/20*460/1403,Vt=61/20*220/1403,bt=21/20*6300/1403-27/1403,Pe=m(ce),je=g(ce),Ie,ze;ve===0||isNaN(ve)?Ie=ze=0:d(Pe)>=d(je)?(ze=Dt/(te/Pe+Vt*je/Pe+bt),Ie=ze*je/Pe):(Ie=Dt/(te/je+Vt+bt*Pe/je),ze=Ie*Pe/je);var Tl=[20/61*at+451/1403*Ie+288/1403*ze,20/61*at-891/1403*Ie-261/1403*ze,20/61*at-220/1403*Ie-6300/1403*ze],Sl=ql(Tl),Pl=Hl(Sl);return Pl}return{fromXyz:Ll,toXyz:El,fillOut:ao}}t.default=A,e.exports=t.default})(Ot,Ot.exports)),Ot.exports}var Nt={exports:{}},ga;function Ui(){return ga||(ga=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Rt(),n=Math,o=n.sqrt,a=n.pow,s=n.exp,c=n.log,i=n.cos,u=n.sin,f=n.atan2,l={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function h(){var d=arguments.length<=0||arguments[0]===void 0?"UCS":arguments[0],p=l[d],v=p.K_L,m=p.c_1,g=p.c_2;function R(N){var w=N.J,b=N.M,_=N.h,k=r.degree.toRadian(_),y=(1+100*m)*w/(1+m*w),q=1/g*c(1+g*b),H=q*i(k),A=q*u(k);return{J_p:y,a_p:H,b_p:A}}function x(N){var w=N.J_p,b=N.a_p,_=N.b_p,k=-w/(m*w-100*m-1),y=o(a(b,2)+a(_,2)),q=(s(g*y)-1)/g,H=f(_,b),A=r.degree.fromRadian(H);return{J:k,M:q,h:A}}function M(N,w){return o(a((N.J_p-w.J_p)/v,2)+a(N.a_p-w.a_p,2)+a(N.b_p-w.b_p,2))}return{fromCam:R,toCam:x,distance:M}}t.default=h,e.exports=t.default})(Nt,Nt.exports)),Nt.exports}var Mn,va;function Qi(){if(va)return Mn;va=1;var e=qt(),t=Ji(),r=Wi(),n=Ui(),o=pa();return Mn={gamut:t,cfs:e.cfs,lerp:e.lerp,cam:r,ucs:n,hq:o},Mn}var eu=Qi();const _a=pr(eu),ya=_a.cam({whitePoint:Ht.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:"average",discounting:!1},_a.cfs("JCh")),wa=Ht.xyz(Ht.workspace.sRGB,Ht.illuminant.D65),ka=e=>wa.toRgb(ya.toXyz({J:e[0],C:e[1],h:e[2]})),On=e=>{const t=ya.fromXyz(wa.fromRgb(e));return[t.J,t.C,t.h]},[tu,ru]=(()=>{const e={k_l:1,c1:.007,c2:.0228},t=Math.PI,r=64/t/5,n=1/(5*r+1),o=.2*n**4*(5*r)+.1*(1-n**4)**2*(5*r)**(1/3);return[a=>{const[s,c,i]=a,u=c*o**.25;let f=(1+100*e.c1)*s/(1+e.c1*s);f/=e.k_l;const l=1/e.c2*Math.log(1+e.c2*u),h=l*Math.cos(i*(t/180)),d=l*Math.sin(i*(t/180));return[f,h,d]},a=>{const[s,c,i]=a,u=Math.sqrt(c*c+i*i),f=(Math.exp(u*e.c2)-1)/e.c2,l=(180/t*Math.atan2(i,c)+360)%360,h=f/o**.25;return[s/(1+e.c1*(100-s)),h,l]}]})(),nu=e=>ka(ru(e)),$a=e=>tu(On(e)),At=console;At.color=(e,t="")=>{const n=O(e).luminance();At.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?"#000":"#fff"}`)},At.ramp=(e,t=1)=>{At.log("%c ",`font-size: 1px;line-height: 16px;background: ${O.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};const Ca=(e,t,r,n,o,a,s=.1)=>{if(e===r||t===n)return!0;const c=(n-t)/(r-e),i=(a+o/c-t+c*e)/(c+1/c),u=a+o/c-i/c;return(o-i)**2+(a-u)**2{const o=(t[0]+r[0])/2,a=e(o);return Ca(...t,...r,o,a,n)?null:[o,a]},Nn=(e,t,r,n=.1)=>{const o=(r-t)/10,a=[];for(let s=t;sMath.round(e*10**t)/10**t,su=(e,t=1,r=90,n=.005)=>{const o=Nn(i=>e(i).gl()[0],0,t,n),a=Nn(i=>e(i).gl()[1],0,t,n),s=Nn(i=>e(i).gl()[2],0,t,n),c=Array.from(new Set([...o.map(i=>Lt(i[0])),...a.map(i=>Lt(i[0])),...s.map(i=>Lt(i[0]))].sort((i,u)=>i-u)));return`linear-gradient(${r}deg, ${c.map(i=>`${e(i).hex()} ${Lt(i*100)}%`).join()});`},au=e=>{e.Color.prototype.jch=function(){return On(this._rgb.slice(0,3).map(o=>o/255))},e.jch=(...o)=>new e.Color(...ka(o).map(a=>Math.floor(a*255)),"rgb"),e.Color.prototype.jab=function(){return $a(this._rgb.slice(0,3).map(o=>o/255))},e.jab=(...o)=>new e.Color(...nu(o).map(a=>Math.floor(a*255)),"rgb"),e.Color.prototype.hsluv=function(){return gr.rgbToHsluv(this._rgb.slice(0,3).map(o=>o/255))},e.hsluv=(...o)=>new e.Color(...gr.hsluvToRgb(o).map(a=>Math.floor(a*255)),"rgb");const t=e.interpolate,r={jch:On,jab:$a,hsluv:gr.rgbToHsluv},n=(o,a,s)=>(Math.abs(o-a)>360/2&&(o>a?a+=360:o+=360),((1-s)*o+s*a)%360);e.interpolate=(o,a,s=.5,c="lrgb")=>{if(r[c]){typeof o!="object"&&(o=new e.Color(o)),typeof a!="object"&&(a=new e.Color(a));const i=r[c](o.gl()),u=r[c](a.gl()),f=Number.isNaN(o.hsl()[0]),l=Number.isNaN(a.hsl()[0]);let h,d,p;switch(c){case"hsluv":i[1]<1e-10&&(i[0]=u[0]),i[1]===0&&(i[1]=u[1]),u[1]<1e-10&&(u[0]=i[0]),u[1]===0&&(u[1]=i[1]),h=n(i[0],u[0],s),d=i[1]+(u[1]-i[1])*s,p=i[2]+(u[2]-i[2])*s;break;case"jch":f&&(i[2]=u[2]),l&&(u[2]=i[2]),h=i[0]+(u[0]-i[0])*s,d=i[1]+(u[1]-i[1])*s,p=n(i[2],u[2],s);break;default:h=i[0]+(u[0]-i[0])*s,d=i[1]+(u[1]-i[1])*s,p=i[2]+(u[2]-i[2])*s}return e[c](h,d,p).alpha(o.alpha()+s*(a.alpha()-o.alpha()))}return t(o,a,s,c)},e.getCSSGradient=su};/** @preserve -///// SAPC APCA - Advanced Perceptual Contrast Algorithm -///// Beta 0.1.9 W3 • contrast function only -///// DIST: W3 • Revision date: July 3, 2022 -///// Function to parse color values and determine Lc contrast -///// Copyright © 2019-2022 by Andrew Somers. All Rights Reserved. -///// LICENSE: W3 LICENSE -///// CONTACT: Please use the ISSUES or DISCUSSIONS tab at: -///// https://github.com/Myndex/SAPC-APCA/ -///// -/////////////////////////////////////////////////////////////////////////////// -///// -///// MINIMAL IMPORTS: -///// import { APCAcontrast, sRGBtoY, displayP3toY, -///// calcAPCA, fontLookupAPCA } from 'apca-w3'; -///// import { colorParsley } from 'colorparsley'; -///// -///// FORWARD CONTRAST USAGE: -///// Lc = APCAcontrast( sRGBtoY( TEXTcolor ) , sRGBtoY( BACKGNDcolor ) ); -///// Where the colors are sent as an rgba array [255,255,255,1] -///// -///// Retrieving an array of font sizes for the contrast: -///// fontArray = fontLookupAPCA(Lc); -///// -///// Live Demonstrator at https://www.myndex.com/APCA/ -// */const Y={mainTRC:2.4,sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1};function xa(e,t,r=-1){const n=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)n[1])return 0;let o=0,a=0,s="BoW";return e=e>Y.blkThrs?e:e+Math.pow(Y.blkThrs-e,Y.blkClmp),t=t>Y.blkThrs?t:t+Math.pow(Y.blkThrs-t,Y.blkClmp),Math.abs(t-e)e?(o=(Math.pow(t,Y.normBG)-Math.pow(e,Y.normTXT))*Y.scaleBoW,a=o-.1?0:o+Y.loWoBoffset),r<0?a*100:r==0?Math.round(Math.abs(a)*100)+""+s+"":Number.isInteger(r)?(a*100).toFixed(r):0)}function Et(e=[0,0,0]){function t(r){return Math.pow(r/255,Y.mainTRC)}return Y.sRco*t(e[0])+Y.sGco*t(e[1])+Y.sBco*t(e[2])}const Ra=(e,t,r,n,o,a,s,c,i)=>{const u=1-i,f=u*u,l=f*u,d=i*i*i,p=l*e+f*3*i*r+u*3*i*i*o+d*s,v=l*t+f*3*i*n+u*3*i*i*a+d*c;return{x:p,y:v}},cu=(e,t)=>{const r=[];let n={x:+e[0],y:+e[1]};for(let o=0,a=e.length;a-2*!0>o;o+=2){const s=[{x:+e[o-2],y:+e[o-1]},{x:+e[o],y:+e[o+1]},{x:+e[o+2],y:+e[o+3]},{x:+e[o+4],y:+e[o+5]}];a-4===o?s[3]=s[2]:o||(s[0]={x:+e[o],y:+e[o+1]}),r.push([n.x,n.y,(-s[0].x+6*s[1].x+s[2].x)/6,(-s[0].y+6*s[1].y+s[2].y)/6,(s[1].x+6*s[2].x-s[3].x)/6,(s[1].y+6*s[2].y-s[3].y)/6,s[2].x,s[2].y]),n=s[2]}return r},iu=(e,t,r,n,o,a,s,c)=>{let u=e,f=t,l=0;for(let h=1;h<5;h++){const{x:d,y:p}=Ra(e,t,r,n,o,a,s,c,h/5);l+=Math.hypot(d-u,p-f),u=d,f=p}return l+=Math.hypot(s-u,c-f),l},uu=(e,t,r,n,o,a,s,c)=>{const i=Math.floor(iu(e,t,r,n,o,a,s,c)*.75),u=[];let f=0;for(let l=0;l<=i;l++){const h=l/i,d=Ra(e,t,r,n,o,a,s,c,h),p=Math.round(d.x);if(u[p]=d.y,p-f>1){const v=u[f],m=u[p];for(let g=f+1;gu[Math.round(l)]||null},Ze={CAM02:"jab",CAM02p:"jch",HEX:"hex",HSL:"hsl",HSLuv:"hsluv",HSV:"hsv",LAB:"lab",LCH:"lch",RGB:"rgb",OKLAB:"oklab",OKLCH:"oklch"};function Ee(e,t=0){const r=10**t;return Math.round(e*r)/r}function fu(e,t){let r;return e>1?r=(e-1)*t+1:e<-1?r=(e+1)*t-1:r=1,Ee(r,2)}function lu(e){return O(String(e)).jch()}function hu(e){return O(String(e)).hsluv()}function du(e,t,r){const n=[[],[],[]];if(e.forEach((a,s)=>n.forEach((c,i)=>c.push(t[s],a[i]))),r==="hcl"){const a=n[1];for(let s=1;s{const s=[];for(let c=1;c{a[i]=a[c]}),s.length=0;break}if(s.length){const c=O("#ccc").jch()[2];s.forEach(i=>{a[i]=c})}s.length=0;for(let c=a.length-1;c>0;c-=2)if(Number.isNaN(a[c]))s.push(c);else{s.forEach(i=>{a[i]=a[c]});break}for(let c=1;ccu(a).map(s=>uu(...s)));return a=>{const s=o.map(c=>{for(let i=0;in*a**e+o}function An({swatches:e,colorKeys:t,colorspace:r="LAB",shift:n=1,fullScale:o=!0,smooth:a=!1,distributeLightness:s="linear",sortColor:c=!0,asFun:i=!1}={}){const u=Ze[r];if(!u)throw new Error(`Colorspace “${r}” not supported`);if(!t)throw new Error(`Colorkeys missing: returned “${t}”`);let f;if(o)f=t.map(R=>e-e*(O(R).jch()[0]/100)).sort((R,x)=>R-x).concat(e),f.unshift(0);else{let R=t.map(N=>O(N).jch()[0]/100),x=Math.min(...R),M=Math.max(...R);f=R.map(N=>N===0||isNaN((N-x)/(M-x))?0:e-(N-x)/(M-x)*e).sort((N,w)=>N-w)}let l=bu(n,[1,e],[1,e]);if(l=f.map(R=>Math.max(0,l(R))),f=l,s==="polynomial"){const R=N=>Math.sqrt(Math.sqrt((Math.pow(N,2.25)+Math.pow(N,4))/2));f=l.map(N=>N/e).map(N=>R(N)*e)}const h=t.map((R,x)=>({colorKeys:lu(R),index:x})).sort((R,x)=>x.colorKeys[0]-R.colorKeys[0]).map(R=>t[R.index]);let d=[],p;if(o){const R=u==="lch"?O.lch(...O("#fff").lch()):"#ffffff",x=u==="lch"?O.lch(...O("#000").lch()):"#000000";d=[R,...h,x]}else c?d=h:d=t;let v;if(a){const R=d;if(d=d.map(x=>O(String(x))[u]()),u==="hcl"&&d.forEach(x=>{x[1]=Number.isNaN(x[1])?0:x[1]}),u==="jch")for(let x=0;xp(M))}else p=O.scale(d.map(R=>typeof R=="object"&&R.constructor===O.Color?R:String(R))).domain(f).mode(u);return i?p:(!a||a===!1?p.colors(e):v).filter(R=>R!=null)}function pu(e,t){const r=[],n={};return Object.keys(e).forEach(s=>{n[e[s][t]]=e[s]}),Object.keys(n).forEach(s=>r.push(n[s])),r}function mu(e){return Number.isNaN(e)?0:e}function Ln(e,t,r=!1){if(!e)throw new Error(`Cannot convert color value of “${e}”`);if(!Ze[t])throw new Error(`Cannot convert to colorspace “${t}”`);const n=Ze[t],o=O(String(e))[n]();if(t==="HSL"&&o.pop(),t==="HEX"){if(r){const u=O(String(e)).rgb();return{r:u[0],g:u[1],b:u[2]}}return o}const a={};let s=o.map(mu);s=s.map((u,f)=>{let l=Ee(u),h=f;n==="hsluv"&&(h+=2);let d=n.charAt(h);return n==="jch"&&d==="c"&&(d="C"),a[d==="j"?"J":d]=l,n in{lab:1,lch:1,jab:1,jch:1}?r||((d==="l"||d==="j")&&(l+="%"),d==="h"&&(l+="deg")):n!=="hsluv"&&(d==="s"||d==="l"||d==="v"?(a[d]=Ee(u,2),r||(l=Ee(u*100),l+="%")):d==="h"&&!r&&(l+="deg")),l});const i=`${n}(${s.join(", ")})`;return r?a:i}function Ha(e,t,r){const n=[e,t,r].map(o=>(o/=255,o<=.03928?o/12.92:((o+.055)/1.055)**2.4));return n[0]*.2126+n[1]*.7152+n[2]*.0722}function gu(e,t,r,n="wcag2"){if(r===void 0){const o=O.rgb(...t).hsluv()[2];r=Ee(o/100,2)}if(n==="wcag2"){const o=Ha(e[0],e[1],e[2]),a=Ha(t[0],t[1],t[2]),s=(o+.05)/(a+.05),c=(a+.05)/(o+.05);return r<.5?s>=1?s:-c:s<1?c:s===1?s:-s}else{if(n==="wcag3")return r<.5?xa(Et(e),Et(t))*-1:xa(Et(e),Et(t));throw new Error(`Contrast calculation method ${n} unsupported; use 'wcag2' or 'wcag3'`)}}function vu(e,t){if(!e)throw new Error("Array undefined");if(!Array.isArray(e))throw new Error("Passed object is not an array");const r=t==="wcag2"?0:1;return Math.min(...e.filter(n=>n>=r))}function _u(e,t){if(!e)throw new Error("Ratios undefined");e=e.sort((c,i)=>c-i);const r=vu(e,t),n=e.indexOf(r),o=[],a=e.slice(0,n),s=e.slice(n,e.length);for(let c=0;cc-i),o}const yu=(e,t,r,n,o)=>{const s=An({swatches:3e3,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),c={},i=l=>{if(c[l])return c[l];const h=O(s(l)).rgb(),d=gu(h,t,r,o);return c[l]=d,d},u=l=>{const h=i(0),d=i(3e3),p=hv&&x;)x--,m/=2,Rf.push(s(u(+l)))),f};let ae=class{constructor({name:t,colorKeys:r,colorspace:n="RGB",ratios:o,smooth:a=!1,output:s="HEX",saturation:c=100}){if(this._name=t,this._colorKeys=r,this._modifiedKeys=r,this._colorspace=n,this._ratios=o,this._smooth=a,this._output=s,this._saturation=c,!this._name)throw new Error("Color missing name");if(!this._colorKeys)throw new Error("Color Keys are undefined");if(!Ze[this._colorspace])throw new Error(`Colorspace “${n}” not supported`);if(!Ze[this._output])throw new Error(`Output “${n}” not supported`);for(let i=0;i{let n=O(`${r}`).oklch(),a=n[1]*(this._saturation/100),s=O.oklch(n[0],a,n[2]),c=O.rgb(s).hex();t.push(c)}),this._modifiedKeys=t,this._generateColorScale()}_generateColorScale(){this._colorScale=An({swatches:3e3,colorKeys:this._modifiedKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}};class qa extends ae{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){ae.prototype._generateColorScale.call(this);const t=An({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});t.push(...this.colorKeys);const r=t.map((a,s)=>({value:Math.round(hu(a)[2]),index:s})),o=pu(r,"value").map(a=>t[a.index]);return o.length>=101&&(o.length=100,o.push("#ffffff")),this._backgroundColorScale=o.map(a=>Ln(a,this._output)),this._backgroundColorScale}}class wu{constructor({colors:t,backgroundColor:r,lightness:n,contrast:o=1,saturation:a=100,output:s="HEX",formula:c="wcag2"}){if(this._output=s,this._colors=t,this._lightness=n,this._saturation=a,this._formula=c,this._setBackgroundColor(r),this._setBackgroundColorValue(),this._contrast=o,!this._colors)throw new Error("No colors are defined");if(!this._backgroundColor)throw new Error("Background color is undefined");if(t.forEach(i=>{if(!i.ratios)throw new Error(`Color ${i.name}'s ratios are undefined`)}),!Ze[this._output])throw new Error(`Output “${s}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(t){this._formula=t,this._findContrastColors()}get formula(){return this._formula}set contrast(t){this._contrast=t,this._findContrastColors()}get contrast(){return this._contrast}set lightness(t){this._lightness=t,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(t){this._saturation=t,this._updateColorSaturation(t),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(t){this._setBackgroundColor(t),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(t){this._colors=t,this._findContrastColors()}get colors(){return this._colors}set addColor(t){this._colors.push(t),this._findContrastColors()}set removeColor(t){const r=this._colors.filter(n=>n.name!==t.name);this._colors=r,this._findContrastColors()}set updateColor(t){if(Array.isArray(t))for(let r=0;rs.name===t[r].color);n=n[0];let o=this._colors.indexOf(n);const a=this._colors.filter(s=>s.name!==t[r].color);t[r].name&&(n.name=t[r].name),t[r].colorKeys&&(n.colorKeys=t[r].colorKeys),t[r].ratios&&(n.ratios=t[r].ratios),t[r].colorspace&&(n.colorspace=t[r].colorspace),t[r].smooth&&(n.smooth=t[r].smooth),n._generateColorScale(),a.splice(o,0,n),this._colors=a}else{let r=this._colors.filter(a=>a.name===t.color);r=r[0];let n=this._colors.indexOf(r);const o=this._colors.filter(a=>a.name!==t.color);t.name&&(r.name=t.name),t.colorKeys&&(r.colorKeys=t.colorKeys),t.ratios&&(r.ratios=t.ratios),t.colorspace&&(r.colorspace=t.colorspace),t.smooth&&(r.smooth=t.smooth),r._generateColorScale(),o.splice(n,0,r),this._colors=o}this._findContrastColors()}set output(t){this._output=t,this._colors.forEach(r=>{r.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(t){if(typeof t=="string"){const r=new qa({name:"background",colorKeys:[t],output:"RGB"}),n=Ee(O(String(t)).hsluv()[2]);this._backgroundColor=r,this._lightness=n,this._backgroundColorValue=r[this._lightness]}else{t.output="RGB";const r=t.backgroundColorScale[this._lightness];this._backgroundColor=t,this._backgroundColorValue=r}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(t){this._colors.map(r=>{r.saturation=t})}_findContrastColors(){const t=O(String(this._backgroundColorValue)).rgb(),r=this._lightness/100,o={background:Ln(this._backgroundColorValue,this._output)},a=[],s=[],c={...o};return a.push(o),this._colors.map(i=>{if(i.ratios!==void 0){let u;const f=[],l={name:i.name,values:f};let h;Array.isArray(i.ratios)?h=i.ratios:Array.isArray(i.ratios)||(u=Object.keys(i.ratios),h=Object.values(i.ratios)),h=h.map(p=>fu(+p,this._contrast));const d=yu(i,t,r,h,this._formula).map(p=>Ln(p,this._output));for(let p=0;pku($u(t,e),r),En=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=Be(e[t],0,255)):t===3&&(e[t]=Be(e[t],0,1));return e},Ma={};for(let e of["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"])Ma[`[object ${e}]`]=e.toLowerCase();function j(e){return Ma[Object.prototype.toString.call(e)]||"object"}const T=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):j(e[0])=="object"&&t?t.split("").filter(r=>e[0][r]!==void 0).map(r=>e[0][r]):e[0].slice(0),Je=e=>{if(e.length<2)return null;const t=e.length-1;return j(e[t])=="string"?e[t].toLowerCase():null},{PI:Tt,min:Oa,max:Na}=Math,ie=e=>Math.round(e*100)/100,Tn=e=>Math.round(e*100)/100,Ce=Tt*2,Sn=Tt/3,Cu=Tt/180,xu=180/Tt;function Aa(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}const E={format:{},autodetect:[]};class ${constructor(...t){const r=this;if(j(t[0])==="object"&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];let n=Je(t),o=!1;if(!n){o=!0,E.sorted||(E.autodetect=E.autodetect.sort((a,s)=>s.p-a.p),E.sorted=!0);for(let a of E.autodetect)if(n=a.test(...t),n)break}if(E.format[n]){const a=E.format[n].apply(null,o?t:t.slice(0,-1));r._rgb=En(a)}else throw new Error("unknown format: "+t);r._rgb.length===3&&r._rgb.push(1)}toString(){return j(this.hex)=="function"?this.hex():`[${this._rgb.join(",")}]`}}const Ru="3.1.2",B=(...e)=>new $(...e);B.version=Ru;const We={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},Hu=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,qu=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,La=e=>{if(e.match(Hu)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const t=parseInt(e,16),r=t>>16,n=t>>8&255,o=t&255;return[r,n,o,1]}if(e.match(qu)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);const t=parseInt(e,16),r=t>>24&255,n=t>>16&255,o=t>>8&255,a=Math.round((t&255)/255*100)/100;return[r,n,o,a]}throw new Error(`unknown hex color: ${e}`)},{round:St}=Math,Ea=(...e)=>{let[t,r,n,o]=T(e,"rgba"),a=Je(e)||"auto";o===void 0&&(o=1),a==="auto"&&(a=o<1?"rgba":"rgb"),t=St(t),r=St(r),n=St(n);let c="000000"+(t<<16|r<<8|n).toString(16);c=c.substr(c.length-6);let i="0"+St(o*255).toString(16);switch(i=i.substr(i.length-2),a.toLowerCase()){case"rgba":return`#${c}${i}`;case"argb":return`#${i}${c}`;default:return`#${c}`}};$.prototype.name=function(){const e=Ea(this._rgb,"rgb");for(let t of Object.keys(We))if(We[t]===e)return t.toLowerCase();return e},E.format.named=e=>{if(e=e.toLowerCase(),We[e])return La(We[e]);throw new Error("unknown color name: "+e)},E.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&j(e)==="string"&&We[e.toLowerCase()])return"named"}}),$.prototype.alpha=function(e,t=!1){return e!==void 0&&j(e)==="number"?t?(this._rgb[3]=e,this):new $([this._rgb[0],this._rgb[1],this._rgb[2],e],"rgb"):this._rgb[3]},$.prototype.clipped=function(){return this._rgb._clipped||!1};const _e={Kn:18,labWhitePoint:"d65",Xn:.95047,Yn:1,Zn:1.08883,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},Mu=new Map([["a",[1.0985,.35585]],["b",[1.0985,.35585]],["c",[.98074,1.18232]],["d50",[.96422,.82521]],["d55",[.95682,.92149]],["d65",[.95047,1.08883]],["e",[1,1,1]],["f2",[.99186,.67393]],["f7",[.95041,1.08747]],["f11",[1.00962,.6435]],["icc",[.96422,.82521]]]);function xe(e){const t=Mu.get(String(e).toLowerCase());if(!t)throw new Error("unknown Lab illuminant "+e);_e.labWhitePoint=e,_e.Xn=t[0],_e.Zn=t[1]}function dt(){return _e.labWhitePoint}const Pn=(...e)=>{e=T(e,"lab");const[t,r,n]=e,[o,a,s]=Ou(t,r,n),[c,i,u]=Ta(o,a,s);return[c,i,u,e.length>3?e[3]:1]},Ou=(e,t,r)=>{const{kE:n,kK:o,kKE:a,Xn:s,Yn:c,Zn:i}=_e,u=(e+16)/116,f=.002*t+u,l=u-.005*r,h=f*f*f,d=l*l*l,p=h>n?h:(116*f-16)/o,v=e>a?Math.pow((e+16)/116,3):e/o,m=d>n?d:(116*l-16)/o,g=p*s,R=v*c,x=m*i;return[g,R,x]},jn=e=>{const t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*Math.pow(e,1/2.4)-.055)*t},Ta=(e,t,r)=>{const{MtxAdaptMa:n,MtxAdaptMaI:o,MtxXYZ2RGB:a,RefWhiteRGB:s,Xn:c,Yn:i,Zn:u}=_e,f=c*n.m00+i*n.m10+u*n.m20,l=c*n.m01+i*n.m11+u*n.m21,h=c*n.m02+i*n.m12+u*n.m22,d=s.X*n.m00+s.Y*n.m10+s.Z*n.m20,p=s.X*n.m01+s.Y*n.m11+s.Z*n.m21,v=s.X*n.m02+s.Y*n.m12+s.Z*n.m22,m=(e*n.m00+t*n.m10+r*n.m20)*(d/f),g=(e*n.m01+t*n.m11+r*n.m21)*(p/l),R=(e*n.m02+t*n.m12+r*n.m22)*(v/h),x=m*o.m00+g*o.m10+R*o.m20,M=m*o.m01+g*o.m11+R*o.m21,N=m*o.m02+g*o.m12+R*o.m22,w=jn(x*a.m00+M*a.m10+N*a.m20),b=jn(x*a.m01+M*a.m11+N*a.m21),_=jn(x*a.m02+M*a.m12+N*a.m22);return[w*255,b*255,_*255]},Bn=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),[a,s,c]=Sa(t,r,n),[i,u,f]=Nu(a,s,c);return[i,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]};function Nu(e,t,r){const{Xn:n,Yn:o,Zn:a,kE:s,kK:c}=_e,i=e/n,u=t/o,f=r/a,l=i>s?Math.pow(i,1/3):(c*i+16)/116,h=u>s?Math.pow(u,1/3):(c*u+16)/116,d=f>s?Math.pow(f,1/3):(c*f+16)/116;return[116*h-16,500*(l-h),200*(h-d)]}function Gn(e){const t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4))*t}const Sa=(e,t,r)=>{e=Gn(e/255),t=Gn(t/255),r=Gn(r/255);const{MtxRGB2XYZ:n,MtxAdaptMa:o,MtxAdaptMaI:a,Xn:s,Yn:c,Zn:i,As:u,Bs:f,Cs:l}=_e;let h=e*n.m00+t*n.m10+r*n.m20,d=e*n.m01+t*n.m11+r*n.m21,p=e*n.m02+t*n.m12+r*n.m22;const v=s*o.m00+c*o.m10+i*o.m20,m=s*o.m01+c*o.m11+i*o.m21,g=s*o.m02+c*o.m12+i*o.m22;let R=h*o.m00+d*o.m10+p*o.m20,x=h*o.m01+d*o.m11+p*o.m21,M=h*o.m02+d*o.m12+p*o.m22;return R*=v/u,x*=m/f,M*=g/l,h=R*a.m00+x*a.m10+M*a.m20,d=R*a.m01+x*a.m11+M*a.m21,p=R*a.m02+x*a.m12+M*a.m22,[h,d,p]};$.prototype.lab=function(){return Bn(this._rgb)},Object.assign(B,{lab:(...e)=>new $(...e,"lab"),getLabWhitePoint:dt,setLabWhitePoint:xe}),E.format.lab=Pn,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"lab"),j(e)==="array"&&e.length===3)return"lab"}}),$.prototype.darken=function(e=1){const t=this,r=t.lab();return r[0]-=_e.Kn*e,new $(r,"lab").alpha(t.alpha(),!0)},$.prototype.brighten=function(e=1){return this.darken(-e)},$.prototype.darker=$.prototype.darken,$.prototype.brighter=$.prototype.brighten,$.prototype.get=function(e){const[t,r]=e.split("."),n=this[t]();if(r){const o=t.indexOf(r)-(t.substr(0,2)==="ok"?2:0);if(o>-1)return n[o];throw new Error(`unknown channel ${r} in mode ${t}`)}else return n};const{pow:Au}=Math,Lu=1e-7,Eu=20;$.prototype.luminance=function(e,t="rgb"){if(e!==void 0&&j(e)==="number"){if(e===0)return new $([0,0,0,this._rgb[3]],"rgb");if(e===1)return new $([255,255,255,this._rgb[3]],"rgb");let r=this.luminance(),n=Eu;const o=(s,c)=>{const i=s.interpolate(c,.5,t),u=i.luminance();return Math.abs(e-u)e?o(s,i):o(i,c)},a=(r>e?o(new $([0,0,0]),this):o(this,new $([255,255,255]))).rgb();return new $([...a,this._rgb[3]])}return Tu(...this._rgb.slice(0,3))};const Tu=(e,t,r)=>(e=In(e),t=In(t),r=In(r),.2126*e+.7152*t+.0722*r),In=e=>(e/=255,e<=.03928?e/12.92:Au((e+.055)/1.055,2.4)),ne={},Ue=(e,t,r=.5,...n)=>{let o=n[0]||"lrgb";if(!ne[o]&&!n.length&&(o=Object.keys(ne)[0]),!ne[o])throw new Error(`interpolation mode ${o} is not defined`);return j(e)!=="object"&&(e=new $(e)),j(t)!=="object"&&(t=new $(t)),ne[o](e,t,r).alpha(e.alpha()+r*(t.alpha()-e.alpha()))};$.prototype.mix=$.prototype.interpolate=function(e,t=.5,...r){return Ue(this,e,t,...r)},$.prototype.premultiply=function(e=!1){const t=this._rgb,r=t[3];return e?(this._rgb=[t[0]*r,t[1]*r,t[2]*r,r],this):new $([t[0]*r,t[1]*r,t[2]*r,r],"rgb")};const{sin:Su,cos:Pu}=Math,Pa=(...e)=>{let[t,r,n]=T(e,"lch");return isNaN(n)&&(n=0),n=n*Cu,[t,Pu(n)*r,Su(n)*r]},zn=(...e)=>{e=T(e,"lch");const[t,r,n]=e,[o,a,s]=Pa(t,r,n),[c,i,u]=Pn(o,a,s);return[c,i,u,e.length>3?e[3]:1]},ju=(...e)=>{const t=Aa(T(e,"hcl"));return zn(...t)},{sqrt:Bu,atan2:Gu,round:Iu}=Math,ja=(...e)=>{const[t,r,n]=T(e,"lab"),o=Bu(r*r+n*n);let a=(Gu(n,r)*xu+360)%360;return Iu(o*1e4)===0&&(a=Number.NaN),[t,o,a]},Fn=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),[a,s,c]=Bn(t,r,n),[i,u,f]=ja(a,s,c);return[i,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]};$.prototype.lch=function(){return Fn(this._rgb)},$.prototype.hcl=function(){return Aa(Fn(this._rgb))},Object.assign(B,{lch:(...e)=>new $(...e,"lch"),hcl:(...e)=>new $(...e,"hcl")}),E.format.lch=zn,E.format.hcl=ju,["lch","hcl"].forEach(e=>E.autodetect.push({p:2,test:(...t)=>{if(t=T(t,e),j(t)==="array"&&t.length===3)return e}})),$.prototype.saturate=function(e=1){const t=this,r=t.lch();return r[1]+=_e.Kn*e,r[1]<0&&(r[1]=0),new $(r,"lch").alpha(t.alpha(),!0)},$.prototype.desaturate=function(e=1){return this.saturate(-e)},$.prototype.set=function(e,t,r=!1){const[n,o]=e.split("."),a=this[n]();if(o){const s=n.indexOf(o)-(n.substr(0,2)==="ok"?2:0);if(s>-1){if(j(t)=="string")switch(t.charAt(0)){case"+":a[s]+=+t;break;case"-":a[s]+=+t;break;case"*":a[s]*=+t.substr(1);break;case"/":a[s]/=+t.substr(1);break;default:a[s]=+t}else if(j(t)==="number")a[s]=t;else throw new Error("unsupported value for Color.set");const c=new $(a,n);return r?(this._rgb=c._rgb,this):c}throw new Error(`unknown channel ${o} in mode ${n}`)}else return a},$.prototype.tint=function(e=.5,...t){return Ue(this,"white",e,...t)},$.prototype.shade=function(e=.5,...t){return Ue(this,"black",e,...t)};const zu=(e,t,r)=>{const n=e._rgb,o=t._rgb;return new $(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"rgb")};ne.rgb=zu;const{sqrt:Xn,pow:Qe}=Math,Fu=(e,t,r)=>{const[n,o,a]=e._rgb,[s,c,i]=t._rgb;return new $(Xn(Qe(n,2)*(1-r)+Qe(s,2)*r),Xn(Qe(o,2)*(1-r)+Qe(c,2)*r),Xn(Qe(a,2)*(1-r)+Qe(i,2)*r),"rgb")};ne.lrgb=Fu;const Xu=(e,t,r)=>{const n=e.lab(),o=t.lab();return new $(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"lab")};ne.lab=Xu;const et=(e,t,r,n)=>{let o,a;n==="hsl"?(o=e.hsl(),a=t.hsl()):n==="hsv"?(o=e.hsv(),a=t.hsv()):n==="hcg"?(o=e.hcg(),a=t.hcg()):n==="hsi"?(o=e.hsi(),a=t.hsi()):n==="lch"||n==="hcl"?(n="hcl",o=e.hcl(),a=t.hcl()):n==="oklch"&&(o=e.oklch().reverse(),a=t.oklch().reverse());let s,c,i,u,f,l;(n.substr(0,1)==="h"||n==="oklch")&&([s,i,f]=o,[c,u,l]=a);let h,d,p,v;return!isNaN(s)&&!isNaN(c)?(c>s&&c-s>180?v=c-(s+360):c180?v=c+360-s:v=c-s,d=s+r*v):isNaN(s)?isNaN(c)?d=Number.NaN:(d=c,(f==1||f==0)&&n!="hsv"&&(h=u)):(d=s,(l==1||l==0)&&n!="hsv"&&(h=i)),h===void 0&&(h=i+r*(u-i)),p=f+r*(l-f),n==="oklch"?new $([p,h,d],n):new $([d,h,p],n)},Ba=(e,t,r)=>et(e,t,r,"lch");ne.lch=Ba,ne.hcl=Ba;const Ku=e=>{if(j(e)=="number"&&e>=0&&e<=16777215){const t=e>>16,r=e>>8&255,n=e&255;return[t,r,n,1]}throw new Error("unknown num color: "+e)},Du=(...e)=>{const[t,r,n]=T(e,"rgb");return(t<<16)+(r<<8)+n};$.prototype.num=function(){return Du(this._rgb)},Object.assign(B,{num:(...e)=>new $(...e,"num")}),E.format.num=Ku,E.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&j(e[0])==="number"&&e[0]>=0&&e[0]<=16777215)return"num"}});const Vu=(e,t,r)=>{const n=e.num(),o=t.num();return new $(n+r*(o-n),"num")};ne.num=Vu;const{floor:Yu}=Math,Zu=(...e)=>{e=T(e,"hcg");let[t,r,n]=e,o,a,s;n=n*255;const c=r*255;if(r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const i=Yu(t),u=t-i,f=n*(1-r),l=f+c*(1-u),h=f+c*u,d=f+c;switch(i){case 0:[o,a,s]=[d,h,f];break;case 1:[o,a,s]=[l,d,f];break;case 2:[o,a,s]=[f,d,h];break;case 3:[o,a,s]=[f,l,d];break;case 4:[o,a,s]=[h,f,d];break;case 5:[o,a,s]=[d,f,l];break}}return[o,a,s,e.length>3?e[3]:1]},Ju=(...e)=>{const[t,r,n]=T(e,"rgb"),o=Oa(t,r,n),a=Na(t,r,n),s=a-o,c=s*100/255,i=o/(255-s)*100;let u;return s===0?u=Number.NaN:(t===a&&(u=(r-n)/s),r===a&&(u=2+(n-t)/s),n===a&&(u=4+(t-r)/s),u*=60,u<0&&(u+=360)),[u,c,i]};$.prototype.hcg=function(){return Ju(this._rgb)};const Wu=(...e)=>new $(...e,"hcg");B.hcg=Wu,E.format.hcg=Zu,E.autodetect.push({p:1,test:(...e)=>{if(e=T(e,"hcg"),j(e)==="array"&&e.length===3)return"hcg"}});const Uu=(e,t,r)=>et(e,t,r,"hcg");ne.hcg=Uu;const{cos:tt}=Math,Qu=(...e)=>{e=T(e,"hsi");let[t,r,n]=e,o,a,s;return isNaN(t)&&(t=0),isNaN(r)&&(r=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(s=(1-r)/3,o=(1+r*tt(Ce*t)/tt(Sn-Ce*t))/3,a=1-(s+o)):t<2/3?(t-=1/3,o=(1-r)/3,a=(1+r*tt(Ce*t)/tt(Sn-Ce*t))/3,s=1-(o+a)):(t-=2/3,a=(1-r)/3,s=(1+r*tt(Ce*t)/tt(Sn-Ce*t))/3,o=1-(a+s)),o=Be(n*o*3),a=Be(n*a*3),s=Be(n*s*3),[o*255,a*255,s*255,e.length>3?e[3]:1]},{min:ef,sqrt:tf,acos:rf}=Math,nf=(...e)=>{let[t,r,n]=T(e,"rgb");t/=255,r/=255,n/=255;let o;const a=ef(t,r,n),s=(t+r+n)/3,c=s>0?1-a/s:0;return c===0?o=NaN:(o=(t-r+(t-n))/2,o/=tf((t-r)*(t-r)+(t-n)*(r-n)),o=rf(o),n>r&&(o=Ce-o),o/=Ce),[o*360,c,s]};$.prototype.hsi=function(){return nf(this._rgb)};const of=(...e)=>new $(...e,"hsi");B.hsi=of,E.format.hsi=Qu,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"hsi"),j(e)==="array"&&e.length===3)return"hsi"}});const sf=(e,t,r)=>et(e,t,r,"hsi");ne.hsi=sf;const Kn=(...e)=>{e=T(e,"hsl");const[t,r,n]=e;let o,a,s;if(r===0)o=a=s=n*255;else{const c=[0,0,0],i=[0,0,0],u=n<.5?n*(1+r):n+r-n*r,f=2*n-u,l=t/360;c[0]=l+1/3,c[1]=l,c[2]=l-1/3;for(let h=0;h<3;h++)c[h]<0&&(c[h]+=1),c[h]>1&&(c[h]-=1),6*c[h]<1?i[h]=f+(u-f)*6*c[h]:2*c[h]<1?i[h]=u:3*c[h]<2?i[h]=f+(u-f)*(2/3-c[h])*6:i[h]=f;[o,a,s]=[i[0]*255,i[1]*255,i[2]*255]}return e.length>3?[o,a,s,e[3]]:[o,a,s,1]},Ga=(...e)=>{e=T(e,"rgba");let[t,r,n]=e;t/=255,r/=255,n/=255;const o=Oa(t,r,n),a=Na(t,r,n),s=(a+o)/2;let c,i;return a===o?(c=0,i=Number.NaN):c=s<.5?(a-o)/(a+o):(a-o)/(2-a-o),t==a?i=(r-n)/(a-o):r==a?i=2+(n-t)/(a-o):n==a&&(i=4+(t-r)/(a-o)),i*=60,i<0&&(i+=360),e.length>3&&e[3]!==void 0?[i,c,s,e[3]]:[i,c,s]};$.prototype.hsl=function(){return Ga(this._rgb)};const af=(...e)=>new $(...e,"hsl");B.hsl=af,E.format.hsl=Kn,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"hsl"),j(e)==="array"&&e.length===3)return"hsl"}});const cf=(e,t,r)=>et(e,t,r,"hsl");ne.hsl=cf;const{floor:uf}=Math,ff=(...e)=>{e=T(e,"hsv");let[t,r,n]=e,o,a,s;if(n*=255,r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const c=uf(t),i=t-c,u=n*(1-r),f=n*(1-r*i),l=n*(1-r*(1-i));switch(c){case 0:[o,a,s]=[n,l,u];break;case 1:[o,a,s]=[f,n,u];break;case 2:[o,a,s]=[u,n,l];break;case 3:[o,a,s]=[u,f,n];break;case 4:[o,a,s]=[l,u,n];break;case 5:[o,a,s]=[n,u,f];break}}return[o,a,s,e.length>3?e[3]:1]},{min:lf,max:hf}=Math,df=(...e)=>{e=T(e,"rgb");let[t,r,n]=e;const o=lf(t,r,n),a=hf(t,r,n),s=a-o;let c,i,u;return u=a/255,a===0?(c=Number.NaN,i=0):(i=s/a,t===a&&(c=(r-n)/s),r===a&&(c=2+(n-t)/s),n===a&&(c=4+(t-r)/s),c*=60,c<0&&(c+=360)),[c,i,u]};$.prototype.hsv=function(){return df(this._rgb)};const bf=(...e)=>new $(...e,"hsv");B.hsv=bf,E.format.hsv=ff,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"hsv"),j(e)==="array"&&e.length===3)return"hsv"}});const pf=(e,t,r)=>et(e,t,r,"hsv");ne.hsv=pf;function Pt(e,t){let r=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(s=>[s]));let n=t[0].length,o=t[0].map((s,c)=>t.map(i=>i[c])),a=e.map(s=>o.map(c=>Array.isArray(s)?s.reduce((i,u,f)=>i+u*(c[f]||0),0):c.reduce((i,u)=>i+u*s,0)));return r===1&&(a=a[0]),n===1?a.map(s=>s[0]):a}const Dn=(...e)=>{e=T(e,"lab");const[t,r,n,...o]=e,[a,s,c]=mf([t,r,n]),[i,u,f]=Ta(a,s,c);return[i,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]};function mf(e){var t=[[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],r=[[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],n=Pt(r,e);return Pt(t,n.map(o=>o**3))}const Vn=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),a=Sa(t,r,n);return[...gf(a),...o.length>0&&o[0]<1?[o[0]]:[]]};function gf(e){const t=[[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],r=[[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],n=Pt(t,e);return Pt(r,n.map(o=>Math.cbrt(o)))}$.prototype.oklab=function(){return Vn(this._rgb)},Object.assign(B,{oklab:(...e)=>new $(...e,"oklab")}),E.format.oklab=Dn,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"oklab"),j(e)==="array"&&e.length===3)return"oklab"}});const vf=(e,t,r)=>{const n=e.oklab(),o=t.oklab();return new $(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"oklab")};ne.oklab=vf;const _f=(e,t,r)=>et(e,t,r,"oklch");ne.oklch=_f;const{pow:Yn,sqrt:Zn,PI:Jn,cos:Ia,sin:za,atan2:yf}=Math,wf=(e,t="lrgb",r=null)=>{const n=e.length;r||(r=Array.from(new Array(n)).map(()=>1));const o=n/r.reduce(function(l,h){return l+h});if(r.forEach((l,h)=>{r[h]*=o}),e=e.map(l=>new $(l)),t==="lrgb")return kf(e,r);const a=e.shift(),s=a.get(t),c=[];let i=0,u=0;for(let l=0;l{const d=l.get(t);f+=l.alpha()*r[h+1];for(let p=0;p=360;)h-=360;s[l]=h}else s[l]=s[l]/c[l];return f/=n,new $(s,t).alpha(f>.99999?1:f,!0)},kf=(e,t)=>{const r=e.length,n=[0,0,0,0];for(let o=0;o.9999999&&(n[3]=1),new $(En(n))},{pow:$f}=Math;function jt(e){let t="rgb",r=B("#ccc"),n=0,o=[0,1],a=[],s=[0,0],c=!1,i=[],u=!1,f=0,l=1,h=!1,d={},p=!0,v=1;const m=function(b){if(b=b||["#fff","#000"],b&&j(b)==="string"&&B.brewer&&B.brewer[b.toLowerCase()]&&(b=B.brewer[b.toLowerCase()]),j(b)==="array"){b.length===1&&(b=[b[0],b[0]]),b=b.slice(0);for(let _=0;_=c[k];)k++;return k-1}return 0};let R=b=>b,x=b=>b;const M=function(b,_){let k,y;if(_==null&&(_=!1),isNaN(b)||b===null)return r;_?y=b:c&&c.length>2?y=g(b)/(c.length-2):l!==f?y=(b-f)/(l-f):y=1,y=x(y),_||(y=R(y)),v!==1&&(y=$f(y,v)),y=s[0]+y*(1-s[0]-s[1]),y=Be(y,0,1);const q=Math.floor(y*1e4);if(p&&d[q])k=d[q];else{if(j(i)==="array")for(let H=0;H=A&&H===a.length-1){k=i[H];break}if(y>A&&yd={};m(e);const w=function(b){const _=B(M(b));return u&&_[u]?_[u]():_};return w.classes=function(b){if(b!=null){if(j(b)==="array")c=b,o=[b[0],b[b.length-1]];else{const _=B.analyze(o);b===0?c=[_.min,_.max]:c=B.limits(_,"e",b)}return w}return c},w.domain=function(b){if(!arguments.length)return o;f=b[0],l=b[b.length-1],a=[];const _=i.length;if(b.length===_&&f!==l)for(let k of Array.from(b))a.push((k-f)/(l-f));else{for(let k=0;k<_;k++)a.push(k/(_-1));if(b.length>2){const k=b.map((q,H)=>H/(b.length-1)),y=b.map(q=>(q-f)/(l-f));y.every((q,H)=>k[H]===q)||(x=q=>{if(q<=0||q>=1)return q;let H=0;for(;q>=y[H+1];)H++;const A=(q-y[H])/(y[H+1]-y[H]);return k[H]+A*(k[H+1]-k[H])})}}return o=[f,l],w},w.mode=function(b){return arguments.length?(t=b,N(),w):t},w.range=function(b,_){return m(b),w},w.out=function(b){return u=b,w},w.spread=function(b){return arguments.length?(n=b,w):n},w.correctLightness=function(b){return b==null&&(b=!0),h=b,N(),h?R=function(_){const k=M(0,!0).lab()[0],y=M(1,!0).lab()[0],q=k>y;let H=M(_,!0).lab()[0];const A=k+(y-k)*_;let I=H-A,K=0,D=1,U=20;for(;Math.abs(I)>.01&&U-- >0;)(function(){return q&&(I*=-1),I<0?(K=_,_+=(D-_)*.5):(D=_,_+=(K-_)*.5),H=M(_,!0).lab()[0],I=H-A})();return _}:R=_=>_,w},w.padding=function(b){return b!=null?(j(b)==="number"&&(b=[b,b]),s=b,w):s},w.colors=function(b,_){arguments.length<2&&(_="hex");let k=[];if(arguments.length===0)k=i.slice(0);else if(b===1)k=[w(.5)];else if(b>1){const y=o[0],q=o[1]-y;k=Cf(0,b).map(H=>w(y+H/(b-1)*q))}else{e=[];let y=[];if(c&&c.length>2)for(let q=1,H=c.length,A=1<=H;A?qH;A?q++:q--)y.push((c[q-1]+c[q])*.5);else y=o;k=y.map(q=>w(q))}return B[_]&&(k=k.map(y=>y[_]())),k},w.cache=function(b){return b!=null?(p=b,w):p},w.gamma=function(b){return b!=null?(v=b,w):v},w.nodata=function(b){return b!=null?(r=B(b),w):r},w}function Cf(e,t,r){let n=[],o=ea;o?s++:s--)n.push(s);return n}const xf=function(e){let t=[1,1];for(let r=1;rnew $(a)),e.length===2)[r,n]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>r[c]+a*(n[c]-r[c]));return new $(s,"lab")};else if(e.length===3)[r,n,o]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>(1-a)*(1-a)*r[c]+2*(1-a)*a*n[c]+a*a*o[c]);return new $(s,"lab")};else if(e.length===4){let a;[r,n,o,a]=e.map(s=>s.lab()),t=function(s){const c=[0,1,2].map(i=>(1-s)*(1-s)*(1-s)*r[i]+3*(1-s)*(1-s)*s*n[i]+3*(1-s)*s*s*o[i]+s*s*s*a[i]);return new $(c,"lab")}}else if(e.length>=5){let a,s,c;a=e.map(i=>i.lab()),c=e.length-1,s=xf(c),t=function(i){const u=1-i,f=[0,1,2].map(l=>a.reduce((h,d,p)=>h+s[p]*u**(c-p)*i**p*d[l],0));return new $(f,"lab")}}else throw new RangeError("No point in running bezier with only one color.");return t},Hf=e=>{const t=Rf(e);return t.scale=()=>jt(t),t},{round:Fa}=Math;$.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Fa)},$.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,r)=>r<3?e===!1?t:Fa(t):t)},Object.assign(B,{rgb:(...e)=>new $(...e,"rgb")}),E.format.rgb=(...e)=>{const t=T(e,"rgba");return t[3]===void 0&&(t[3]=1),t},E.autodetect.push({p:3,test:(...e)=>{if(e=T(e,"rgba"),j(e)==="array"&&(e.length===3||e.length===4&&j(e[3])=="number"&&e[3]>=0&&e[3]<=1))return"rgb"}});const pe=(e,t,r)=>{if(!pe[r])throw new Error("unknown blend mode "+r);return pe[r](e,t)},Te=e=>(t,r)=>{const n=B(r).rgb(),o=B(t).rgb();return B.rgb(e(n,o))},Se=e=>(t,r)=>{const n=[];return n[0]=e(t[0],r[0]),n[1]=e(t[1],r[1]),n[2]=e(t[2],r[2]),n},qf=e=>e,Mf=(e,t)=>e*t/255,Of=(e,t)=>e>t?t:e,Nf=(e,t)=>e>t?e:t,Af=(e,t)=>255*(1-(1-e/255)*(1-t/255)),Lf=(e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)),Ef=(e,t)=>255*(1-(1-t/255)/(e/255)),Tf=(e,t)=>e===255?255:(e=255*(t/255)/(1-e/255),e>255?255:e);pe.normal=Te(Se(qf)),pe.multiply=Te(Se(Mf)),pe.screen=Te(Se(Af)),pe.overlay=Te(Se(Lf)),pe.darken=Te(Se(Of)),pe.lighten=Te(Se(Nf)),pe.dodge=Te(Se(Tf)),pe.burn=Te(Se(Ef));const{pow:Sf,sin:Pf,cos:jf}=Math;function Bf(e=300,t=-1.5,r=1,n=1,o=[0,1]){let a=0,s;j(o)==="array"?s=o[1]-o[0]:(s=0,o=[o,o]);const c=function(i){const u=Ce*((e+120)/360+t*i),f=Sf(o[0]+s*i,n),h=(a!==0?r[0]+i*a:r)*f*(1-f)/2,d=jf(u),p=Pf(u),v=f+h*(-.14861*d+1.78277*p),m=f+h*(-.29227*d-.90649*p),g=f+h*(1.97294*d);return B(En([v*255,m*255,g*255,1]))};return c.start=function(i){return i==null?e:(e=i,c)},c.rotations=function(i){return i==null?t:(t=i,c)},c.gamma=function(i){return i==null?n:(n=i,c)},c.hue=function(i){return i==null?r:(r=i,j(r)==="array"?(a=r[1]-r[0],a===0&&(r=r[1])):a=0,c)},c.lightness=function(i){return i==null?o:(j(i)==="array"?(o=i,s=i[1]-i[0]):(o=[i,i],s=0),c)},c.scale=()=>B.scale(c),c.hue(r),c}const Gf="0123456789abcdef",{floor:If,random:zf}=Math,Ff=()=>{let e="#";for(let t=0;t<6;t++)e+=Gf.charAt(If(zf()*16));return new $(e,"hex")},{log:Xa,pow:Xf,floor:Kf,abs:Df}=Math;function Ka(e,t=null){const r={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return j(e)==="object"&&(e=Object.values(e)),e.forEach(n=>{t&&j(n)==="object"&&(n=n[t]),n!=null&&!isNaN(n)&&(r.values.push(n),r.sum+=n,nr.max&&(r.max=n),r.count+=1)}),r.domain=[r.min,r.max],r.limits=(n,o)=>Da(r,n,o),r}function Da(e,t="equal",r=7){j(e)=="array"&&(e=Ka(e));const{min:n,max:o}=e,a=e.values.sort((c,i)=>c-i);if(r===1)return[n,o];const s=[];if(t.substr(0,1)==="c"&&(s.push(n),s.push(o)),t.substr(0,1)==="e"){s.push(n);for(let c=1;c 0");const c=Math.LOG10E*Xa(n),i=Math.LOG10E*Xa(o);s.push(n);for(let u=1;u200&&(l=!1)}const p={};for(let m=0;mm-g),s.push(v[0]);for(let m=1;m{e=new $(e),t=new $(t);const r=e.luminance(),n=t.luminance();return r>n?(r+.05)/(n+.05):(n+.05)/(r+.05)};/** - * @license - * - * The APCA contrast prediction algorithm is based of the formulas published - * in the APCA-1.0.98G specification by Myndex. The specification is available at: - * https://raw.githubusercontent.com/Myndex/apca-w3/master/images/APCAw3_0.1.17_APCA0.0.98G.svg - * - * Note that the APCA implementation is still beta, so please update to - * future versions of chroma.js when they become available. - * - * You can read more about the APCA Readability Criterion at - * https://readtech.org/ARC/ - */const Va=.027,Yf=5e-4,Zf=.1,Ya=1.14,Bt=.022,Za=1.414,Jf=(e,t)=>{e=new $(e),t=new $(t),e.alpha()<1&&(e=Ue(t,e,e.alpha(),"rgb"));const r=Ja(...e.rgb()),n=Ja(...t.rgb()),o=r>=Bt?r:r+Math.pow(Bt-r,Za),a=n>=Bt?n:n+Math.pow(Bt-n,Za),s=Math.pow(a,.56)-Math.pow(o,.57),c=Math.pow(a,.65)-Math.pow(o,.62),i=Math.abs(a-o)0?i-Va:i+Va)*100};function Ja(e,t,r){return .2126729*Math.pow(e/255,2.4)+.7151522*Math.pow(t/255,2.4)+.072175*Math.pow(r/255,2.4)}const{sqrt:Re,pow:Z,min:Wf,max:Uf,atan2:Wa,abs:Ua,cos:Gt,sin:Qa,exp:Qf,PI:ec}=Math;function el(e,t,r=1,n=1,o=1){var a=function(le){return 360*le/(2*ec)},s=function(le){return 2*ec*le/360};e=new $(e),t=new $(t);const[c,i,u]=Array.from(e.lab()),[f,l,h]=Array.from(t.lab()),d=(c+f)/2,p=Re(Z(i,2)+Z(u,2)),v=Re(Z(l,2)+Z(h,2)),m=(p+v)/2,g=.5*(1-Re(Z(m,7)/(Z(m,7)+Z(25,7)))),R=i*(1+g),x=l*(1+g),M=Re(Z(R,2)+Z(u,2)),N=Re(Z(x,2)+Z(h,2)),w=(M+N)/2,b=a(Wa(u,R)),_=a(Wa(h,x)),k=b>=0?b:b+360,y=_>=0?_:_+360,q=Ua(k-y)>180?(k+y+360)/2:(k+y)/2,H=1-.17*Gt(s(q-30))+.24*Gt(s(2*q))+.32*Gt(s(3*q+6))-.2*Gt(s(4*q-63));let A=y-k;A=Ua(A)<=180?A:y<=k?A+360:A-360,A=2*Re(M*N)*Qa(s(A)/2);const I=f-c,K=N-M,D=1+.015*Z(d-50,2)/Re(20+Z(d-50,2)),U=1+.045*w,ge=1+.015*w*H,ye=30*Qf(-Z((q-275)/25,2)),fe=-(2*Re(Z(w,7)/(Z(w,7)+Z(25,7))))*Qa(2*s(ye)),qe=Re(Z(I/(r*D),2)+Z(K/(n*U),2)+Z(A/(o*ge),2)+fe*(K/(n*U))*(A/(o*ge)));return Uf(0,Wf(100,qe))}function tl(e,t,r="lab"){e=new $(e),t=new $(t);const n=e.get(r),o=t.get(r);let a=0;for(let s in n){const c=(n[s]||0)-(o[s]||0);a+=c*c}return Math.sqrt(a)}const rl=(...e)=>{try{return new $(...e),!0}catch{return!1}},nl={cool(){return jt([B.hsl(180,1,.9),B.hsl(250,.7,.4)])},hot(){return jt(["#000","#f00","#ff0","#fff"]).mode("rgb")}},Wn={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]},tc=Object.keys(Wn),rc=new Map(tc.map(e=>[e.toLowerCase(),e])),ol=typeof Proxy=="function"?new Proxy(Wn,{get(e,t){const r=t.toLowerCase();if(rc.has(r))return e[rc.get(r)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tc)}}):Wn,sl=(...e)=>{e=T(e,"cmyk");const[t,r,n,o]=e,a=e.length>4?e[4]:1;return o===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-o),r>=1?0:255*(1-r)*(1-o),n>=1?0:255*(1-n)*(1-o),a]},{max:nc}=Math,al=(...e)=>{let[t,r,n]=T(e,"rgb");t=t/255,r=r/255,n=n/255;const o=1-nc(t,nc(r,n)),a=o<1?1/(1-o):0,s=(1-t-o)*a,c=(1-r-o)*a,i=(1-n-o)*a;return[s,c,i,o]};$.prototype.cmyk=function(){return al(this._rgb)},Object.assign(B,{cmyk:(...e)=>new $(...e,"cmyk")}),E.format.cmyk=sl,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"cmyk"),j(e)==="array"&&e.length===4)return"cmyk"}});const cl=(...e)=>{const t=T(e,"hsla");let r=Je(e)||"lsa";return t[0]=ie(t[0]||0)+"deg",t[1]=ie(t[1]*100)+"%",t[2]=ie(t[2]*100)+"%",r==="hsla"||t.length>3&&t[3]<1?(t[3]="/ "+(t.length>3?t[3]:1),r="hsla"):t.length=3,`${r.substr(0,3)}(${t.join(" ")})`},il=(...e)=>{const t=T(e,"lab");let r=Je(e)||"lab";return t[0]=ie(t[0])+"%",t[1]=ie(t[1]),t[2]=ie(t[2]),r==="laba"||t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(" ")})`},ul=(...e)=>{const t=T(e,"lch");let r=Je(e)||"lab";return t[0]=ie(t[0])+"%",t[1]=ie(t[1]),t[2]=isNaN(t[2])?"none":ie(t[2])+"deg",r==="lcha"||t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(" ")})`},fl=(...e)=>{const t=T(e,"lab");return t[0]=ie(t[0]*100)+"%",t[1]=Tn(t[1]),t[2]=Tn(t[2]),t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(" ")})`},oc=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),[a,s,c]=Vn(t,r,n),[i,u,f]=ja(a,s,c);return[i,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]},ll=(...e)=>{const t=T(e,"lch");return t[0]=ie(t[0]*100)+"%",t[1]=Tn(t[1]),t[2]=isNaN(t[2])?"none":ie(t[2])+"deg",t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(" ")})`},{round:Un}=Math,hl=(...e)=>{const t=T(e,"rgba");let r=Je(e)||"rgb";if(r.substr(0,3)==="hsl")return cl(Ga(t),r);if(r.substr(0,3)==="lab"){const n=dt();xe("d50");const o=il(Bn(t),r);return xe(n),o}if(r.substr(0,3)==="lch"){const n=dt();xe("d50");const o=ul(Fn(t),r);return xe(n),o}return r.substr(0,5)==="oklab"?fl(Vn(t)):r.substr(0,5)==="oklch"?ll(oc(t)):(t[0]=Un(t[0]),t[1]=Un(t[1]),t[2]=Un(t[2]),(r==="rgba"||t.length>3&&t[3]<1)&&(t[3]="/ "+(t.length>3?t[3]:1),r="rgba"),`${r.substr(0,3)}(${t.slice(0,r==="rgb"?3:4).join(" ")})`)},sc=(...e)=>{e=T(e,"lch");const[t,r,n,...o]=e,[a,s,c]=Pa(t,r,n),[i,u,f]=Dn(a,s,c);return[i,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]},He=/((?:-?\d+)|(?:-?\d+(?:\.\d+)?)%|none)/.source,me=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%?)|none)/.source,It=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%)|none)/.source,ue=/\s*/.source,rt=/\s+/.source,Qn=/\s*,\s*/.source,zt=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?)|none)/.source,nt=/\s*(?:\/\s*((?:[01]|[01]?\.\d+)|\d+(?:\.\d+)?%))?/.source,ac=new RegExp("^rgba?\\("+ue+[He,He,He].join(rt)+nt+"\\)$"),cc=new RegExp("^rgb\\("+ue+[He,He,He].join(Qn)+ue+"\\)$"),ic=new RegExp("^rgba\\("+ue+[He,He,He,me].join(Qn)+ue+"\\)$"),uc=new RegExp("^hsla?\\("+ue+[zt,It,It].join(rt)+nt+"\\)$"),fc=new RegExp("^hsl?\\("+ue+[zt,It,It].join(Qn)+ue+"\\)$"),lc=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,hc=new RegExp("^lab\\("+ue+[me,me,me].join(rt)+nt+"\\)$"),dc=new RegExp("^lch\\("+ue+[me,me,zt].join(rt)+nt+"\\)$"),bc=new RegExp("^oklab\\("+ue+[me,me,me].join(rt)+nt+"\\)$"),pc=new RegExp("^oklch\\("+ue+[me,me,zt].join(rt)+nt+"\\)$"),{round:mc}=Math,ot=e=>e.map((t,r)=>r<=2?Be(mc(t),0,255):t),J=(e,t=0,r=100,n=!1)=>(typeof e=="string"&&e.endsWith("%")&&(e=parseFloat(e.substring(0,e.length-1))/100,n?e=t+(e+1)*.5*(r-t):e=t+e*(r-t)),+e),oe=(e,t)=>e==="none"?t:e,eo=e=>{if(e=e.toLowerCase().trim(),e==="transparent")return[0,0,0,0];let t;if(E.format.named)try{return E.format.named(e)}catch{}if((t=e.match(ac))||(t=e.match(cc))){let r=t.slice(1,4);for(let o=0;o<3;o++)r[o]=+J(oe(r[o],0),0,255);r=ot(r);const n=t[4]!==void 0?+J(t[4],0,1):1;return r[3]=n,r}if(t=e.match(ic)){const r=t.slice(1,5);for(let n=0;n<4;n++)r[n]=+J(r[n],0,255);return r}if((t=e.match(uc))||(t=e.match(fc))){const r=t.slice(1,4);r[0]=+oe(r[0].replace("deg",""),0),r[1]=+J(oe(r[1],0),0,100)*.01,r[2]=+J(oe(r[2],0),0,100)*.01;const n=ot(Kn(r)),o=t[4]!==void 0?+J(t[4],0,1):1;return n[3]=o,n}if(t=e.match(lc)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=Kn(r);for(let o=0;o<3;o++)n[o]=mc(n[o]);return n[3]=+t[4],n}if(t=e.match(hc)){const r=t.slice(1,4);r[0]=J(oe(r[0],0),0,100),r[1]=J(oe(r[1],0),-125,125,!0),r[2]=J(oe(r[2],0),-125,125,!0);const n=dt();xe("d50");const o=ot(Pn(r));xe(n);const a=t[4]!==void 0?+J(t[4],0,1):1;return o[3]=a,o}if(t=e.match(dc)){const r=t.slice(1,4);r[0]=J(r[0],0,100),r[1]=J(oe(r[1],0),0,150,!1),r[2]=+oe(r[2].replace("deg",""),0);const n=dt();xe("d50");const o=ot(zn(r));xe(n);const a=t[4]!==void 0?+J(t[4],0,1):1;return o[3]=a,o}if(t=e.match(bc)){const r=t.slice(1,4);r[0]=J(oe(r[0],0),0,1),r[1]=J(oe(r[1],0),-.4,.4,!0),r[2]=J(oe(r[2],0),-.4,.4,!0);const n=ot(Dn(r)),o=t[4]!==void 0?+J(t[4],0,1):1;return n[3]=o,n}if(t=e.match(pc)){const r=t.slice(1,4);r[0]=J(oe(r[0],0),0,1),r[1]=J(oe(r[1],0),0,.4,!1),r[2]=+oe(r[2].replace("deg",""),0);const n=ot(sc(r)),o=t[4]!==void 0?+J(t[4],0,1):1;return n[3]=o,n}};eo.test=e=>ac.test(e)||uc.test(e)||hc.test(e)||dc.test(e)||bc.test(e)||pc.test(e)||cc.test(e)||ic.test(e)||fc.test(e)||lc.test(e)||e==="transparent",$.prototype.css=function(e){return hl(this._rgb,e)};const dl=(...e)=>new $(...e,"css");B.css=dl,E.format.css=eo,E.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&j(e)==="string"&&eo.test(e))return"css"}}),E.format.gl=(...e)=>{const t=T(e,"rgba");return t[0]*=255,t[1]*=255,t[2]*=255,t};const bl=(...e)=>new $(...e,"gl");B.gl=bl,$.prototype.gl=function(){const e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},$.prototype.hex=function(e){return Ea(this._rgb,e)};const pl=(...e)=>new $(...e,"hex");B.hex=pl,E.format.hex=La,E.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&j(e)==="string"&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return"hex"}});const{log:Ft}=Math,gc=e=>{const t=e/100;let r,n,o;return t<66?(r=255,n=t<6?0:-155.25485562709179-.44596950469579133*(n=t-2)+104.49216199393888*Ft(n),o=t<20?0:-254.76935184120902+.8274096064007395*(o=t-10)+115.67994401066147*Ft(o)):(r=351.97690566805693+.114206453784165*(r=t-55)-40.25366309332127*Ft(r),n=325.4494125711974+.07943456536662342*(n=t-50)-28.0852963507957*Ft(n),o=255),[r,n,o,1]},{round:ml}=Math,gl=(...e)=>{const t=T(e,"rgb"),r=t[0],n=t[2];let o=1e3,a=4e4;const s=.4;let c;for(;a-o>s;){c=(a+o)*.5;const i=gc(c);i[2]/i[0]>=n/r?a=c:o=c}return ml(c)};$.prototype.temp=$.prototype.kelvin=$.prototype.temperature=function(){return gl(this._rgb)};const to=(...e)=>new $(...e,"temp");Object.assign(B,{temp:to,kelvin:to,temperature:to}),E.format.temp=E.format.kelvin=E.format.temperature=gc,$.prototype.oklch=function(){return oc(this._rgb)},Object.assign(B,{oklch:(...e)=>new $(...e,"oklch")}),E.format.oklch=sc,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"oklch"),j(e)==="array"&&e.length===3)return"oklch"}}),Object.assign(B,{analyze:Ka,average:wf,bezier:Hf,blend:pe,brewer:ol,Color:$,colors:We,contrast:Vf,contrastAPCA:Jf,cubehelix:Bf,deltaE:el,distance:tl,input:E,interpolate:Ue,limits:Da,mix:Ue,random:Ff,scale:jt,scales:nl,valid:rl});function vl(e){return+`${Math.ceil(`${e}e+2`)}e-2`}const vc=e=>{const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},_c=(e,t,r)=>{const n=e/255,o=t/255,a=r/255,s=Math.min(n,o,a),c=Math.max(n,o,a),i=c-s;let u=0,f=0,l=0;return i===0?u=0:c===n?u=(o-a)/i%6:c===o?u=(a-n)/i+2:u=(n-o)/i+4,u=Math.round(u*60),u<0&&(u+=360),l=(c+s)/2,f=i===0?0:i/(1-Math.abs(2*l-1)),f=+(f*100).toFixed(1),l=+(l*100).toFixed(1),[u,f,Math.round(l)]},_l=(e,t,r,n)=>{const o=r/100,a=t*Math.min(o,1-o)/100,s=d=>{const p=(d+e/30)%12,v=o-a*Math.max(Math.min(p-3,9-p,1),-1);return Math.round(255*v).toString(16).padStart(2,"0").toUpperCase()},c=s(0),i=s(8),u=s(4),l=((d,p,v)=>Math.min(Math.max(d,p),v))(n,0,1),h=Math.round(l*255).toString(16).padStart(2,"0").toUpperCase();return`#${c}${i}${u}${h}`},yl=(e,t,r=1)=>{const n=vc(e),o=vc(t==="white"?"#FFFFFF":t==="black"?"#000000":t),a=n.map((u,f)=>[(u-o[f])/(255-o[f]),(u-o[f])/(0-o[f])]),s=vl(Math.max(...a.flat().filter(u=>/^-?\d+\.?\d*$/.test(u)))),c=n.map((u,f)=>Math.round((u-o[f]+o[f]*s)/s));if(c.includes(Number.NaN)){const u=_c(n[0],n[1],n[2]);return{h:u[0],s:Math.round(u[1]*r),l:u[2],a:1}}const i=_c(c[0],c[1],c[2]);return{h:i[0],s:Math.round(i[1]*r),l:i[2],a:s}},ro={backgroundColor:"gray",colorSpace:"OKLCH",colorSmoothing:!1,formula:"wcag2",output:"HEX",colors:{gray:[X(215,20,90),X(215,8,50),X(215,6,25)],red:[X(358,100,58),X(350,100,30)],orange:[X(32,100,48),X(12,100,30)],yellow:[X(50,100,50),X(25,100,20)],lime:[X(100,68,50),X(115,86,25)],green:[X(163,87,42),X(168,100,25)],cyan:[X(185,80,45),X(200,98,35)],blue:[X(212,98,46),X(222,95,25)],purple:[X(258,94,64),X(265,100,35)],fuchsia:[X(295,56,50),X(285,80,25)],pink:[X(334,90,50),X(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function X(e,t,r){return B.hsl(e,t/100,r/100).hex()}function wl(e,t){const r=e.colorSpace,n=e.colorSmoothing,o=e.themes[t].ratios,a=new qa({name:"gray",colorKeys:e.colors.gray,colorspace:r,ratios:o,smooth:n}),s=new ae({name:"blue",colorKeys:e.colors.blue,colorspace:r,ratios:o,smooth:n}),c=new ae({name:"cyan",colorKeys:e.colors.cyan,colorspace:r,ratios:o,smooth:n}),i=new ae({name:"fuchsia",colorKeys:e.colors.fuchsia,colorspace:r,ratios:o,smooth:n}),u=new ae({name:"green",colorKeys:e.colors.green,colorspace:r,ratios:o,smooth:n}),f=new ae({name:"lime",colorKeys:e.colors.lime,colorspace:r,ratios:o,smooth:n}),l=new ae({name:"orange",colorKeys:e.colors.orange,colorspace:r,ratios:o,smooth:n}),h=new ae({name:"pink",colorKeys:e.colors.pink,colorspace:r,ratios:o,smooth:n}),d=new ae({name:"purple",colorKeys:e.colors.purple,colorspace:r,ratios:o,smooth:n}),p=new ae({name:"red",colorKeys:e.colors.red,colorspace:r,ratios:o,smooth:n}),v=new ae({name:"yellow",colorKeys:e.colors.yellow,colorspace:r,ratios:o,smooth:n}),m={gray:a,red:p,orange:l,yellow:v,lime:f,green:u,cyan:c,blue:s,purple:d,fuchsia:i,pink:h};return e.colors.custom&&(m.custom=new ae({name:"custom",colorKeys:e.colors.custom,colorspace:r,ratios:o,smooth:n})),new wu({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function yc(e){const t={};for(const r of Object.keys(e.themes))t[r]=wl(e,r);return t}function kl(e){ro.colors.custom=[e];const t=yc(ro);return Object.fromEntries(Object.entries(t).map(([r,n])=>{const o=n.find(s=>s&&s.name==="custom"),a=Object.fromEntries(o.values.map(({name:s,value:c})=>[s,c]));for(const[s,c]of Object.entries(a)){const i=yl(c,n[0].background);a[`alpha${s.charAt(0).toUpperCase()+s.slice(1)}`]=_l(i.h,i.s,i.l,i.a)}return[r,a]}))}return Fe.generateCustomColors=kl,Fe.generateThemesJson=yc,Fe.hslToHex=X,Fe.leonardoConfig=ro,Object.defineProperty(Fe,Symbol.toStringTag,{value:"Module"}),Fe})({}); +var CompoundTheme=(function(Fe){"use strict";const Xe=(e,t=0,r=1)=>Zt(Jt(t,e),r),Yt=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=Xe(e[t],0,255)):t===3&&(e[t]=Xe(e[t],0,1));return e},co={};for(let e of["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"])co[`[object ${e}]`]=e.toLowerCase();function P(e){return co[Object.prototype.toString.call(e)]||"object"}const j=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):P(e[0])=="object"&&t?t.split("").filter(r=>e[0][r]!==void 0).map(r=>e[0][r]):e[0],pt=e=>{if(e.length<2)return null;const t=e.length-1;return P(e[t])=="string"?e[t].toLowerCase():null},{PI:mt,min:Zt,max:Jt}=Math,we=mt*2,Wt=mt/3,Ac=mt/180,Lc=180/mt,L={format:{},autodetect:[]};let $=class{constructor(...t){const r=this;if(P(t[0])==="object"&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];let n=pt(t),o=!1;if(!n){o=!0,L.sorted||(L.autodetect=L.autodetect.sort((a,s)=>s.p-a.p),L.sorted=!0);for(let a of L.autodetect)if(n=a.test(...t),n)break}if(L.format[n]){const a=L.format[n].apply(null,o?t:t.slice(0,-1));r._rgb=Yt(a)}else throw new Error("unknown format: "+t);r._rgb.length===3&&r._rgb.push(1)}toString(){return P(this.hex)=="function"?this.hex():`[${this._rgb.join(",")}]`}};const Ec="2.6.0",O=(...e)=>new O.Color(...e);O.Color=$,O.version=Ec;const Tc=(...e)=>{e=j(e,"cmyk");const[t,r,n,o]=e,a=e.length>4?e[4]:1;return o===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-o),r>=1?0:255*(1-r)*(1-o),n>=1?0:255*(1-n)*(1-o),a]},{max:io}=Math,Sc=(...e)=>{let[t,r,n]=j(e,"rgb");t=t/255,r=r/255,n=n/255;const o=1-io(t,io(r,n)),a=o<1?1/(1-o):0,s=(1-t-o)*a,c=(1-r-o)*a,i=(1-n-o)*a;return[s,c,i,o]};$.prototype.cmyk=function(){return Sc(this._rgb)},O.cmyk=(...e)=>new $(...e,"cmyk"),L.format.cmyk=Tc,L.autodetect.push({p:2,test:(...e)=>{if(e=j(e,"cmyk"),P(e)==="array"&&e.length===4)return"cmyk"}});const Ut=e=>Math.round(e*100)/100,Pc=(...e)=>{const t=j(e,"hsla");let r=pt(e)||"lsa";return t[0]=Ut(t[0]||0),t[1]=Ut(t[1]*100)+"%",t[2]=Ut(t[2]*100)+"%",r==="hsla"||t.length>3&&t[3]<1?(t[3]=t.length>3?t[3]:1,r="hsla"):t.length=3,`${r}(${t.join(",")})`},uo=(...e)=>{e=j(e,"rgba");let[t,r,n]=e;t/=255,r/=255,n/=255;const o=Zt(t,r,n),a=Jt(t,r,n),s=(a+o)/2;let c,i;return a===o?(c=0,i=Number.NaN):c=s<.5?(a-o)/(a+o):(a-o)/(2-a-o),t==a?i=(r-n)/(a-o):r==a?i=2+(n-t)/(a-o):n==a&&(i=4+(t-r)/(a-o)),i*=60,i<0&&(i+=360),e.length>3&&e[3]!==void 0?[i,c,s,e[3]]:[i,c,s]},{round:Qt}=Math,jc=(...e)=>{const t=j(e,"rgba");let r=pt(e)||"rgb";return r.substr(0,3)=="hsl"?Pc(uo(t),r):(t[0]=Qt(t[0]),t[1]=Qt(t[1]),t[2]=Qt(t[2]),(r==="rgba"||t.length>3&&t[3]<1)&&(t[3]=t.length>3?t[3]:1,r="rgba"),`${r}(${t.slice(0,r==="rgb"?3:4).join(",")})`)},{round:er}=Math,tr=(...e)=>{e=j(e,"hsl");const[t,r,n]=e;let o,a,s;if(r===0)o=a=s=n*255;else{const c=[0,0,0],i=[0,0,0],u=n<.5?n*(1+r):n+r-n*r,l=2*n-u,f=t/360;c[0]=f+1/3,c[1]=f,c[2]=f-1/3;for(let h=0;h<3;h++)c[h]<0&&(c[h]+=1),c[h]>1&&(c[h]-=1),6*c[h]<1?i[h]=l+(u-l)*6*c[h]:2*c[h]<1?i[h]=u:3*c[h]<2?i[h]=l+(u-l)*(2/3-c[h])*6:i[h]=l;[o,a,s]=[er(i[0]*255),er(i[1]*255),er(i[2]*255)]}return e.length>3?[o,a,s,e[3]]:[o,a,s,1]},fo=/^rgb\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*\)$/,lo=/^rgba\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*([01]|[01]?\.\d+)\)$/,ho=/^rgb\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,bo=/^rgba\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,po=/^hsl\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,mo=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,{round:go}=Math,rr=e=>{e=e.toLowerCase().trim();let t;if(L.format.named)try{return L.format.named(e)}catch{}if(t=e.match(fo)){const r=t.slice(1,4);for(let n=0;n<3;n++)r[n]=+r[n];return r[3]=1,r}if(t=e.match(lo)){const r=t.slice(1,5);for(let n=0;n<4;n++)r[n]=+r[n];return r}if(t=e.match(ho)){const r=t.slice(1,4);for(let n=0;n<3;n++)r[n]=go(r[n]*2.55);return r[3]=1,r}if(t=e.match(bo)){const r=t.slice(1,5);for(let n=0;n<3;n++)r[n]=go(r[n]*2.55);return r[3]=+r[3],r}if(t=e.match(po)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=tr(r);return n[3]=1,n}if(t=e.match(mo)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=tr(r);return n[3]=+t[4],n}};rr.test=e=>fo.test(e)||lo.test(e)||ho.test(e)||bo.test(e)||po.test(e)||mo.test(e),$.prototype.css=function(e){return jc(this._rgb,e)},O.css=(...e)=>new $(...e,"css"),L.format.css=rr,L.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&P(e)==="string"&&rr.test(e))return"css"}}),L.format.gl=(...e)=>{const t=j(e,"rgba");return t[0]*=255,t[1]*=255,t[2]*=255,t},O.gl=(...e)=>new $(...e,"gl"),$.prototype.gl=function(){const e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]};const{floor:Bc}=Math,Gc=(...e)=>{e=j(e,"hcg");let[t,r,n]=e,o,a,s;n=n*255;const c=r*255;if(r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const i=Bc(t),u=t-i,l=n*(1-r),f=l+c*(1-u),h=l+c*u,d=l+c;switch(i){case 0:[o,a,s]=[d,h,l];break;case 1:[o,a,s]=[f,d,l];break;case 2:[o,a,s]=[l,d,h];break;case 3:[o,a,s]=[l,f,d];break;case 4:[o,a,s]=[h,l,d];break;case 5:[o,a,s]=[d,l,f];break}}return[o,a,s,e.length>3?e[3]:1]},Ic=(...e)=>{const[t,r,n]=j(e,"rgb"),o=Zt(t,r,n),a=Jt(t,r,n),s=a-o,c=s*100/255,i=o/(255-s)*100;let u;return s===0?u=Number.NaN:(t===a&&(u=(r-n)/s),r===a&&(u=2+(n-t)/s),n===a&&(u=4+(t-r)/s),u*=60,u<0&&(u+=360)),[u,c,i]};$.prototype.hcg=function(){return Ic(this._rgb)},O.hcg=(...e)=>new $(...e,"hcg"),L.format.hcg=Gc,L.autodetect.push({p:1,test:(...e)=>{if(e=j(e,"hcg"),P(e)==="array"&&e.length===3)return"hcg"}});const zc=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,Fc=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,vo=e=>{if(e.match(zc)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const t=parseInt(e,16),r=t>>16,n=t>>8&255,o=t&255;return[r,n,o,1]}if(e.match(Fc)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);const t=parseInt(e,16),r=t>>24&255,n=t>>16&255,o=t>>8&255,a=Math.round((t&255)/255*100)/100;return[r,n,o,a]}throw new Error(`unknown hex color: ${e}`)},{round:gt}=Math,_o=(...e)=>{let[t,r,n,o]=j(e,"rgba"),a=pt(e)||"auto";o===void 0&&(o=1),a==="auto"&&(a=o<1?"rgba":"rgb"),t=gt(t),r=gt(r),n=gt(n);let c="000000"+(t<<16|r<<8|n).toString(16);c=c.substr(c.length-6);let i="0"+gt(o*255).toString(16);switch(i=i.substr(i.length-2),a.toLowerCase()){case"rgba":return`#${c}${i}`;case"argb":return`#${i}${c}`;default:return`#${c}`}};$.prototype.hex=function(e){return _o(this._rgb,e)},O.hex=(...e)=>new $(...e,"hex"),L.format.hex=vo,L.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&P(e)==="string"&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return"hex"}});const{cos:Ke}=Math,Xc=(...e)=>{e=j(e,"hsi");let[t,r,n]=e,o,a,s;return isNaN(t)&&(t=0),isNaN(r)&&(r=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(s=(1-r)/3,o=(1+r*Ke(we*t)/Ke(Wt-we*t))/3,a=1-(s+o)):t<2/3?(t-=1/3,o=(1-r)/3,a=(1+r*Ke(we*t)/Ke(Wt-we*t))/3,s=1-(o+a)):(t-=2/3,a=(1-r)/3,s=(1+r*Ke(we*t)/Ke(Wt-we*t))/3,o=1-(a+s)),o=Xe(n*o*3),a=Xe(n*a*3),s=Xe(n*s*3),[o*255,a*255,s*255,e.length>3?e[3]:1]},{min:Kc,sqrt:Dc,acos:Vc}=Math,Yc=(...e)=>{let[t,r,n]=j(e,"rgb");t/=255,r/=255,n/=255;let o;const a=Kc(t,r,n),s=(t+r+n)/3,c=s>0?1-a/s:0;return c===0?o=NaN:(o=(t-r+(t-n))/2,o/=Dc((t-r)*(t-r)+(t-n)*(r-n)),o=Vc(o),n>r&&(o=we-o),o/=we),[o*360,c,s]};$.prototype.hsi=function(){return Yc(this._rgb)},O.hsi=(...e)=>new $(...e,"hsi"),L.format.hsi=Xc,L.autodetect.push({p:2,test:(...e)=>{if(e=j(e,"hsi"),P(e)==="array"&&e.length===3)return"hsi"}}),$.prototype.hsl=function(){return uo(this._rgb)},O.hsl=(...e)=>new $(...e,"hsl"),L.format.hsl=tr,L.autodetect.push({p:2,test:(...e)=>{if(e=j(e,"hsl"),P(e)==="array"&&e.length===3)return"hsl"}});const{floor:Zc}=Math,Jc=(...e)=>{e=j(e,"hsv");let[t,r,n]=e,o,a,s;if(n*=255,r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const c=Zc(t),i=t-c,u=n*(1-r),l=n*(1-r*i),f=n*(1-r*(1-i));switch(c){case 0:[o,a,s]=[n,f,u];break;case 1:[o,a,s]=[l,n,u];break;case 2:[o,a,s]=[u,n,f];break;case 3:[o,a,s]=[u,l,n];break;case 4:[o,a,s]=[f,u,n];break;case 5:[o,a,s]=[n,u,l];break}}return[o,a,s,e.length>3?e[3]:1]},{min:Wc,max:Uc}=Math,Qc=(...e)=>{e=j(e,"rgb");let[t,r,n]=e;const o=Wc(t,r,n),a=Uc(t,r,n),s=a-o;let c,i,u;return u=a/255,a===0?(c=Number.NaN,i=0):(i=s/a,t===a&&(c=(r-n)/s),r===a&&(c=2+(n-t)/s),n===a&&(c=4+(t-r)/s),c*=60,c<0&&(c+=360)),[c,i,u]};$.prototype.hsv=function(){return Qc(this._rgb)},O.hsv=(...e)=>new $(...e,"hsv"),L.format.hsv=Jc,L.autodetect.push({p:2,test:(...e)=>{if(e=j(e,"hsv"),P(e)==="array"&&e.length===3)return"hsv"}});const se={Kn:18,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452},{pow:e0}=Math,yo=(...e)=>{e=j(e,"lab");const[t,r,n]=e;let o,a,s,c,i,u;return a=(t+16)/116,o=isNaN(r)?a:a+r/500,s=isNaN(n)?a:a-n/200,a=se.Yn*or(a),o=se.Xn*or(o),s=se.Zn*or(s),c=nr(3.2404542*o-1.5371385*a-.4985314*s),i=nr(-.969266*o+1.8760108*a+.041556*s),u=nr(.0556434*o-.2040259*a+1.0572252*s),[c,i,u,e.length>3?e[3]:1]},nr=e=>255*(e<=.00304?12.92*e:1.055*e0(e,1/2.4)-.055),or=e=>e>se.t1?e*e*e:se.t2*(e-se.t0),{pow:wo}=Math,ko=(...e)=>{const[t,r,n]=j(e,"rgb"),[o,a,s]=t0(t,r,n),c=116*a-16;return[c<0?0:c,500*(o-a),200*(a-s)]},sr=e=>(e/=255)<=.04045?e/12.92:wo((e+.055)/1.055,2.4),ar=e=>e>se.t3?wo(e,1/3):e/se.t2+se.t0,t0=(e,t,r)=>{e=sr(e),t=sr(t),r=sr(r);const n=ar((.4124564*e+.3575761*t+.1804375*r)/se.Xn),o=ar((.2126729*e+.7151522*t+.072175*r)/se.Yn),a=ar((.0193339*e+.119192*t+.9503041*r)/se.Zn);return[n,o,a]};$.prototype.lab=function(){return ko(this._rgb)},O.lab=(...e)=>new $(...e,"lab"),L.format.lab=yo,L.autodetect.push({p:2,test:(...e)=>{if(e=j(e,"lab"),P(e)==="array"&&e.length===3)return"lab"}});const{sin:r0,cos:n0}=Math,$o=(...e)=>{let[t,r,n]=j(e,"lch");return isNaN(n)&&(n=0),n=n*Ac,[t,n0(n)*r,r0(n)*r]},Co=(...e)=>{e=j(e,"lch");const[t,r,n]=e,[o,a,s]=$o(t,r,n),[c,i,u]=yo(o,a,s);return[c,i,u,e.length>3?e[3]:1]},o0=(...e)=>{const t=j(e,"hcl").reverse();return Co(...t)},{sqrt:s0,atan2:a0,round:c0}=Math,xo=(...e)=>{const[t,r,n]=j(e,"lab"),o=s0(r*r+n*n);let a=(a0(n,r)*Lc+360)%360;return c0(o*1e4)===0&&(a=Number.NaN),[t,o,a]},Ro=(...e)=>{const[t,r,n]=j(e,"rgb"),[o,a,s]=ko(t,r,n);return xo(o,a,s)};$.prototype.lch=function(){return Ro(this._rgb)},$.prototype.hcl=function(){return Ro(this._rgb).reverse()},O.lch=(...e)=>new $(...e,"lch"),O.hcl=(...e)=>new $(...e,"hcl"),L.format.lch=Co,L.format.hcl=o0,["lch","hcl"].forEach(e=>L.autodetect.push({p:2,test:(...t)=>{if(t=j(t,e),P(t)==="array"&&t.length===3)return e}}));const De={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};$.prototype.name=function(){const e=_o(this._rgb,"rgb");for(let t of Object.keys(De))if(De[t]===e)return t.toLowerCase();return e},L.format.named=e=>{if(e=e.toLowerCase(),De[e])return vo(De[e]);throw new Error("unknown color name: "+e)},L.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&P(e)==="string"&&De[e.toLowerCase()])return"named"}});const i0=e=>{if(P(e)=="number"&&e>=0&&e<=16777215){const t=e>>16,r=e>>8&255,n=e&255;return[t,r,n,1]}throw new Error("unknown num color: "+e)},u0=(...e)=>{const[t,r,n]=j(e,"rgb");return(t<<16)+(r<<8)+n};$.prototype.num=function(){return u0(this._rgb)},O.num=(...e)=>new $(...e,"num"),L.format.num=i0,L.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&P(e[0])==="number"&&e[0]>=0&&e[0]<=16777215)return"num"}});const{round:Ho}=Math;$.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Ho)},$.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,r)=>r<3?e===!1?t:Ho(t):t)},O.rgb=(...e)=>new $(...e,"rgb"),L.format.rgb=(...e)=>{const t=j(e,"rgba");return t[3]===void 0&&(t[3]=1),t},L.autodetect.push({p:3,test:(...e)=>{if(e=j(e,"rgba"),P(e)==="array"&&(e.length===3||e.length===4&&P(e[3])=="number"&&e[3]>=0&&e[3]<=1))return"rgb"}});const{log:vt}=Math,qo=e=>{const t=e/100;let r,n,o;return t<66?(r=255,n=t<6?0:-155.25485562709179-.44596950469579133*(n=t-2)+104.49216199393888*vt(n),o=t<20?0:-254.76935184120902+.8274096064007395*(o=t-10)+115.67994401066147*vt(o)):(r=351.97690566805693+.114206453784165*(r=t-55)-40.25366309332127*vt(r),n=325.4494125711974+.07943456536662342*(n=t-50)-28.0852963507957*vt(n),o=255),[r,n,o,1]},{round:f0}=Math,l0=(...e)=>{const t=j(e,"rgb"),r=t[0],n=t[2];let o=1e3,a=4e4;const s=.4;let c;for(;a-o>s;){c=(a+o)*.5;const i=qo(c);i[2]/i[0]>=n/r?a=c:o=c}return f0(c)};$.prototype.temp=$.prototype.kelvin=$.prototype.temperature=function(){return l0(this._rgb)},O.temp=O.kelvin=O.temperature=(...e)=>new $(...e,"temp"),L.format.temp=L.format.kelvin=L.format.temperature=qo;const{pow:_t,sign:h0}=Math,Mo=(...e)=>{e=j(e,"lab");const[t,r,n]=e,o=_t(t+.3963377774*r+.2158037573*n,3),a=_t(t-.1055613458*r-.0638541728*n,3),s=_t(t-.0894841775*r-1.291485548*n,3);return[255*cr(4.0767416621*o-3.3077115913*a+.2309699292*s),255*cr(-1.2684380046*o+2.6097574011*a-.3413193965*s),255*cr(-.0041960863*o-.7034186147*a+1.707614701*s),e.length>3?e[3]:1]};function cr(e){const t=Math.abs(e);return t>.0031308?(h0(e)||1)*(1.055*_t(t,.4166666666666667)-.055):e*12.92}const{cbrt:ir,pow:d0,sign:b0}=Math,Oo=(...e)=>{const[t,r,n]=j(e,"rgb"),[o,a,s]=[ur(t/255),ur(r/255),ur(n/255)],c=ir(.4122214708*o+.5363325363*a+.0514459929*s),i=ir(.2119034982*o+.6806995451*a+.1073969566*s),u=ir(.0883024619*o+.2817188376*a+.6299787005*s);return[.2104542553*c+.793617785*i-.0040720468*u,1.9779984951*c-2.428592205*i+.4505937099*u,.0259040371*c+.7827717662*i-.808675766*u]};function ur(e){const t=Math.abs(e);return t<.04045?e/12.92:(b0(e)||1)*d0((t+.055)/1.055,2.4)}$.prototype.oklab=function(){return Oo(this._rgb)},O.oklab=(...e)=>new $(...e,"oklab"),L.format.oklab=Mo,L.autodetect.push({p:3,test:(...e)=>{if(e=j(e,"oklab"),P(e)==="array"&&e.length===3)return"oklab"}});const p0=(...e)=>{e=j(e,"lch");const[t,r,n]=e,[o,a,s]=$o(t,r,n),[c,i,u]=Mo(o,a,s);return[c,i,u,e.length>3?e[3]:1]},m0=(...e)=>{const[t,r,n]=j(e,"rgb"),[o,a,s]=Oo(t,r,n);return xo(o,a,s)};$.prototype.oklch=function(){return m0(this._rgb)},O.oklch=(...e)=>new $(...e,"oklch"),L.format.oklch=p0,L.autodetect.push({p:3,test:(...e)=>{if(e=j(e,"oklch"),P(e)==="array"&&e.length===3)return"oklch"}}),$.prototype.alpha=function(e,t=!1){return e!==void 0&&P(e)==="number"?t?(this._rgb[3]=e,this):new $([this._rgb[0],this._rgb[1],this._rgb[2],e],"rgb"):this._rgb[3]},$.prototype.clipped=function(){return this._rgb._clipped||!1},$.prototype.darken=function(e=1){const t=this,r=t.lab();return r[0]-=se.Kn*e,new $(r,"lab").alpha(t.alpha(),!0)},$.prototype.brighten=function(e=1){return this.darken(-e)},$.prototype.darker=$.prototype.darken,$.prototype.brighter=$.prototype.brighten,$.prototype.get=function(e){const[t,r]=e.split("."),n=this[t]();if(r){const o=t.indexOf(r)-(t.substr(0,2)==="ok"?2:0);if(o>-1)return n[o];throw new Error(`unknown channel ${r} in mode ${t}`)}else return n};const{pow:g0}=Math,v0=1e-7,_0=20;$.prototype.luminance=function(e,t="rgb"){if(e!==void 0&&P(e)==="number"){if(e===0)return new $([0,0,0,this._rgb[3]],"rgb");if(e===1)return new $([255,255,255,this._rgb[3]],"rgb");let r=this.luminance(),n=_0;const o=(s,c)=>{const i=s.interpolate(c,.5,t),u=i.luminance();return Math.abs(e-u)e?o(s,i):o(i,c)},a=(r>e?o(new $([0,0,0]),this):o(this,new $([255,255,255]))).rgb();return new $([...a,this._rgb[3]])}return y0(...this._rgb.slice(0,3))};const y0=(e,t,r)=>(e=fr(e),t=fr(t),r=fr(r),.2126*e+.7152*t+.0722*r),fr=e=>(e/=255,e<=.03928?e/12.92:g0((e+.055)/1.055,2.4)),re={},ct=(e,t,r=.5,...n)=>{let o=n[0]||"lrgb";if(!re[o]&&!n.length&&(o=Object.keys(re)[0]),!re[o])throw new Error(`interpolation mode ${o} is not defined`);return P(e)!=="object"&&(e=new $(e)),P(t)!=="object"&&(t=new $(t)),re[o](e,t,r).alpha(e.alpha()+r*(t.alpha()-e.alpha()))};$.prototype.mix=$.prototype.interpolate=function(e,t=.5,...r){return ct(this,e,t,...r)},$.prototype.premultiply=function(e=!1){const t=this._rgb,r=t[3];return e?(this._rgb=[t[0]*r,t[1]*r,t[2]*r,r],this):new $([t[0]*r,t[1]*r,t[2]*r,r],"rgb")},$.prototype.saturate=function(e=1){const t=this,r=t.lch();return r[1]+=se.Kn*e,r[1]<0&&(r[1]=0),new $(r,"lch").alpha(t.alpha(),!0)},$.prototype.desaturate=function(e=1){return this.saturate(-e)},$.prototype.set=function(e,t,r=!1){const[n,o]=e.split("."),a=this[n]();if(o){const s=n.indexOf(o)-(n.substr(0,2)==="ok"?2:0);if(s>-1){if(P(t)=="string")switch(t.charAt(0)){case"+":a[s]+=+t;break;case"-":a[s]+=+t;break;case"*":a[s]*=+t.substr(1);break;case"/":a[s]/=+t.substr(1);break;default:a[s]=+t}else if(P(t)==="number")a[s]=t;else throw new Error("unsupported value for Color.set");const c=new $(a,n);return r?(this._rgb=c._rgb,this):c}throw new Error(`unknown channel ${o} in mode ${n}`)}else return a},$.prototype.tint=function(e=.5,...t){return ct(this,"white",e,...t)},$.prototype.shade=function(e=.5,...t){return ct(this,"black",e,...t)};const w0=(e,t,r)=>{const n=e._rgb,o=t._rgb;return new $(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"rgb")};re.rgb=w0;const{sqrt:lr,pow:Ve}=Math,k0=(e,t,r)=>{const[n,o,a]=e._rgb,[s,c,i]=t._rgb;return new $(lr(Ve(n,2)*(1-r)+Ve(s,2)*r),lr(Ve(o,2)*(1-r)+Ve(c,2)*r),lr(Ve(a,2)*(1-r)+Ve(i,2)*r),"rgb")};re.lrgb=k0;const $0=(e,t,r)=>{const n=e.lab(),o=t.lab();return new $(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"lab")};re.lab=$0;const Ye=(e,t,r,n)=>{let o,a;n==="hsl"?(o=e.hsl(),a=t.hsl()):n==="hsv"?(o=e.hsv(),a=t.hsv()):n==="hcg"?(o=e.hcg(),a=t.hcg()):n==="hsi"?(o=e.hsi(),a=t.hsi()):n==="lch"||n==="hcl"?(n="hcl",o=e.hcl(),a=t.hcl()):n==="oklch"&&(o=e.oklch().reverse(),a=t.oklch().reverse());let s,c,i,u,l,f;(n.substr(0,1)==="h"||n==="oklch")&&([s,i,l]=o,[c,u,f]=a);let h,d,b,_;return!isNaN(s)&&!isNaN(c)?(c>s&&c-s>180?_=c-(s+360):c180?_=c+360-s:_=c-s,d=s+r*_):isNaN(s)?isNaN(c)?d=Number.NaN:(d=c,(l==1||l==0)&&n!="hsv"&&(h=u)):(d=s,(f==1||f==0)&&n!="hsv"&&(h=i)),h===void 0&&(h=i+r*(u-i)),b=l+r*(f-l),n==="oklch"?new $([b,h,d],n):new $([d,h,b],n)},No=(e,t,r)=>Ye(e,t,r,"lch");re.lch=No,re.hcl=No;const C0=(e,t,r)=>{const n=e.num(),o=t.num();return new $(n+r*(o-n),"num")};re.num=C0;const x0=(e,t,r)=>Ye(e,t,r,"hcg");re.hcg=x0;const R0=(e,t,r)=>Ye(e,t,r,"hsi");re.hsi=R0;const H0=(e,t,r)=>Ye(e,t,r,"hsl");re.hsl=H0;const q0=(e,t,r)=>Ye(e,t,r,"hsv");re.hsv=q0;const M0=(e,t,r)=>{const n=e.oklab(),o=t.oklab();return new $(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"oklab")};re.oklab=M0;const O0=(e,t,r)=>Ye(e,t,r,"oklch");re.oklch=O0;const{pow:hr,sqrt:dr,PI:br,cos:Ao,sin:Lo,atan2:N0}=Math,A0=(e,t="lrgb",r=null)=>{const n=e.length;r||(r=Array.from(new Array(n)).map(()=>1));const o=n/r.reduce(function(f,h){return f+h});if(r.forEach((f,h)=>{r[h]*=o}),e=e.map(f=>new $(f)),t==="lrgb")return L0(e,r);const a=e.shift(),s=a.get(t),c=[];let i=0,u=0;for(let f=0;f{const d=f.get(t);l+=f.alpha()*r[h+1];for(let b=0;b=360;)h-=360;s[f]=h}else s[f]=s[f]/c[f];return l/=n,new $(s,t).alpha(l>.99999?1:l,!0)},L0=(e,t)=>{const r=e.length,n=[0,0,0,0];for(let o=0;o.9999999&&(n[3]=1),new $(Yt(n))},{pow:E0}=Math;function yt(e){let t="rgb",r=O("#ccc"),n=0,o=[0,1],a=[],s=[0,0],c=!1,i=[],u=!1,l=0,f=1,h=!1,d={},b=!0,_=1;const g=function(m){if(m=m||["#fff","#000"],m&&P(m)==="string"&&O.brewer&&O.brewer[m.toLowerCase()]&&(m=O.brewer[m.toLowerCase()]),P(m)==="array"){m.length===1&&(m=[m[0],m[0]]),m=m.slice(0);for(let p=0;p=c[y];)y++;return y-1}return 0};let H=m=>m,x=m=>m;const N=function(m,p){let y,w;if(p==null&&(p=!1),isNaN(m)||m===null)return r;p?w=m:c&&c.length>2?w=v(m)/(c.length-2):f!==l?w=(m-l)/(f-l):w=1,w=x(w),p||(w=H(w)),_!==1&&(w=E0(w,_)),w=s[0]+w*(1-s[0]-s[1]),w=Xe(w,0,1);const C=Math.floor(w*1e4);if(b&&d[C])y=d[C];else{if(P(i)==="array")for(let q=0;q=M&&q===a.length-1){y=i[q];break}if(w>M&&wd={};g(e);const R=function(m){const p=O(N(m));return u&&p[u]?p[u]():p};return R.classes=function(m){if(m!=null){if(P(m)==="array")c=m,o=[m[0],m[m.length-1]];else{const p=O.analyze(o);m===0?c=[p.min,p.max]:c=O.limits(p,"e",m)}return R}return c},R.domain=function(m){if(!arguments.length)return o;l=m[0],f=m[m.length-1],a=[];const p=i.length;if(m.length===p&&l!==f)for(let y of Array.from(m))a.push((y-l)/(f-l));else{for(let y=0;y2){const y=m.map((C,q)=>q/(m.length-1)),w=m.map(C=>(C-l)/(f-l));w.every((C,q)=>y[q]===C)||(x=C=>{if(C<=0||C>=1)return C;let q=0;for(;C>=w[q+1];)q++;const M=(C-w[q])/(w[q+1]-w[q]);return y[q]+M*(y[q+1]-y[q])})}}return o=[l,f],R},R.mode=function(m){return arguments.length?(t=m,A(),R):t},R.range=function(m,p){return g(m),R},R.out=function(m){return u=m,R},R.spread=function(m){return arguments.length?(n=m,R):n},R.correctLightness=function(m){return m==null&&(m=!0),h=m,A(),h?H=function(p){const y=N(0,!0).lab()[0],w=N(1,!0).lab()[0],C=y>w;let q=N(p,!0).lab()[0];const M=y+(w-y)*p;let S=q-M,X=0,D=1,U=20;for(;Math.abs(S)>.01&&U-- >0;)(function(){return C&&(S*=-1),S<0?(X=p,p+=(D-p)*.5):(D=p,p+=(X-p)*.5),q=N(p,!0).lab()[0],S=q-M})();return p}:H=p=>p,R},R.padding=function(m){return m!=null?(P(m)==="number"&&(m=[m,m]),s=m,R):s},R.colors=function(m,p){arguments.length<2&&(p="hex");let y=[];if(arguments.length===0)y=i.slice(0);else if(m===1)y=[R(.5)];else if(m>1){const w=o[0],C=o[1]-w;y=T0(0,m).map(q=>R(w+q/(m-1)*C))}else{e=[];let w=[];if(c&&c.length>2)for(let C=1,q=c.length,M=1<=q;M?Cq;M?C++:C--)w.push((c[C-1]+c[C])*.5);else w=o;y=w.map(C=>R(C))}return O[p]&&(y=y.map(w=>w[p]())),y},R.cache=function(m){return m!=null?(b=m,R):b},R.gamma=function(m){return m!=null?(_=m,R):_},R.nodata=function(m){return m!=null?(r=O(m),R):r},R}function T0(e,t,r){let n=[],o=ea;o?s++:s--)n.push(s);return n}const S0=function(e){let t=[1,1];for(let r=1;rnew $(a)),e.length===2)[r,n]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>r[c]+a*(n[c]-r[c]));return new $(s,"lab")};else if(e.length===3)[r,n,o]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>(1-a)*(1-a)*r[c]+2*(1-a)*a*n[c]+a*a*o[c]);return new $(s,"lab")};else if(e.length===4){let a;[r,n,o,a]=e.map(s=>s.lab()),t=function(s){const c=[0,1,2].map(i=>(1-s)*(1-s)*(1-s)*r[i]+3*(1-s)*(1-s)*s*n[i]+3*(1-s)*s*s*o[i]+s*s*s*a[i]);return new $(c,"lab")}}else if(e.length>=5){let a,s,c;a=e.map(i=>i.lab()),c=e.length-1,s=S0(c),t=function(i){const u=1-i,l=[0,1,2].map(f=>a.reduce((h,d,b)=>h+s[b]*u**(c-b)*i**b*d[f],0));return new $(l,"lab")}}else throw new RangeError("No point in running bezier with only one color.");return t},j0=e=>{const t=P0(e);return t.scale=()=>yt(t),t},de=(e,t,r)=>{if(!de[r])throw new Error("unknown blend mode "+r);return de[r](e,t)},Ne=e=>(t,r)=>{const n=O(r).rgb(),o=O(t).rgb();return O.rgb(e(n,o))},Ae=e=>(t,r)=>{const n=[];return n[0]=e(t[0],r[0]),n[1]=e(t[1],r[1]),n[2]=e(t[2],r[2]),n},B0=e=>e,G0=(e,t)=>e*t/255,I0=(e,t)=>e>t?t:e,z0=(e,t)=>e>t?e:t,F0=(e,t)=>255*(1-(1-e/255)*(1-t/255)),X0=(e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)),K0=(e,t)=>255*(1-(1-t/255)/(e/255)),D0=(e,t)=>e===255?255:(e=255*(t/255)/(1-e/255),e>255?255:e);de.normal=Ne(Ae(B0)),de.multiply=Ne(Ae(G0)),de.screen=Ne(Ae(F0)),de.overlay=Ne(Ae(X0)),de.darken=Ne(Ae(I0)),de.lighten=Ne(Ae(z0)),de.dodge=Ne(Ae(D0)),de.burn=Ne(Ae(K0));const{pow:V0,sin:Y0,cos:Z0}=Math;function J0(e=300,t=-1.5,r=1,n=1,o=[0,1]){let a=0,s;P(o)==="array"?s=o[1]-o[0]:(s=0,o=[o,o]);const c=function(i){const u=we*((e+120)/360+t*i),l=V0(o[0]+s*i,n),h=(a!==0?r[0]+i*a:r)*l*(1-l)/2,d=Z0(u),b=Y0(u),_=l+h*(-.14861*d+1.78277*b),g=l+h*(-.29227*d-.90649*b),v=l+h*(1.97294*d);return O(Yt([_*255,g*255,v*255,1]))};return c.start=function(i){return i==null?e:(e=i,c)},c.rotations=function(i){return i==null?t:(t=i,c)},c.gamma=function(i){return i==null?n:(n=i,c)},c.hue=function(i){return i==null?r:(r=i,P(r)==="array"?(a=r[1]-r[0],a===0&&(r=r[1])):a=0,c)},c.lightness=function(i){return i==null?o:(P(i)==="array"?(o=i,s=i[1]-i[0]):(o=[i,i],s=0),c)},c.scale=()=>O.scale(c),c.hue(r),c}const W0="0123456789abcdef",{floor:U0,random:Q0}=Math,ei=()=>{let e="#";for(let t=0;t<6;t++)e+=W0.charAt(U0(Q0()*16));return new $(e,"hex")},{log:Eo,pow:ti,floor:ri,abs:ni}=Math;function To(e,t=null){const r={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return P(e)==="object"&&(e=Object.values(e)),e.forEach(n=>{t&&P(n)==="object"&&(n=n[t]),n!=null&&!isNaN(n)&&(r.values.push(n),r.sum+=n,nr.max&&(r.max=n),r.count+=1)}),r.domain=[r.min,r.max],r.limits=(n,o)=>So(r,n,o),r}function So(e,t="equal",r=7){P(e)=="array"&&(e=To(e));const{min:n,max:o}=e,a=e.values.sort((c,i)=>c-i);if(r===1)return[n,o];const s=[];if(t.substr(0,1)==="c"&&(s.push(n),s.push(o)),t.substr(0,1)==="e"){s.push(n);for(let c=1;c 0");const c=Math.LOG10E*Eo(n),i=Math.LOG10E*Eo(o);s.push(n);for(let u=1;u200&&(f=!1)}const b={};for(let g=0;gg-v),s.push(_[0]);for(let g=1;g<_.length;g+=2){const v=_[g];!isNaN(v)&&s.indexOf(v)===-1&&s.push(v)}}return s}const oi=(e,t)=>{e=new $(e),t=new $(t);const r=e.luminance(),n=t.luminance();return r>n?(r+.05)/(n+.05):(n+.05)/(r+.05)},{sqrt:ke,pow:V,min:si,max:ai,atan2:Po,abs:jo,cos:wt,sin:Bo,exp:ci,PI:Go}=Math;function ii(e,t,r=1,n=1,o=1){var a=function(he){return 360*he/(2*Go)},s=function(he){return 2*Go*he/360};e=new $(e),t=new $(t);const[c,i,u]=Array.from(e.lab()),[l,f,h]=Array.from(t.lab()),d=(c+l)/2,b=ke(V(i,2)+V(u,2)),_=ke(V(f,2)+V(h,2)),g=(b+_)/2,v=.5*(1-ke(V(g,7)/(V(g,7)+V(25,7)))),H=i*(1+v),x=f*(1+v),N=ke(V(H,2)+V(u,2)),A=ke(V(x,2)+V(h,2)),R=(N+A)/2,m=a(Po(u,H)),p=a(Po(h,x)),y=m>=0?m:m+360,w=p>=0?p:p+360,C=jo(y-w)>180?(y+w+360)/2:(y+w)/2,q=1-.17*wt(s(C-30))+.24*wt(s(2*C))+.32*wt(s(3*C+6))-.2*wt(s(4*C-63));let M=w-y;M=jo(M)<=180?M:w<=y?M+360:M-360,M=2*ke(N*A)*Bo(s(M)/2);const S=l-c,X=A-N,D=1+.015*V(d-50,2)/ke(20+V(d-50,2)),U=1+.045*R,ce=1+.015*R*q,ye=30*ci(-V((C-275)/25,2)),le=-(2*ke(V(R,7)/(V(R,7)+V(25,7))))*Bo(2*s(ye)),qe=ke(V(S/(r*D),2)+V(X/(n*U),2)+V(M/(o*ce),2)+le*(X/(n*U))*(M/(o*ce)));return ai(0,si(100,qe))}function ui(e,t,r="lab"){e=new $(e),t=new $(t);const n=e.get(r),o=t.get(r);let a=0;for(let s in n){const c=(n[s]||0)-(o[s]||0);a+=c*c}return Math.sqrt(a)}const fi=(...e)=>{try{return new $(...e),!0}catch{return!1}},li={cool(){return yt([O.hsl(180,1,.9),O.hsl(250,.7,.4)])},hot(){return yt(["#000","#f00","#ff0","#fff"]).mode("rgb")}},kt={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]};for(let e of Object.keys(kt))kt[e.toLowerCase()]=kt[e];Object.assign(O,{average:A0,bezier:j0,blend:de,cubehelix:J0,mix:ct,interpolate:ct,random:ei,scale:yt,analyze:To,contrast:oi,deltaE:ii,distance:ui,limits:So,valid:fi,scales:li,input:L,colors:De,brewer:kt});function pr(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var mr,Io;function hi(){if(Io)return mr;Io=1;var e=e||{};e.Geometry=function(){},e.Geometry.intersectLineLine=function(r,n){var o=(r.intercept-n.intercept)/(n.slope-r.slope),a=r.slope*o+r.intercept;return{x:o,y:a}},e.Geometry.distanceFromOrigin=function(r){return Math.sqrt(Math.pow(r.x,2)+Math.pow(r.y,2))},e.Geometry.distanceLineFromOrigin=function(r){return Math.abs(r.intercept)/Math.sqrt(Math.pow(r.slope,2)+1)},e.Geometry.perpendicularThroughPoint=function(r,n){var o=-1/r.slope,a=n.y-o*n.x;return{slope:o,intercept:a}},e.Geometry.angleFromOrigin=function(r){return Math.atan2(r.y,r.x)},e.Geometry.normalizeAngle=function(r){var n=2*Math.PI;return(r%n+n)%n},e.Geometry.lengthOfRayUntilIntersect=function(r,n){return n.intercept/(Math.sin(r)-n.slope*Math.cos(r))},e.Hsluv=function(){},e.Hsluv.getBounds=function(r){for(var n=[],o=Math.pow(r+16,3)/1560896,a=o>e.Hsluv.epsilon?o:r/e.Hsluv.kappa,s=0;s<3;)for(var c=s++,i=e.Hsluv.m[c][0],u=e.Hsluv.m[c][1],l=e.Hsluv.m[c][2],f=0;f<2;){var h=f++,d=(284517*i-94839*l)*a,b=(838422*l+769860*u+731718*i)*r*a-769860*h*r,_=(632260*l-126452*u)*a+126452*h;n.push({slope:d/_,intercept:b/_})}return n},e.Hsluv.maxSafeChromaForL=function(r){for(var n=e.Hsluv.getBounds(r),o=1/0,a=0;a=0&&(s=Math.min(s,u))}return s},e.Hsluv.dotProduct=function(r,n){for(var o=0,a=0,s=r.length;a.04045?Math.pow((r+.055)/1.055,2.4):r/12.92},e.Hsluv.xyzToRgb=function(r){return[e.Hsluv.fromLinear(e.Hsluv.dotProduct(e.Hsluv.m[0],r)),e.Hsluv.fromLinear(e.Hsluv.dotProduct(e.Hsluv.m[1],r)),e.Hsluv.fromLinear(e.Hsluv.dotProduct(e.Hsluv.m[2],r))]},e.Hsluv.rgbToXyz=function(r){var n=[e.Hsluv.toLinear(r[0]),e.Hsluv.toLinear(r[1]),e.Hsluv.toLinear(r[2])];return[e.Hsluv.dotProduct(e.Hsluv.minv[0],n),e.Hsluv.dotProduct(e.Hsluv.minv[1],n),e.Hsluv.dotProduct(e.Hsluv.minv[2],n)]},e.Hsluv.yToL=function(r){return r<=e.Hsluv.epsilon?r/e.Hsluv.refY*e.Hsluv.kappa:116*Math.pow(r/e.Hsluv.refY,.3333333333333333)-16},e.Hsluv.lToY=function(r){return r<=8?e.Hsluv.refY*r/e.Hsluv.kappa:e.Hsluv.refY*Math.pow((r+16)/116,3)},e.Hsluv.xyzToLuv=function(r){var n=r[0],o=r[1],a=r[2],s=n+15*o+3*a,c=4*n,i=9*o;s!=0?(c/=s,i/=s):(c=NaN,i=NaN);var u=e.Hsluv.yToL(o);if(u==0)return[0,0,0];var l=13*u*(c-e.Hsluv.refU),f=13*u*(i-e.Hsluv.refV);return[u,l,f]},e.Hsluv.luvToXyz=function(r){var n=r[0],o=r[1],a=r[2];if(n==0)return[0,0,0];var s=o/(13*n)+e.Hsluv.refU,c=a/(13*n)+e.Hsluv.refV,i=e.Hsluv.lToY(n),u=0-9*i*s/((s-4)*c-s*c),l=(9*i-15*c*i-c*u)/(3*c);return[u,i,l]},e.Hsluv.luvToLch=function(r){var n=r[0],o=r[1],a=r[2],s=Math.sqrt(o*o+a*a),c;if(s<1e-8)c=0;else{var i=Math.atan2(a,o);c=i*180/Math.PI,c<0&&(c=360+c)}return[n,s,c]},e.Hsluv.lchToLuv=function(r){var n=r[0],o=r[1],a=r[2],s=a/360*2*Math.PI,c=Math.cos(s)*o,i=Math.sin(s)*o;return[n,c,i]},e.Hsluv.hsluvToLch=function(r){var n=r[0],o=r[1],a=r[2];if(a>99.9999999)return[100,0,n];if(a<1e-8)return[0,0,n];var s=e.Hsluv.maxChromaForLH(a,n),c=s/100*o;return[a,c,n]},e.Hsluv.lchToHsluv=function(r){var n=r[0],o=r[1],a=r[2];if(n>99.9999999)return[a,0,100];if(n<1e-8)return[a,0,0];var s=e.Hsluv.maxChromaForLH(n,a),c=o/s*100;return[a,c,n]},e.Hsluv.hpluvToLch=function(r){var n=r[0],o=r[1],a=r[2];if(a>99.9999999)return[100,0,n];if(a<1e-8)return[0,0,n];var s=e.Hsluv.maxSafeChromaForL(a),c=s/100*o;return[a,c,n]},e.Hsluv.lchToHpluv=function(r){var n=r[0],o=r[1],a=r[2];if(n>99.9999999)return[a,0,100];if(n<1e-8)return[a,0,0];var s=e.Hsluv.maxSafeChromaForL(n),c=o/s*100;return[a,c,n]},e.Hsluv.rgbToHex=function(r){for(var n="#",o=0;o<3;){var a=o++,s=r[a],c=Math.round(s*255),i=c%16,u=(c-i)/16|0;n+=e.Hsluv.hexChars.charAt(u)+e.Hsluv.hexChars.charAt(i)}return n},e.Hsluv.hexToRgb=function(r){r=r.toLowerCase();for(var n=[],o=0;o<3;){var a=o++,s=e.Hsluv.hexChars.indexOf(r.charAt(a*2+1)),c=e.Hsluv.hexChars.indexOf(r.charAt(a*2+2)),i=s*16+c;n.push(i/255)}return n},e.Hsluv.lchToRgb=function(r){return e.Hsluv.xyzToRgb(e.Hsluv.luvToXyz(e.Hsluv.lchToLuv(r)))},e.Hsluv.rgbToLch=function(r){return e.Hsluv.luvToLch(e.Hsluv.xyzToLuv(e.Hsluv.rgbToXyz(r)))},e.Hsluv.hsluvToRgb=function(r){return e.Hsluv.lchToRgb(e.Hsluv.hsluvToLch(r))},e.Hsluv.rgbToHsluv=function(r){return e.Hsluv.lchToHsluv(e.Hsluv.rgbToLch(r))},e.Hsluv.hpluvToRgb=function(r){return e.Hsluv.lchToRgb(e.Hsluv.hpluvToLch(r))},e.Hsluv.rgbToHpluv=function(r){return e.Hsluv.lchToHpluv(e.Hsluv.rgbToLch(r))},e.Hsluv.hsluvToHex=function(r){return e.Hsluv.rgbToHex(e.Hsluv.hsluvToRgb(r))},e.Hsluv.hpluvToHex=function(r){return e.Hsluv.rgbToHex(e.Hsluv.hpluvToRgb(r))},e.Hsluv.hexToHsluv=function(r){return e.Hsluv.rgbToHsluv(e.Hsluv.hexToRgb(r))},e.Hsluv.hexToHpluv=function(r){return e.Hsluv.rgbToHpluv(e.Hsluv.hexToRgb(r))},e.Hsluv.m=[[3.240969941904521,-1.537383177570093,-.498610760293],[-.96924363628087,1.87596750150772,.041555057407175],[.055630079696993,-.20397695888897,1.056971514242878]],e.Hsluv.minv=[[.41239079926595,.35758433938387,.18048078840183],[.21263900587151,.71516867876775,.072192315360733],[.019330818715591,.11919477979462,.95053215224966]],e.Hsluv.refY=1,e.Hsluv.refU=.19783000664283,e.Hsluv.refV=.46831999493879,e.Hsluv.kappa=903.2962962,e.Hsluv.epsilon=.0088564516,e.Hsluv.hexChars="0123456789abcdef";var t={hsluvToRgb:e.Hsluv.hsluvToRgb,rgbToHsluv:e.Hsluv.rgbToHsluv,hpluvToRgb:e.Hsluv.hpluvToRgb,rgbToHpluv:e.Hsluv.rgbToHpluv,hsluvToHex:e.Hsluv.hsluvToHex,hexToHsluv:e.Hsluv.hexToHsluv,hpluvToHex:e.Hsluv.hpluvToHex,hexToHpluv:e.Hsluv.hexToHpluv,lchToHpluv:e.Hsluv.lchToHpluv,hpluvToLch:e.Hsluv.hpluvToLch,lchToHsluv:e.Hsluv.lchToHsluv,hsluvToLch:e.Hsluv.hsluvToLch,lchToLuv:e.Hsluv.lchToLuv,luvToLch:e.Hsluv.luvToLch,xyzToLuv:e.Hsluv.xyzToLuv,luvToXyz:e.Hsluv.luvToXyz,xyzToRgb:e.Hsluv.xyzToRgb,rgbToXyz:e.Hsluv.rgbToXyz,lchToRgb:e.Hsluv.lchToRgb,rgbToLch:e.Hsluv.rgbToLch};return mr=t,mr}var di=hi();const gr=pr(di);var $t={exports:{}},vr,zo;function it(){if(zo)return vr;zo=1;function e(t,r){return Object.prototype.hasOwnProperty.call(t,r)}return vr=e,vr}var _r,Fo;function yr(){if(Fo)return _r;Fo=1;var e=it(),t,r;function n(){r=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],t=!0;for(var s in{toString:null})t=!1}function o(s,c,i){var u,l=0;t==null&&n();for(u in s)if(a(c,s,u,i)===!1)break;if(t)for(var f=s.constructor,h=!!f&&s===f.prototype;(u=r[l++])&&!((u!=="constructor"||!h&&e(s,u))&&s[u]!==Object.prototype[u]&&a(c,s,u,i)===!1););}function a(s,c,i,u){return s.call(u,c[i],i,c)}return _r=o,_r}var wr,Xo;function Ko(){if(Xo)return wr;Xo=1;var e=yr();function t(r){var n=[];return e(r,function(o,a){typeof o=="function"&&n.push(a)}),n.sort()}return wr=t,wr}var kr,Do;function ut(){if(Do)return kr;Do=1;function e(t,r,n){var o=t.length;r==null?r=0:r<0?r=Math.max(o+r,0):r=Math.min(r,o),n==null?n=o:n<0?n=Math.max(o+n,0):n=Math.min(n,o);for(var a=[];r1?n(arguments,1):e(a);r(c,function(i){a[i]=t(a[i],a)})}return Rr=o,Rr}var Hr,Jo;function Q(){if(Jo)return Hr;Jo=1;var e=it(),t=yr();function r(n,o,a){t(n,function(s,c){if(e(n,c))return o.call(a,n[c],c,n)})}return Hr=r,Hr}var qr,Wo;function mi(){if(Wo)return qr;Wo=1;function e(t){return t}return qr=e,qr}var Mr,Uo;function Qo(){if(Uo)return Mr;Uo=1;function e(t){return function(r){return r[t]}}return Mr=e,Mr}var Or,es;function Nr(){if(es)return Or;es=1;var e=/^\[object (.*)\]$/,t=Object.prototype.toString,r;function n(o){return o===null?"Null":o===r?"Undefined":e.exec(t.call(o))[1]}return Or=n,Or}var Ar,ts;function Lr(){if(ts)return Ar;ts=1;var e=Nr();function t(r,n){return e(r)===n}return Ar=t,Ar}var Er,rs;function gi(){if(rs)return Er;rs=1;var e=Lr(),t=Array.isArray||function(r){return e(r,"Array")};return Er=t,Er}var Tr,ns;function os(){if(ns)return Tr;ns=1;var e=Q(),t=gi();function r(s,c){for(var i=-1,u=s.length;++is&&(s=i,a=c);return a}return rn=t,rn}var nn,Ns;function on(){if(Ns)return nn;Ns=1;var e=Q();function t(r){var n=[];return e(r,function(o,a){n.push(o)}),n}return nn=t,nn}var sn,As;function Mi(){if(As)return sn;As=1;var e=qi(),t=on();function r(n,o){return e(t(n),o)}return sn=r,sn}var an,Ls;function Es(){if(Ls)return an;Ls=1;var e=Q();function t(n,o){for(var a=0,s=arguments.length,c;++a2;if(!t(n)&&!c)throw new Error("reduce of empty object with no initial value");return e(n,function(i,u,l){c?a=o.call(s,a,i,u,l):(a=i,c=!0)}),a}return yn=r,yn}var wn,Js;function Ii(){if(Js)return wn;Js=1;var e=_s(),t=Le();function r(n,o,a){return o=t(o,a),e(n,function(s,c,i){return!o(s,c,i)},a)}return wn=r,wn}var kn,Ws;function zi(){if(Ws)return kn;Ws=1;var e=Lr();function t(r){return e(r,"Function")}return kn=t,kn}var $n,Us;function Fi(){if(Us)return $n;Us=1;var e=zi();function t(r,n){var o=r[n];if(o!==void 0)return e(o)?o.call(r):o}return $n=t,$n}var Cn,Qs;function Xi(){if(Qs)return Cn;Qs=1;var e=Is();function t(r,n,o){var a=/^(.+)\.(.+)$/.exec(n);a?e(r,a[1])[a[2]]=o:r[n]=o}return Cn=t,Cn}var xn,ea;function Ki(){if(ea)return xn;ea=1;var e=xs();function t(r,n){if(e(r,n)){for(var o=n.split("."),a=o.pop();n=o.shift();)r=r[n];return delete r[a]}else return!0}return xn=t,xn}var Rn,ta;function Hn(){return ta||(ta=1,Rn={bindAll:pi(),contains:vi(),deepFillIn:_i(),deepMatches:os(),deepMixIn:yi(),equals:ki(),every:hs(),fillIn:$i(),filter:_s(),find:Ci(),flatten:xi(),forIn:yr(),forOwn:Q(),functions:Ko(),get:$s(),has:xs(),hasOwn:it(),keys:Ri(),map:qs(),matches:Hi(),max:Mi(),merge:Ai(),min:Ei(),mixIn:Es(),namespace:Is(),omit:Pi(),pick:ji(),pluck:Bi(),reduce:Gi(),reject:Ii(),result:Fi(),set:Xi(),size:Ys(),some:jr(),unset:Ki(),values:on()}),Rn}var ra;function na(){return ra||(ra=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Hn(),n={A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},o=(0,r.map)(n,function(a){var s=100*(a.x/a.y),c=100,i=100*(1-a.x-a.y)/a.y;return[s,c,i]});t.default=o,e.exports=t.default})($t,$t.exports)),$t.exports}var Ct={exports:{}},oa;function sa(){return oa||(oa=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Math,n=r.pow,o=r.sign,a=r.abs,s={decode:function(f){return f<=.04045?f/12.92:n((f+.055)/1.055,2.4)},encode:function(f){return f<=.0031308?12.92*f:1.055*n(f,1/2.4)-.055}},c={encode:function(f){return f<.001953125?16*f:n(f,1/1.8)},decode:function(f){return f<16*.001953125?f/16:n(f,1.8)}};function i(l){return{decode:function(h){return o(h)*n(a(h),l)},encode:function(h){return o(h)*n(a(h),1/l)}}}var u={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:s},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:i(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:i(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:c}};t.default=u,e.exports=t.default})(Ct,Ct.exports)),Ct.exports}var $e={},aa;function ca(){if(aa)return $e;aa=1,Object.defineProperty($e,"__esModule",{value:!0});function e(s){return[[s[0][0],s[1][0],s[2][0]],[s[0][1],s[1][1],s[2][1]],[s[0][2],s[1][2],s[2][2]]]}function t(s){return s[0][0]*(s[2][2]*s[1][1]-s[2][1]*s[1][2])+s[1][0]*(s[2][1]*s[0][2]-s[2][2]*s[0][1])+s[2][0]*(s[1][2]*s[0][1]-s[1][1]*s[0][2])}function r(s){var c=1/t(s);return[[(s[2][2]*s[1][1]-s[2][1]*s[1][2])*c,(s[2][1]*s[0][2]-s[2][2]*s[0][1])*c,(s[1][2]*s[0][1]-s[1][1]*s[0][2])*c],[(s[2][0]*s[1][2]-s[2][2]*s[1][0])*c,(s[2][2]*s[0][0]-s[2][0]*s[0][2])*c,(s[1][0]*s[0][2]-s[1][2]*s[0][0])*c],[(s[2][1]*s[1][0]-s[2][0]*s[1][1])*c,(s[2][0]*s[0][1]-s[2][1]*s[0][0])*c,(s[1][1]*s[0][0]-s[1][0]*s[0][1])*c]]}function n(s,c){return[s[0][0]*c[0]+s[0][1]*c[1]+s[0][2]*c[2],s[1][0]*c[0]+s[1][1]*c[1]+s[1][2]*c[2],s[2][0]*c[0]+s[2][1]*c[1]+s[2][2]*c[2]]}function o(s,c){return[[s[0][0]*c[0],s[0][1]*c[1],s[0][2]*c[2]],[s[1][0]*c[0],s[1][1]*c[1],s[1][2]*c[2]],[s[2][0]*c[0],s[2][1]*c[1],s[2][2]*c[2]]]}function a(s,c){return[[s[0][0]*c[0][0]+s[0][1]*c[1][0]+s[0][2]*c[2][0],s[0][0]*c[0][1]+s[0][1]*c[1][1]+s[0][2]*c[2][1],s[0][0]*c[0][2]+s[0][1]*c[1][2]+s[0][2]*c[2][2]],[s[1][0]*c[0][0]+s[1][1]*c[1][0]+s[1][2]*c[2][0],s[1][0]*c[0][1]+s[1][1]*c[1][1]+s[1][2]*c[2][1],s[1][0]*c[0][2]+s[1][1]*c[1][2]+s[1][2]*c[2][2]],[s[2][0]*c[0][0]+s[2][1]*c[1][0]+s[2][2]*c[2][0],s[2][0]*c[0][1]+s[2][1]*c[1][1]+s[2][2]*c[2][1],s[2][0]*c[0][2]+s[2][1]*c[1][2]+s[2][2]*c[2][2]]]}return $e.transpose=e,$e.determinant=t,$e.inverse=r,$e.multiply=n,$e.scalar=o,$e.product=a,$e}var lt={},ia;function Di(){if(ia)return lt;ia=1,Object.defineProperty(lt,"__esModule",{value:!0});var e=Math,t=e.PI;function r(o){for(var a=o*180/t;a<0;)a+=360;for(;a>360;)a-=360;return a}function n(o){for(var a=t*o/180;a<0;)a+=2*t;for(;a>2*t;)a-=2*t;return a}return lt.fromRadian=r,lt.toRadian=n,lt}var ht={},ua;function Vi(){if(ua)return ht;ua=1,Object.defineProperty(ht,"__esModule",{value:!0});var e=Math,t=e.round;function r(o){return o[0]=="#"&&(o=o.slice(1)),o.length<6&&(o=o.split("").map(function(a){return a+a}).join("")),o.match(/../g).map(function(a){return parseInt(a,16)/255})}function n(o){var a=o.map(function(s){return s=t(255*s).toString(16),s.length<2&&(s="0"+s),s}).join("");return"#"+a}return ht.fromHex=r,ht.toHex=n,ht}var xt={exports:{}},fa;function Yi(){return fa||(fa=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=ca(),n=u(r),o=na(),a=i(o),s=sa(),c=i(s);function i(f){return f&&f.__esModule?f:{default:f}}function u(f){if(f&&f.__esModule)return f;var h={};if(f!=null)for(var d in f)Object.prototype.hasOwnProperty.call(f,d)&&(h[d]=f[d]);return h.default=f,h}function l(){var f=arguments.length<=0||arguments[0]===void 0?c.default.sRGB:arguments[0],h=arguments.length<=1||arguments[1]===void 0?a.default.D65:arguments[1],d=[f.r,f.g,f.b],b=n.transpose(d.map(function(x){var N=x.x/x.y,A=1,R=(1-x.x-x.y)/x.y;return[N,A,R]})),_=f.gamma,g=n.multiply(n.inverse(b),h),v=n.scalar(b,g),H=n.inverse(v);return{fromRgb:function(N){return n.multiply(v,N.map(_.decode))},toRgb:function(N){return n.multiply(H,N).map(_.encode)}}}t.default=l,e.exports=t.default})(xt,xt.exports)),xt.exports}var qn,la;function Rt(){if(la)return qn;la=1;var e=na(),t=sa(),r=ca(),n=Di(),o=Vi(),a=Yi();return qn={illuminant:e,workspace:t,matrix:r,degree:n,rgb:o,xyz:a},qn}var Zi=Rt();const Ht=pr(Zi);var be={},ha;function qt(){if(ha)return be;ha=1,Object.defineProperty(be,"__esModule",{value:!0}),be.cfs=be.distance=be.lerp=be.corLerp=void 0;var e=Hn();function t(h,d,b){return d in h?Object.defineProperty(h,d,{value:b,enumerable:!0,configurable:!0,writable:!0}):h[d]=b,h}function r(h){if(Array.isArray(h)){for(var d=0,b=Array(h.length);dg/2&&(h>d?d+=g:h+=g)}return((1-b)*h+b*d)%(g||1/0)}function u(h,d,b){var _={};for(var g in h)_[g]=i(h[g],d[g],b,g);return _}function l(h,d){var b=0;for(var _ in h)b+=a(h[_]-d[_],2);return s(b)}function f(h){return e.merge.apply(void 0,r(h.split("").map(function(d){return t({},d,!0)})))}return be.corLerp=i,be.lerp=u,be.distance=l,be.cfs=f,be}var Mt={exports:{}},da;function Ji(){return da||(da=1,(function(e,t){var r=(function(){function s(c,i){var u=[],l=!0,f=!1,h=void 0;try{for(var d=c[Symbol.iterator](),b;!(l=(b=d.next()).done)&&(u.push(b.value),!(i&&u.length===i));l=!0);}catch(_){f=!0,h=_}finally{try{!l&&d.return&&d.return()}finally{if(f)throw h}}return u}return function(c,i){if(Array.isArray(c))return c;if(Symbol.iterator in Object(c))return s(c,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(t,"__esModule",{value:!0});var n=Rt(),o=qt();function a(s,c){var i=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],u=-i,l=1+i,f=Math,h=f.min,d=f.max,b=["000","fff"].map(function(R){return c.fromXyz(s.fromRgb(n.rgb.fromHex(R)))}),_=r(b,2),g=_[0],v=_[1];function H(R){var m=s.toRgb(c.toXyz(R)),p=m.map(function(y){return y>=u&&y<=l}).reduce(function(y,w){return y&&w},!0);return[p,m]}function x(R,m){for(var p=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,o.distance)(R,m)>p;){var y=(0,o.lerp)(R,m,.5),w=H(y),C=r(w,1),q=C[0];q?R=y:m=y}return R}function N(R){return(0,o.lerp)(g,v,R)}function A(R){return R.map(function(m){return d(u,h(l,m))})}return{contains:H,limit:x,spine:N,crop:A}}t.default=a,e.exports=t.default})(Mt,Mt.exports)),Mt.exports}var Ot={exports:{}},pe={},ba;function pa(){if(ba)return pe;ba=1;var e=(function(){function f(h,d){var b=[],_=!0,g=!1,v=void 0;try{for(var H=h[Symbol.iterator](),x;!(_=(x=H.next()).done)&&(b.push(x.value),!(d&&b.length===d));_=!0);}catch(N){g=!0,v=N}finally{try{!_&&H.return&&H.return()}finally{if(g)throw v}}return b}return function(h,d){if(Array.isArray(h))return h;if(Symbol.iterator in Object(h))return f(h,d);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(pe,"__esModule",{value:!0}),pe.toNotation=pe.fromNotation=pe.toHue=pe.fromHue=void 0;var t=qt(),r=Math,n=r.floor,o=[{s:"R",h:20.14,e:.8,H:0},{s:"Y",h:90,e:.7,H:100},{s:"G",h:164.25,e:1,H:200},{s:"B",h:237.53,e:1.2,H:300},{s:"R",h:380.14,e:.8,H:400}],a=o.map(function(f){return f.s}).slice(0,-1).join("");function s(f){f50){var _=[d,h];h=_[0],d=_[1],b=100-b}return b<1?a[h]:a[h]+b.toFixed()+a[d]}return pe.fromHue=s,pe.toHue=c,pe.fromNotation=u,pe.toNotation=l,pe}var ma;function Wi(){return ma||(ma=1,(function(e,t){var r=(function(){function S(X,D){var U=[],ce=!0,ye=!1,st=void 0;try{for(var le=X[Symbol.iterator](),qe;!(ce=(qe=le.next()).done)&&(U.push(qe.value),!(D&&U.length===D));ce=!0);}catch(he){ye=!0,st=he}finally{try{!ce&&le.return&&le.return()}finally{if(ye)throw st}}return U}return function(X,D){if(Array.isArray(X))return X;if(Symbol.iterator in Object(X))return S(X,D);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(t,"__esModule",{value:!0});var n=Rt(),o=pa(),a=i(o),s=qt(),c=Hn();function i(S){if(S&&S.__esModule)return S;var X={};if(S!=null)for(var D in S)Object.prototype.hasOwnProperty.call(S,D)&&(X[D]=S[D]);return X.default=S,X}var u=Math,l=u.pow,f=u.sqrt,h=u.exp,d=u.abs,b=u.sign,_=Math,g=_.sin,v=_.cos,H=_.atan2,x={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},N=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],A=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],R=N,m=n.matrix.inverse(N),p=n.matrix.product(A,n.matrix.inverse(N)),y=n.matrix.product(N,n.matrix.inverse(A)),w={whitePoint:n.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:"average",discounting:!1},C=(0,s.cfs)("QJMCshH"),q=(0,s.cfs)("JCh");function M(){var S=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],X=arguments.length<=1||arguments[1]===void 0?C:arguments[1];S=(0,c.merge)(w,S);var D=S.whitePoint,U=S.adaptingLuminance,ce=S.backgroundLuminance,ye=x[S.surroundType],st=ye.F,le=ye.c,qe=ye.N_c,he=D[1],wc=1/(5*U+1),Ge=.2*l(wc,4)*5*U+.1*l(1-l(wc,4),2)*l(5*U,1/3),Xt=ce/he,no=.725*l(1/Xt,.2),kc=no,$c=1.48+f(Xt),Cc=S.discounting?1:st*(1-1/3.6*h(-(U+42)/92)),$l=n.matrix.multiply(N,D),Cl=$l.map(function(I){return Cc*he/I+1-Cc}),oo=r(Cl,3),xc=oo[0],Rc=oo[1],Hc=oo[2],xl=qc(D),Rl=Mc(xl),Kt=Oc(Rl);function qc(I){var z=n.matrix.multiply(R,I),F=r(z,3),ee=F[0],W=F[1],ie=F[2];return[xc*ee,Rc*W,Hc*ie]}function Hl(I){var z=r(I,3),F=z[0],ee=z[1],W=z[2];return n.matrix.multiply(m,[F/xc,ee/Rc,W/Hc])}function Mc(I){return n.matrix.multiply(p,I).map(function(z){var F=l(Ge*d(z)/100,.42);return b(z)*400*F/(27.13+F)+.1})}function ql(I){return n.matrix.multiply(y,I.map(function(z){var F=z-.1;return b(F)*100/Ge*l(27.13*d(F)/(400-d(F)),2.380952380952381)}))}function Oc(I){var z=r(I,3),F=z[0],ee=z[1],W=z[2];return(F*2+ee+W/20-.305)*no}function so(I){return 4/le*f(I/100)*(Kt+4)*l(Ge,.25)}function Ml(I){return 6.25*l(le*I/((Kt+4)*l(Ge,.25)),2)}function Nc(I){return I*l(Ge,.25)}function Ol(I,z){return l(I/100,2)*z/l(Ge,.25)}function Nl(I){return I/l(Ge,.25)}function Al(I,z){return 100*f(I/z)}function ao(I,z){var F=z.Q,ee=z.J,W=z.M,ie=z.C,ve=z.s,Me=z.h,Oe=z.H,te={};return I.J&&(te.J=isNaN(ee)?Ml(F):ee),I.C&&(isNaN(ie)?isNaN(W)?(F=isNaN(F)?so(ee):F,te.C=Ol(ve,F)):te.C=Nl(W):te.C=z.C),I.h&&(te.h=isNaN(Me)?a.toHue(Oe):Me),I.Q&&(te.Q=isNaN(F)?so(ee):F),I.M&&(te.M=isNaN(W)?Nc(ie):W),I.s&&(isNaN(ve)?(F=isNaN(F)?so(ee):F,W=isNaN(W)?Nc(ie):W,te.s=Al(W,F)):te.s=ve),I.H&&(te.H=isNaN(Oe)?a.fromHue(Me):Oe),te}function Ll(I){var z=qc(I),F=Mc(z),ee=r(F,3),W=ee[0],ie=ee[1],ve=ee[2],Me=W-ie*12/11+ve/11,Oe=(W+ie-2*ve)/9,te=H(Oe,Me),at=n.degree.fromRadian(te),Dt=1/4*(v(te+2)+3.8),Vt=Oc(F),bt=100*l(Vt/Kt,le*$c),Pe=5e4/13*qe*kc*Dt*f(Me*Me+Oe*Oe)/(W+ie+21/20*ve),je=l(Pe,.9)*f(bt/100)*l(1.64-l(.29,Xt),.73);return ao(X,{J:bt,C:je,h:at})}function El(I){var z=ao(q,I),F=z.J,ee=z.C,W=z.h,ie=n.degree.toRadian(W),ve=l(ee/(f(F/100)*l(1.64-l(.29,Xt),.73)),10/9),Me=1/4*(v(ie+2)+3.8),Oe=Kt*l(F/100,1/le/$c),te=5e4/13*qe*kc*Me/ve,at=Oe/no+.305,Dt=at*61/20*460/1403,Vt=61/20*220/1403,bt=21/20*6300/1403-27/1403,Pe=g(ie),je=v(ie),Ie,ze;ve===0||isNaN(ve)?Ie=ze=0:d(Pe)>=d(je)?(ze=Dt/(te/Pe+Vt*je/Pe+bt),Ie=ze*je/Pe):(Ie=Dt/(te/je+Vt+bt*Pe/je),ze=Ie*Pe/je);var Tl=[20/61*at+451/1403*Ie+288/1403*ze,20/61*at-891/1403*Ie-261/1403*ze,20/61*at-220/1403*Ie-6300/1403*ze],Sl=ql(Tl),Pl=Hl(Sl);return Pl}return{fromXyz:Ll,toXyz:El,fillOut:ao}}t.default=M,e.exports=t.default})(Ot,Ot.exports)),Ot.exports}var Nt={exports:{}},ga;function Ui(){return ga||(ga=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Rt(),n=Math,o=n.sqrt,a=n.pow,s=n.exp,c=n.log,i=n.cos,u=n.sin,l=n.atan2,f={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function h(){var d=arguments.length<=0||arguments[0]===void 0?"UCS":arguments[0],b=f[d],_=b.K_L,g=b.c_1,v=b.c_2;function H(A){var R=A.J,m=A.M,p=A.h,y=r.degree.toRadian(p),w=(1+100*g)*R/(1+g*R),C=1/v*c(1+v*m),q=C*i(y),M=C*u(y);return{J_p:w,a_p:q,b_p:M}}function x(A){var R=A.J_p,m=A.a_p,p=A.b_p,y=-R/(g*R-100*g-1),w=o(a(m,2)+a(p,2)),C=(s(v*w)-1)/v,q=l(p,m),M=r.degree.fromRadian(q);return{J:y,M:C,h:M}}function N(A,R){return o(a((A.J_p-R.J_p)/_,2)+a(A.a_p-R.a_p,2)+a(A.b_p-R.b_p,2))}return{fromCam:H,toCam:x,distance:N}}t.default=h,e.exports=t.default})(Nt,Nt.exports)),Nt.exports}var Mn,va;function Qi(){if(va)return Mn;va=1;var e=qt(),t=Ji(),r=Wi(),n=Ui(),o=pa();return Mn={gamut:t,cfs:e.cfs,lerp:e.lerp,cam:r,ucs:n,hq:o},Mn}var eu=Qi();const _a=pr(eu),ya=_a.cam({whitePoint:Ht.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:"average",discounting:!1},_a.cfs("JCh")),wa=Ht.xyz(Ht.workspace.sRGB,Ht.illuminant.D65),ka=e=>wa.toRgb(ya.toXyz({J:e[0],C:e[1],h:e[2]})),On=e=>{const t=ya.fromXyz(wa.fromRgb(e));return[t.J,t.C,t.h]},[tu,ru]=(()=>{const e={k_l:1,c1:.007,c2:.0228},t=Math.PI,r=64/t/5,n=1/(5*r+1),o=.2*n**4*(5*r)+.1*(1-n**4)**2*(5*r)**(1/3);return[a=>{const[s,c,i]=a,u=c*o**.25;let l=(1+100*e.c1)*s/(1+e.c1*s);l/=e.k_l;const f=1/e.c2*Math.log(1+e.c2*u),h=f*Math.cos(i*(t/180)),d=f*Math.sin(i*(t/180));return[l,h,d]},a=>{const[s,c,i]=a,u=Math.sqrt(c*c+i*i),l=(Math.exp(u*e.c2)-1)/e.c2,f=(180/t*Math.atan2(i,c)+360)%360,h=l/o**.25;return[s/(1+e.c1*(100-s)),h,f]}]})(),nu=e=>ka(ru(e)),$a=e=>tu(On(e)),At=console;At.color=(e,t="")=>{const n=O(e).luminance();At.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?"#000":"#fff"}`)},At.ramp=(e,t=1)=>{At.log("%c ",`font-size: 1px;line-height: 16px;background: ${O.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};const Ca=(e,t,r,n,o,a,s=.1)=>{if(e===r||t===n)return!0;const c=(n-t)/(r-e),i=(a+o/c-t+c*e)/(c+1/c),u=a+o/c-i/c;return(o-i)**2+(a-u)**2{const o=(t[0]+r[0])/2,a=e(o);return Ca(...t,...r,o,a,n)?null:[o,a]},Nn=(e,t,r,n=.1)=>{const o=(r-t)/10,a=[];for(let s=t;sMath.round(e*10**t)/10**t,su=(e,t=1,r=90,n=.005)=>{const o=Nn(i=>e(i).gl()[0],0,t,n),a=Nn(i=>e(i).gl()[1],0,t,n),s=Nn(i=>e(i).gl()[2],0,t,n),c=Array.from(new Set([...o.map(i=>Lt(i[0])),...a.map(i=>Lt(i[0])),...s.map(i=>Lt(i[0]))].sort((i,u)=>i-u)));return`linear-gradient(${r}deg, ${c.map(i=>`${e(i).hex()} ${Lt(i*100)}%`).join()});`},au=e=>{e.Color.prototype.jch=function(){return On(this._rgb.slice(0,3).map(o=>o/255))},e.jch=(...o)=>new e.Color(...ka(o).map(a=>Math.floor(a*255)),"rgb"),e.Color.prototype.jab=function(){return $a(this._rgb.slice(0,3).map(o=>o/255))},e.jab=(...o)=>new e.Color(...nu(o).map(a=>Math.floor(a*255)),"rgb"),e.Color.prototype.hsluv=function(){return gr.rgbToHsluv(this._rgb.slice(0,3).map(o=>o/255))},e.hsluv=(...o)=>new e.Color(...gr.hsluvToRgb(o).map(a=>Math.floor(a*255)),"rgb");const t=e.interpolate,r={jch:On,jab:$a,hsluv:gr.rgbToHsluv},n=(o,a,s)=>(Math.abs(o-a)>360/2&&(o>a?a+=360:o+=360),((1-s)*o+s*a)%360);e.interpolate=(o,a,s=.5,c="lrgb")=>{if(r[c]){typeof o!="object"&&(o=new e.Color(o)),typeof a!="object"&&(a=new e.Color(a));const i=r[c](o.gl()),u=r[c](a.gl()),l=Number.isNaN(o.hsl()[0]),f=Number.isNaN(a.hsl()[0]);let h,d,b;switch(c){case"hsluv":i[1]<1e-10&&(i[0]=u[0]),i[1]===0&&(i[1]=u[1]),u[1]<1e-10&&(u[0]=i[0]),u[1]===0&&(u[1]=i[1]),h=n(i[0],u[0],s),d=i[1]+(u[1]-i[1])*s,b=i[2]+(u[2]-i[2])*s;break;case"jch":l&&(i[2]=u[2]),f&&(u[2]=i[2]),h=i[0]+(u[0]-i[0])*s,d=i[1]+(u[1]-i[1])*s,b=n(i[2],u[2],s);break;default:h=i[0]+(u[0]-i[0])*s,d=i[1]+(u[1]-i[1])*s,b=i[2]+(u[2]-i[2])*s}return e[c](h,d,b).alpha(o.alpha()+s*(a.alpha()-o.alpha()))}return t(o,a,s,c)},e.getCSSGradient=su};const Y={mainTRC:2.4,sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1};function xa(e,t,r=-1){const n=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)n[1])return 0;let o=0,a=0,s="BoW";return e=e>Y.blkThrs?e:e+Math.pow(Y.blkThrs-e,Y.blkClmp),t=t>Y.blkThrs?t:t+Math.pow(Y.blkThrs-t,Y.blkClmp),Math.abs(t-e)e?(o=(Math.pow(t,Y.normBG)-Math.pow(e,Y.normTXT))*Y.scaleBoW,a=o-.1?0:o+Y.loWoBoffset),r<0?a*100:r==0?Math.round(Math.abs(a)*100)+""+s+"":Number.isInteger(r)?(a*100).toFixed(r):0)}function Et(e=[0,0,0]){function t(r){return Math.pow(r/255,Y.mainTRC)}return Y.sRco*t(e[0])+Y.sGco*t(e[1])+Y.sBco*t(e[2])}const Ra=(e,t,r,n,o,a,s,c,i)=>{const u=1-i,l=u*u,f=l*u,d=i*i*i,b=f*e+l*3*i*r+u*3*i*i*o+d*s,_=f*t+l*3*i*n+u*3*i*i*a+d*c;return{x:b,y:_}},cu=(e,t)=>{const r=[];let n={x:+e[0],y:+e[1]};for(let o=0,a=e.length;a-2*!0>o;o+=2){const s=[{x:+e[o-2],y:+e[o-1]},{x:+e[o],y:+e[o+1]},{x:+e[o+2],y:+e[o+3]},{x:+e[o+4],y:+e[o+5]}];a-4===o?s[3]=s[2]:o||(s[0]={x:+e[o],y:+e[o+1]}),r.push([n.x,n.y,(-s[0].x+6*s[1].x+s[2].x)/6,(-s[0].y+6*s[1].y+s[2].y)/6,(s[1].x+6*s[2].x-s[3].x)/6,(s[1].y+6*s[2].y-s[3].y)/6,s[2].x,s[2].y]),n=s[2]}return r},iu=(e,t,r,n,o,a,s,c)=>{let u=e,l=t,f=0;for(let h=1;h<5;h++){const{x:d,y:b}=Ra(e,t,r,n,o,a,s,c,h/5);f+=Math.hypot(d-u,b-l),u=d,l=b}return f+=Math.hypot(s-u,c-l),f},uu=(e,t,r,n,o,a,s,c)=>{const i=Math.floor(iu(e,t,r,n,o,a,s,c)*.75),u=[];let l=0;for(let f=0;f<=i;f++){const h=f/i,d=Ra(e,t,r,n,o,a,s,c,h),b=Math.round(d.x);if(u[b]=d.y,b-l>1){const _=u[l],g=u[b];for(let v=l+1;vu[Math.round(f)]||null},Ze={CAM02:"jab",CAM02p:"jch",HEX:"hex",HSL:"hsl",HSLuv:"hsluv",HSV:"hsv",LAB:"lab",LCH:"lch",RGB:"rgb",OKLAB:"oklab",OKLCH:"oklch"};function Ee(e,t=0){const r=10**t;return Math.round(e*r)/r}function fu(e,t){let r;return e>1?r=(e-1)*t+1:e<-1?r=(e+1)*t-1:r=1,Ee(r,2)}function lu(e){return O(String(e)).jch()}function hu(e){return O(String(e)).hsluv()}function du(e,t,r){const n=[[],[],[]];if(e.forEach((a,s)=>n.forEach((c,i)=>c.push(t[s],a[i]))),r==="hcl"){const a=n[1];for(let s=1;s{const s=[];for(let c=1;c{a[i]=a[c]}),s.length=0;break}if(s.length){const c=O("#ccc").jch()[2];s.forEach(i=>{a[i]=c})}s.length=0;for(let c=a.length-1;c>0;c-=2)if(Number.isNaN(a[c]))s.push(c);else{s.forEach(i=>{a[i]=a[c]});break}for(let c=1;ccu(a).map(s=>uu(...s)));return a=>{const s=o.map(c=>{for(let i=0;in*a**e+o}function An({swatches:e,colorKeys:t,colorspace:r="LAB",shift:n=1,fullScale:o=!0,smooth:a=!1,distributeLightness:s="linear",sortColor:c=!0,asFun:i=!1}={}){const u=Ze[r];if(!u)throw new Error(`Colorspace “${r}” not supported`);if(!t)throw new Error(`Colorkeys missing: returned “${t}”`);let l;if(o)l=t.map(H=>e-e*(O(H).jch()[0]/100)).sort((H,x)=>H-x).concat(e),l.unshift(0);else{let H=t.map(A=>O(A).jch()[0]/100),x=Math.min(...H),N=Math.max(...H);l=H.map(A=>A===0||isNaN((A-x)/(N-x))?0:e-(A-x)/(N-x)*e).sort((A,R)=>A-R)}let f=bu(n,[1,e],[1,e]);if(f=l.map(H=>Math.max(0,f(H))),l=f,s==="polynomial"){const H=A=>Math.sqrt(Math.sqrt((Math.pow(A,2.25)+Math.pow(A,4))/2));l=f.map(A=>A/e).map(A=>H(A)*e)}const h=t.map((H,x)=>({colorKeys:lu(H),index:x})).sort((H,x)=>x.colorKeys[0]-H.colorKeys[0]).map(H=>t[H.index]);let d=[],b;if(o){const H=u==="lch"?O.lch(...O("#fff").lch()):"#ffffff",x=u==="lch"?O.lch(...O("#000").lch()):"#000000";d=[H,...h,x]}else c?d=h:d=t;let _;if(a){const H=d;if(d=d.map(x=>O(String(x))[u]()),u==="hcl"&&d.forEach(x=>{x[1]=Number.isNaN(x[1])?0:x[1]}),u==="jch")for(let x=0;xb(N))}else b=O.scale(d.map(H=>typeof H=="object"&&H.constructor===O.Color?H:String(H))).domain(l).mode(u);return i?b:(!a||a===!1?b.colors(e):_).filter(H=>H!=null)}function pu(e,t){const r=[],n={};return Object.keys(e).forEach(s=>{n[e[s][t]]=e[s]}),Object.keys(n).forEach(s=>r.push(n[s])),r}function mu(e){return Number.isNaN(e)?0:e}function Ln(e,t,r=!1){if(!e)throw new Error(`Cannot convert color value of “${e}”`);if(!Ze[t])throw new Error(`Cannot convert to colorspace “${t}”`);const n=Ze[t],o=O(String(e))[n]();if(t==="HSL"&&o.pop(),t==="HEX"){if(r){const u=O(String(e)).rgb();return{r:u[0],g:u[1],b:u[2]}}return o}const a={};let s=o.map(mu);s=s.map((u,l)=>{let f=Ee(u),h=l;n==="hsluv"&&(h+=2);let d=n.charAt(h);return n==="jch"&&d==="c"&&(d="C"),a[d==="j"?"J":d]=f,n in{lab:1,lch:1,jab:1,jch:1}?r||((d==="l"||d==="j")&&(f+="%"),d==="h"&&(f+="deg")):n!=="hsluv"&&(d==="s"||d==="l"||d==="v"?(a[d]=Ee(u,2),r||(f=Ee(u*100),f+="%")):d==="h"&&!r&&(f+="deg")),f});const i=`${n}(${s.join(", ")})`;return r?a:i}function Ha(e,t,r){const n=[e,t,r].map(o=>(o/=255,o<=.03928?o/12.92:((o+.055)/1.055)**2.4));return n[0]*.2126+n[1]*.7152+n[2]*.0722}function gu(e,t,r,n="wcag2"){if(r===void 0){const o=O.rgb(...t).hsluv()[2];r=Ee(o/100,2)}if(n==="wcag2"){const o=Ha(e[0],e[1],e[2]),a=Ha(t[0],t[1],t[2]),s=(o+.05)/(a+.05),c=(a+.05)/(o+.05);return r<.5?s>=1?s:-c:s<1?c:s===1?s:-s}else{if(n==="wcag3")return r<.5?xa(Et(e),Et(t))*-1:xa(Et(e),Et(t));throw new Error(`Contrast calculation method ${n} unsupported; use 'wcag2' or 'wcag3'`)}}function vu(e,t){if(!e)throw new Error("Array undefined");if(!Array.isArray(e))throw new Error("Passed object is not an array");const r=t==="wcag2"?0:1;return Math.min(...e.filter(n=>n>=r))}function _u(e,t){if(!e)throw new Error("Ratios undefined");e=e.sort((c,i)=>c-i);const r=vu(e,t),n=e.indexOf(r),o=[],a=e.slice(0,n),s=e.slice(n,e.length);for(let c=0;cc-i),o}const yu=(e,t,r,n,o)=>{const s=An({swatches:3e3,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),c={},i=f=>{if(c[f])return c[f];const h=O(s(f)).rgb(),d=gu(h,t,r,o);return c[f]=d,d},u=f=>{const h=i(0),d=i(3e3),b=h_&&x;)x--,g/=2,Hl.push(s(u(+f)))),l};let ae=class{constructor({name:t,colorKeys:r,colorspace:n="RGB",ratios:o,smooth:a=!1,output:s="HEX",saturation:c=100}){if(this._name=t,this._colorKeys=r,this._modifiedKeys=r,this._colorspace=n,this._ratios=o,this._smooth=a,this._output=s,this._saturation=c,!this._name)throw new Error("Color missing name");if(!this._colorKeys)throw new Error("Color Keys are undefined");if(!Ze[this._colorspace])throw new Error(`Colorspace “${n}” not supported`);if(!Ze[this._output])throw new Error(`Output “${n}” not supported`);for(let i=0;i{let n=O(`${r}`).oklch(),a=n[1]*(this._saturation/100),s=O.oklch(n[0],a,n[2]),c=O.rgb(s).hex();t.push(c)}),this._modifiedKeys=t,this._generateColorScale()}_generateColorScale(){this._colorScale=An({swatches:3e3,colorKeys:this._modifiedKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}};class qa extends ae{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){ae.prototype._generateColorScale.call(this);const t=An({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});t.push(...this.colorKeys);const r=t.map((a,s)=>({value:Math.round(hu(a)[2]),index:s})),o=pu(r,"value").map(a=>t[a.index]);return o.length>=101&&(o.length=100,o.push("#ffffff")),this._backgroundColorScale=o.map(a=>Ln(a,this._output)),this._backgroundColorScale}}class wu{constructor({colors:t,backgroundColor:r,lightness:n,contrast:o=1,saturation:a=100,output:s="HEX",formula:c="wcag2"}){if(this._output=s,this._colors=t,this._lightness=n,this._saturation=a,this._formula=c,this._setBackgroundColor(r),this._setBackgroundColorValue(),this._contrast=o,!this._colors)throw new Error("No colors are defined");if(!this._backgroundColor)throw new Error("Background color is undefined");if(t.forEach(i=>{if(!i.ratios)throw new Error(`Color ${i.name}'s ratios are undefined`)}),!Ze[this._output])throw new Error(`Output “${s}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(t){this._formula=t,this._findContrastColors()}get formula(){return this._formula}set contrast(t){this._contrast=t,this._findContrastColors()}get contrast(){return this._contrast}set lightness(t){this._lightness=t,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(t){this._saturation=t,this._updateColorSaturation(t),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(t){this._setBackgroundColor(t),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(t){this._colors=t,this._findContrastColors()}get colors(){return this._colors}set addColor(t){this._colors.push(t),this._findContrastColors()}set removeColor(t){const r=this._colors.filter(n=>n.name!==t.name);this._colors=r,this._findContrastColors()}set updateColor(t){if(Array.isArray(t))for(let r=0;rs.name===t[r].color);n=n[0];let o=this._colors.indexOf(n);const a=this._colors.filter(s=>s.name!==t[r].color);t[r].name&&(n.name=t[r].name),t[r].colorKeys&&(n.colorKeys=t[r].colorKeys),t[r].ratios&&(n.ratios=t[r].ratios),t[r].colorspace&&(n.colorspace=t[r].colorspace),t[r].smooth&&(n.smooth=t[r].smooth),n._generateColorScale(),a.splice(o,0,n),this._colors=a}else{let r=this._colors.filter(a=>a.name===t.color);r=r[0];let n=this._colors.indexOf(r);const o=this._colors.filter(a=>a.name!==t.color);t.name&&(r.name=t.name),t.colorKeys&&(r.colorKeys=t.colorKeys),t.ratios&&(r.ratios=t.ratios),t.colorspace&&(r.colorspace=t.colorspace),t.smooth&&(r.smooth=t.smooth),r._generateColorScale(),o.splice(n,0,r),this._colors=o}this._findContrastColors()}set output(t){this._output=t,this._colors.forEach(r=>{r.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(t){if(typeof t=="string"){const r=new qa({name:"background",colorKeys:[t],output:"RGB"}),n=Ee(O(String(t)).hsluv()[2]);this._backgroundColor=r,this._lightness=n,this._backgroundColorValue=r[this._lightness]}else{t.output="RGB";const r=t.backgroundColorScale[this._lightness];this._backgroundColor=t,this._backgroundColorValue=r}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(t){this._colors.map(r=>{r.saturation=t})}_findContrastColors(){const t=O(String(this._backgroundColorValue)).rgb(),r=this._lightness/100,o={background:Ln(this._backgroundColorValue,this._output)},a=[],s=[],c={...o};return a.push(o),this._colors.map(i=>{if(i.ratios!==void 0){let u;const l=[],f={name:i.name,values:l};let h;Array.isArray(i.ratios)?h=i.ratios:Array.isArray(i.ratios)||(u=Object.keys(i.ratios),h=Object.values(i.ratios)),h=h.map(b=>fu(+b,this._contrast));const d=yu(i,t,r,h,this._formula).map(b=>Ln(b,this._output));for(let b=0;bku($u(t,e),r),En=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=Be(e[t],0,255)):t===3&&(e[t]=Be(e[t],0,1));return e},Ma={};for(let e of["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"])Ma[`[object ${e}]`]=e.toLowerCase();function B(e){return Ma[Object.prototype.toString.call(e)]||"object"}const T=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):B(e[0])=="object"&&t?t.split("").filter(r=>e[0][r]!==void 0).map(r=>e[0][r]):e[0].slice(0),Je=e=>{if(e.length<2)return null;const t=e.length-1;return B(e[t])=="string"?e[t].toLowerCase():null},{PI:Tt,min:Oa,max:Na}=Math,ue=e=>Math.round(e*100)/100,Tn=e=>Math.round(e*100)/100,Ce=Tt*2,Sn=Tt/3,Cu=Tt/180,xu=180/Tt;function Aa(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}const E={format:{},autodetect:[]};class k{constructor(...t){const r=this;if(B(t[0])==="object"&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];let n=Je(t),o=!1;if(!n){o=!0,E.sorted||(E.autodetect=E.autodetect.sort((a,s)=>s.p-a.p),E.sorted=!0);for(let a of E.autodetect)if(n=a.test(...t),n)break}if(E.format[n]){const a=E.format[n].apply(null,o?t:t.slice(0,-1));r._rgb=En(a)}else throw new Error("unknown format: "+t);r._rgb.length===3&&r._rgb.push(1)}toString(){return B(this.hex)=="function"?this.hex():`[${this._rgb.join(",")}]`}}const Ru="3.2.0",G=(...e)=>new k(...e);G.version=Ru;const We={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},Hu=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,qu=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,La=e=>{if(e.match(Hu)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const t=parseInt(e,16),r=t>>16,n=t>>8&255,o=t&255;return[r,n,o,1]}if(e.match(qu)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);const t=parseInt(e,16),r=t>>24&255,n=t>>16&255,o=t>>8&255,a=Math.round((t&255)/255*100)/100;return[r,n,o,a]}throw new Error(`unknown hex color: ${e}`)},{round:St}=Math,Ea=(...e)=>{let[t,r,n,o]=T(e,"rgba"),a=Je(e)||"auto";o===void 0&&(o=1),a==="auto"&&(a=o<1?"rgba":"rgb"),t=St(t),r=St(r),n=St(n);let c="000000"+(t<<16|r<<8|n).toString(16);c=c.substr(c.length-6);let i="0"+St(o*255).toString(16);switch(i=i.substr(i.length-2),a.toLowerCase()){case"rgba":return`#${c}${i}`;case"argb":return`#${i}${c}`;default:return`#${c}`}};k.prototype.name=function(){const e=Ea(this._rgb,"rgb");for(let t of Object.keys(We))if(We[t]===e)return t.toLowerCase();return e},E.format.named=e=>{if(e=e.toLowerCase(),We[e])return La(We[e]);throw new Error("unknown color name: "+e)},E.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&B(e)==="string"&&We[e.toLowerCase()])return"named"}}),k.prototype.alpha=function(e,t=!1){return e!==void 0&&B(e)==="number"?t?(this._rgb[3]=e,this):new k([this._rgb[0],this._rgb[1],this._rgb[2],e],"rgb"):this._rgb[3]},k.prototype.clipped=function(){return this._rgb._clipped||!1};const _e={Kn:18,labWhitePoint:"d65",Xn:.95047,Yn:1,Zn:1.08883,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},Mu=new Map([["a",[1.0985,.35585]],["b",[1.0985,.35585]],["c",[.98074,1.18232]],["d50",[.96422,.82521]],["d55",[.95682,.92149]],["d65",[.95047,1.08883]],["e",[1,1,1]],["f2",[.99186,.67393]],["f7",[.95041,1.08747]],["f11",[1.00962,.6435]],["icc",[.96422,.82521]]]);function xe(e){const t=Mu.get(String(e).toLowerCase());if(!t)throw new Error("unknown Lab illuminant "+e);_e.labWhitePoint=e,_e.Xn=t[0],_e.Zn=t[1]}function dt(){return _e.labWhitePoint}const Pn=(...e)=>{e=T(e,"lab");const[t,r,n]=e,[o,a,s]=Ou(t,r,n),[c,i,u]=Ta(o,a,s);return[c,i,u,e.length>3?e[3]:1]},Ou=(e,t,r)=>{const{kE:n,kK:o,kKE:a,Xn:s,Yn:c,Zn:i}=_e,u=(e+16)/116,l=.002*t+u,f=u-.005*r,h=l*l*l,d=f*f*f,b=h>n?h:(116*l-16)/o,_=e>a?Math.pow((e+16)/116,3):e/o,g=d>n?d:(116*f-16)/o,v=b*s,H=_*c,x=g*i;return[v,H,x]},jn=e=>{const t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*Math.pow(e,1/2.4)-.055)*t},Ta=(e,t,r)=>{const{MtxAdaptMa:n,MtxAdaptMaI:o,MtxXYZ2RGB:a,RefWhiteRGB:s,Xn:c,Yn:i,Zn:u}=_e,l=c*n.m00+i*n.m10+u*n.m20,f=c*n.m01+i*n.m11+u*n.m21,h=c*n.m02+i*n.m12+u*n.m22,d=s.X*n.m00+s.Y*n.m10+s.Z*n.m20,b=s.X*n.m01+s.Y*n.m11+s.Z*n.m21,_=s.X*n.m02+s.Y*n.m12+s.Z*n.m22,g=(e*n.m00+t*n.m10+r*n.m20)*(d/l),v=(e*n.m01+t*n.m11+r*n.m21)*(b/f),H=(e*n.m02+t*n.m12+r*n.m22)*(_/h),x=g*o.m00+v*o.m10+H*o.m20,N=g*o.m01+v*o.m11+H*o.m21,A=g*o.m02+v*o.m12+H*o.m22,R=jn(x*a.m00+N*a.m10+A*a.m20),m=jn(x*a.m01+N*a.m11+A*a.m21),p=jn(x*a.m02+N*a.m12+A*a.m22);return[R*255,m*255,p*255]},Bn=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),[a,s,c]=Sa(t,r,n),[i,u,l]=Nu(a,s,c);return[i,u,l,...o.length>0&&o[0]<1?[o[0]]:[]]};function Nu(e,t,r){const{Xn:n,Yn:o,Zn:a,kE:s,kK:c}=_e,i=e/n,u=t/o,l=r/a,f=i>s?Math.pow(i,1/3):(c*i+16)/116,h=u>s?Math.pow(u,1/3):(c*u+16)/116,d=l>s?Math.pow(l,1/3):(c*l+16)/116;return[116*h-16,500*(f-h),200*(h-d)]}function Gn(e){const t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4))*t}const Sa=(e,t,r)=>{e=Gn(e/255),t=Gn(t/255),r=Gn(r/255);const{MtxRGB2XYZ:n,MtxAdaptMa:o,MtxAdaptMaI:a,Xn:s,Yn:c,Zn:i,As:u,Bs:l,Cs:f}=_e;let h=e*n.m00+t*n.m10+r*n.m20,d=e*n.m01+t*n.m11+r*n.m21,b=e*n.m02+t*n.m12+r*n.m22;const _=s*o.m00+c*o.m10+i*o.m20,g=s*o.m01+c*o.m11+i*o.m21,v=s*o.m02+c*o.m12+i*o.m22;let H=h*o.m00+d*o.m10+b*o.m20,x=h*o.m01+d*o.m11+b*o.m21,N=h*o.m02+d*o.m12+b*o.m22;return H*=_/u,x*=g/l,N*=v/f,h=H*a.m00+x*a.m10+N*a.m20,d=H*a.m01+x*a.m11+N*a.m21,b=H*a.m02+x*a.m12+N*a.m22,[h,d,b]};k.prototype.lab=function(){return Bn(this._rgb)},Object.assign(G,{lab:(...e)=>new k(...e,"lab"),getLabWhitePoint:dt,setLabWhitePoint:xe}),E.format.lab=Pn,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"lab"),B(e)==="array"&&e.length===3)return"lab"}}),k.prototype.darken=function(e=1){const t=this,r=t.lab();return r[0]-=_e.Kn*e,new k(r,"lab").alpha(t.alpha(),!0)},k.prototype.brighten=function(e=1){return this.darken(-e)},k.prototype.darker=k.prototype.darken,k.prototype.brighter=k.prototype.brighten,k.prototype.get=function(e){const[t,r]=e.split("."),n=this[t]();if(r){const o=t.indexOf(r)-(t.substr(0,2)==="ok"?2:0);if(o>-1)return n[o];throw new Error(`unknown channel ${r} in mode ${t}`)}else return n};const{pow:Au}=Math,Lu=1e-7,Eu=20;k.prototype.luminance=function(e,t="rgb"){if(e!==void 0&&B(e)==="number"){if(e===0)return new k([0,0,0,this._rgb[3]],"rgb");if(e===1)return new k([255,255,255,this._rgb[3]],"rgb");let r=this.luminance(),n=Eu;const o=(s,c)=>{const i=s.interpolate(c,.5,t),u=i.luminance();return Math.abs(e-u)e?o(s,i):o(i,c)},a=(r>e?o(new k([0,0,0]),this):o(this,new k([255,255,255]))).rgb();return new k([...a,this._rgb[3]])}return Tu(...this._rgb.slice(0,3))};const Tu=(e,t,r)=>(e=In(e),t=In(t),r=In(r),.2126*e+.7152*t+.0722*r),In=e=>(e/=255,e<=.03928?e/12.92:Au((e+.055)/1.055,2.4)),ne={},Ue=(e,t,r=.5,...n)=>{let o=n[0]||"lrgb";if(!ne[o]&&!n.length&&(o=Object.keys(ne)[0]),!ne[o])throw new Error(`interpolation mode ${o} is not defined`);return B(e)!=="object"&&(e=new k(e)),B(t)!=="object"&&(t=new k(t)),ne[o](e,t,r).alpha(e.alpha()+r*(t.alpha()-e.alpha()))};k.prototype.mix=k.prototype.interpolate=function(e,t=.5,...r){return Ue(this,e,t,...r)},k.prototype.premultiply=function(e=!1){const t=this._rgb,r=t[3];return e?(this._rgb=[t[0]*r,t[1]*r,t[2]*r,r],this):new k([t[0]*r,t[1]*r,t[2]*r,r],"rgb")};const{sin:Su,cos:Pu}=Math,Pa=(...e)=>{let[t,r,n]=T(e,"lch");return isNaN(n)&&(n=0),n=n*Cu,[t,Pu(n)*r,Su(n)*r]},zn=(...e)=>{e=T(e,"lch");const[t,r,n]=e,[o,a,s]=Pa(t,r,n),[c,i,u]=Pn(o,a,s);return[c,i,u,e.length>3?e[3]:1]},ju=(...e)=>{const t=Aa(T(e,"hcl"));return zn(...t)},{sqrt:Bu,atan2:Gu,round:Iu}=Math,ja=(...e)=>{const[t,r,n]=T(e,"lab"),o=Bu(r*r+n*n);let a=(Gu(n,r)*xu+360)%360;return Iu(o*1e4)===0&&(a=Number.NaN),[t,o,a]},Fn=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),[a,s,c]=Bn(t,r,n),[i,u,l]=ja(a,s,c);return[i,u,l,...o.length>0&&o[0]<1?[o[0]]:[]]};k.prototype.lch=function(){return Fn(this._rgb)},k.prototype.hcl=function(){return Aa(Fn(this._rgb))},Object.assign(G,{lch:(...e)=>new k(...e,"lch"),hcl:(...e)=>new k(...e,"hcl")}),E.format.lch=zn,E.format.hcl=ju,["lch","hcl"].forEach(e=>E.autodetect.push({p:2,test:(...t)=>{if(t=T(t,e),B(t)==="array"&&t.length===3)return e}})),k.prototype.saturate=function(e=1){const t=this,r=t.lch();return r[1]+=_e.Kn*e,r[1]<0&&(r[1]=0),new k(r,"lch").alpha(t.alpha(),!0)},k.prototype.desaturate=function(e=1){return this.saturate(-e)},k.prototype.set=function(e,t,r=!1){const[n,o]=e.split("."),a=this[n]();if(o){const s=n.indexOf(o)-(n.substr(0,2)==="ok"?2:0);if(s>-1){if(B(t)=="string")switch(t.charAt(0)){case"+":a[s]+=+t;break;case"-":a[s]+=+t;break;case"*":a[s]*=+t.substr(1);break;case"/":a[s]/=+t.substr(1);break;default:a[s]=+t}else if(B(t)==="number")a[s]=t;else throw new Error("unsupported value for Color.set");const c=new k(a,n);return r?(this._rgb=c._rgb,this):c}throw new Error(`unknown channel ${o} in mode ${n}`)}else return a},k.prototype.tint=function(e=.5,...t){return Ue(this,"white",e,...t)},k.prototype.shade=function(e=.5,...t){return Ue(this,"black",e,...t)};const zu=(e,t,r)=>{const n=e._rgb,o=t._rgb;return new k(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"rgb")};ne.rgb=zu;const{sqrt:Xn,pow:Qe}=Math,Fu=(e,t,r)=>{const[n,o,a]=e._rgb,[s,c,i]=t._rgb;return new k(Xn(Qe(n,2)*(1-r)+Qe(s,2)*r),Xn(Qe(o,2)*(1-r)+Qe(c,2)*r),Xn(Qe(a,2)*(1-r)+Qe(i,2)*r),"rgb")};ne.lrgb=Fu;const Xu=(e,t,r)=>{const n=e.lab(),o=t.lab();return new k(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"lab")};ne.lab=Xu;const et=(e,t,r,n)=>{let o,a;n==="hsl"?(o=e.hsl(),a=t.hsl()):n==="hsv"?(o=e.hsv(),a=t.hsv()):n==="hcg"?(o=e.hcg(),a=t.hcg()):n==="hsi"?(o=e.hsi(),a=t.hsi()):n==="lch"||n==="hcl"?(n="hcl",o=e.hcl(),a=t.hcl()):n==="oklch"&&(o=e.oklch().reverse(),a=t.oklch().reverse());let s,c,i,u,l,f;(n.substr(0,1)==="h"||n==="oklch")&&([s,i,l]=o,[c,u,f]=a);let h,d,b,_;return!isNaN(s)&&!isNaN(c)?(c>s&&c-s>180?_=c-(s+360):c180?_=c+360-s:_=c-s,d=s+r*_):isNaN(s)?isNaN(c)?d=Number.NaN:(d=c,(l==1||l==0)&&n!="hsv"&&(h=u)):(d=s,(f==1||f==0)&&n!="hsv"&&(h=i)),h===void 0&&(h=i+r*(u-i)),b=l+r*(f-l),n==="oklch"?new k([b,h,d],n):new k([d,h,b],n)},Ba=(e,t,r)=>et(e,t,r,"lch");ne.lch=Ba,ne.hcl=Ba;const Ku=e=>{if(B(e)=="number"&&e>=0&&e<=16777215){const t=e>>16,r=e>>8&255,n=e&255;return[t,r,n,1]}throw new Error("unknown num color: "+e)},Du=(...e)=>{const[t,r,n]=T(e,"rgb");return(t<<16)+(r<<8)+n};k.prototype.num=function(){return Du(this._rgb)},Object.assign(G,{num:(...e)=>new k(...e,"num")}),E.format.num=Ku,E.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&B(e[0])==="number"&&e[0]>=0&&e[0]<=16777215)return"num"}});const Vu=(e,t,r)=>{const n=e.num(),o=t.num();return new k(n+r*(o-n),"num")};ne.num=Vu;const{floor:Yu}=Math,Zu=(...e)=>{e=T(e,"hcg");let[t,r,n]=e,o,a,s;n=n*255;const c=r*255;if(r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const i=Yu(t),u=t-i,l=n*(1-r),f=l+c*(1-u),h=l+c*u,d=l+c;switch(i){case 0:[o,a,s]=[d,h,l];break;case 1:[o,a,s]=[f,d,l];break;case 2:[o,a,s]=[l,d,h];break;case 3:[o,a,s]=[l,f,d];break;case 4:[o,a,s]=[h,l,d];break;case 5:[o,a,s]=[d,l,f];break}}return[o,a,s,e.length>3?e[3]:1]},Ju=(...e)=>{const[t,r,n]=T(e,"rgb"),o=Oa(t,r,n),a=Na(t,r,n),s=a-o,c=s*100/255,i=o/(255-s)*100;let u;return s===0?u=Number.NaN:(t===a&&(u=(r-n)/s),r===a&&(u=2+(n-t)/s),n===a&&(u=4+(t-r)/s),u*=60,u<0&&(u+=360)),[u,c,i]};k.prototype.hcg=function(){return Ju(this._rgb)};const Wu=(...e)=>new k(...e,"hcg");G.hcg=Wu,E.format.hcg=Zu,E.autodetect.push({p:1,test:(...e)=>{if(e=T(e,"hcg"),B(e)==="array"&&e.length===3)return"hcg"}});const Uu=(e,t,r)=>et(e,t,r,"hcg");ne.hcg=Uu;const{cos:tt}=Math,Qu=(...e)=>{e=T(e,"hsi");let[t,r,n]=e,o,a,s;return isNaN(t)&&(t=0),isNaN(r)&&(r=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(s=(1-r)/3,o=(1+r*tt(Ce*t)/tt(Sn-Ce*t))/3,a=1-(s+o)):t<2/3?(t-=1/3,o=(1-r)/3,a=(1+r*tt(Ce*t)/tt(Sn-Ce*t))/3,s=1-(o+a)):(t-=2/3,a=(1-r)/3,s=(1+r*tt(Ce*t)/tt(Sn-Ce*t))/3,o=1-(a+s)),o=Be(n*o*3),a=Be(n*a*3),s=Be(n*s*3),[o*255,a*255,s*255,e.length>3?e[3]:1]},{min:ef,sqrt:tf,acos:rf}=Math,nf=(...e)=>{let[t,r,n]=T(e,"rgb");t/=255,r/=255,n/=255;let o;const a=ef(t,r,n),s=(t+r+n)/3,c=s>0?1-a/s:0;return c===0?o=NaN:(o=(t-r+(t-n))/2,o/=tf((t-r)*(t-r)+(t-n)*(r-n)),o=rf(o),n>r&&(o=Ce-o),o/=Ce),[o*360,c,s]};k.prototype.hsi=function(){return nf(this._rgb)};const of=(...e)=>new k(...e,"hsi");G.hsi=of,E.format.hsi=Qu,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"hsi"),B(e)==="array"&&e.length===3)return"hsi"}});const sf=(e,t,r)=>et(e,t,r,"hsi");ne.hsi=sf;const Kn=(...e)=>{e=T(e,"hsl");const[t,r,n]=e;let o,a,s;if(r===0)o=a=s=n*255;else{const c=[0,0,0],i=[0,0,0],u=n<.5?n*(1+r):n+r-n*r,l=2*n-u,f=t/360;c[0]=f+1/3,c[1]=f,c[2]=f-1/3;for(let h=0;h<3;h++)c[h]<0&&(c[h]+=1),c[h]>1&&(c[h]-=1),6*c[h]<1?i[h]=l+(u-l)*6*c[h]:2*c[h]<1?i[h]=u:3*c[h]<2?i[h]=l+(u-l)*(2/3-c[h])*6:i[h]=l;[o,a,s]=[i[0]*255,i[1]*255,i[2]*255]}return e.length>3?[o,a,s,e[3]]:[o,a,s,1]},Ga=(...e)=>{e=T(e,"rgba");let[t,r,n]=e;t/=255,r/=255,n/=255;const o=Oa(t,r,n),a=Na(t,r,n),s=(a+o)/2;let c,i;return a===o?(c=0,i=Number.NaN):c=s<.5?(a-o)/(a+o):(a-o)/(2-a-o),t==a?i=(r-n)/(a-o):r==a?i=2+(n-t)/(a-o):n==a&&(i=4+(t-r)/(a-o)),i*=60,i<0&&(i+=360),e.length>3&&e[3]!==void 0?[i,c,s,e[3]]:[i,c,s]};k.prototype.hsl=function(){return Ga(this._rgb)};const af=(...e)=>new k(...e,"hsl");G.hsl=af,E.format.hsl=Kn,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"hsl"),B(e)==="array"&&e.length===3)return"hsl"}});const cf=(e,t,r)=>et(e,t,r,"hsl");ne.hsl=cf;const{floor:uf}=Math,ff=(...e)=>{e=T(e,"hsv");let[t,r,n]=e,o,a,s;if(n*=255,r===0)o=a=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const c=uf(t),i=t-c,u=n*(1-r),l=n*(1-r*i),f=n*(1-r*(1-i));switch(c){case 0:[o,a,s]=[n,f,u];break;case 1:[o,a,s]=[l,n,u];break;case 2:[o,a,s]=[u,n,f];break;case 3:[o,a,s]=[u,l,n];break;case 4:[o,a,s]=[f,u,n];break;case 5:[o,a,s]=[n,u,l];break}}return[o,a,s,e.length>3?e[3]:1]},{min:lf,max:hf}=Math,df=(...e)=>{e=T(e,"rgb");let[t,r,n]=e;const o=lf(t,r,n),a=hf(t,r,n),s=a-o;let c,i,u;return u=a/255,a===0?(c=Number.NaN,i=0):(i=s/a,t===a&&(c=(r-n)/s),r===a&&(c=2+(n-t)/s),n===a&&(c=4+(t-r)/s),c*=60,c<0&&(c+=360)),[c,i,u]};k.prototype.hsv=function(){return df(this._rgb)};const bf=(...e)=>new k(...e,"hsv");G.hsv=bf,E.format.hsv=ff,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"hsv"),B(e)==="array"&&e.length===3)return"hsv"}});const pf=(e,t,r)=>et(e,t,r,"hsv");ne.hsv=pf;function Pt(e,t){let r=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(s=>[s]));let n=t[0].length,o=t[0].map((s,c)=>t.map(i=>i[c])),a=e.map(s=>o.map(c=>Array.isArray(s)?s.reduce((i,u,l)=>i+u*(c[l]||0),0):c.reduce((i,u)=>i+u*s,0)));return r===1&&(a=a[0]),n===1?a.map(s=>s[0]):a}const Dn=(...e)=>{e=T(e,"lab");const[t,r,n,...o]=e,[a,s,c]=mf([t,r,n]),[i,u,l]=Ta(a,s,c);return[i,u,l,...o.length>0&&o[0]<1?[o[0]]:[]]};function mf(e){var t=[[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],r=[[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],n=Pt(r,e);return Pt(t,n.map(o=>o**3))}const Vn=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),a=Sa(t,r,n);return[...gf(a),...o.length>0&&o[0]<1?[o[0]]:[]]};function gf(e){const t=[[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],r=[[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],n=Pt(t,e);return Pt(r,n.map(o=>Math.cbrt(o)))}k.prototype.oklab=function(){return Vn(this._rgb)},Object.assign(G,{oklab:(...e)=>new k(...e,"oklab")}),E.format.oklab=Dn,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"oklab"),B(e)==="array"&&e.length===3)return"oklab"}});const vf=(e,t,r)=>{const n=e.oklab(),o=t.oklab();return new k(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"oklab")};ne.oklab=vf;const _f=(e,t,r)=>et(e,t,r,"oklch");ne.oklch=_f;const{pow:Yn,sqrt:Zn,PI:Jn,cos:Ia,sin:za,atan2:yf}=Math,wf=(e,t="lrgb",r=null)=>{const n=e.length;r||(r=Array.from(new Array(n)).map(()=>1));const o=n/r.reduce(function(f,h){return f+h});if(r.forEach((f,h)=>{r[h]*=o}),e=e.map(f=>new k(f)),t==="lrgb")return kf(e,r);const a=e.shift(),s=a.get(t),c=[];let i=0,u=0;for(let f=0;f{const d=f.get(t);l+=f.alpha()*r[h+1];for(let b=0;b=360;)h-=360;s[f]=h}else s[f]=s[f]/c[f];return l/=n,new k(s,t).alpha(l>.99999?1:l,!0)},kf=(e,t)=>{const r=e.length,n=[0,0,0,0];for(let o=0;o.9999999&&(n[3]=1),new k(En(n))},{pow:$f}=Math;function jt(e){let t="rgb",r=G("#ccc"),n=0,o=[0,1],a=[0,1],s=[],c=[0,0],i=!1,u=[],l=!1,f=0,h=1,d=!1,b={},_=!0,g=1;const v=function(p){if(p=p||["#fff","#000"],p&&B(p)==="string"&&G.brewer&&G.brewer[p.toLowerCase()]&&(p=G.brewer[p.toLowerCase()]),B(p)==="array"){p.length===1&&(p=[p[0],p[0]]),p=p.slice(0);for(let y=0;y=i[w];)w++;return w-1}return 0};let x=p=>p,N=p=>p;const A=function(p,y){let w,C;if(y==null&&(y=!1),isNaN(p)||p===null)return r;y?C=p:i&&i.length>2?C=H(p)/(i.length-2):h!==f?C=(p-f)/(h-f):C=1,C=N(C),y||(C=x(C)),g!==1&&(C=$f(C,g)),C=c[0]+C*(1-c[0]-c[1]),C=Be(C,0,1);const q=Math.floor(C*1e4);if(_&&b[q])w=b[q];else{if(B(u)==="array")for(let M=0;M=S&&M===s.length-1){w=u[M];break}if(C>S&&Cb={};v(e);const m=function(p){const y=G(A(p));return l&&y[l]?y[l]():y};return m.classes=function(p){if(p!=null){if(B(p)==="array")i=p,o=[p[0],p[p.length-1]];else{const y=G.analyze(o);p===0?i=[y.min,y.max]:i=G.limits(y,"e",p)}return m}return i},m.domain=function(p){if(!arguments.length)return a;a=p.slice(0),f=p[0],h=p[p.length-1],s=[];const y=u.length;if(p.length===y&&f!==h)for(let w of Array.from(p))s.push((w-f)/(h-f));else{for(let w=0;w2){const w=p.map((q,M)=>M/(p.length-1)),C=p.map(q=>(q-f)/(h-f));C.every((q,M)=>w[M]===q)||(N=q=>{if(q<=0||q>=1)return q;let M=0;for(;q>=C[M+1];)M++;const S=(q-C[M])/(C[M+1]-C[M]);return w[M]+S*(w[M+1]-w[M])})}}return o=[f,h],m},m.mode=function(p){return arguments.length?(t=p,R(),m):t},m.range=function(p,y){return v(p),m},m.out=function(p){return l=p,m},m.spread=function(p){return arguments.length?(n=p,m):n},m.correctLightness=function(p){return p==null&&(p=!0),d=p,R(),d?x=function(y){const w=A(0,!0).lab()[0],C=A(1,!0).lab()[0],q=w>C;let M=A(y,!0).lab()[0];const S=w+(C-w)*y;let X=M-S,D=0,U=1,ce=20;for(;Math.abs(X)>.01&&ce-- >0;)(function(){return q&&(X*=-1),X<0?(D=y,y+=(U-y)*.5):(U=y,y+=(D-y)*.5),M=A(y,!0).lab()[0],X=M-S})();return y}:x=y=>y,m},m.padding=function(p){return p!=null?(B(p)==="number"&&(p=[p,p]),c=p,m):c},m.colors=function(p,y){arguments.length<2&&(y="hex");let w=[];if(arguments.length===0)w=u.slice(0);else if(p===1)w=[m(.5)];else if(p>1){const C=o[0],q=o[1]-C;w=Cf(0,p).map(M=>m(C+M/(p-1)*q))}else{e=[];let C=[];if(i&&i.length>2)for(let q=1,M=i.length,S=1<=M;S?qM;S?q++:q--)C.push((i[q-1]+i[q])*.5);else C=o;w=C.map(q=>m(q))}return G[y]&&(w=w.map(C=>C[y]())),w},m.cache=function(p){return p!=null?(_=p,m):_},m.gamma=function(p){return p!=null?(g=p,m):g},m.nodata=function(p){return p!=null?(r=G(p),m):r},m}function Cf(e,t,r){let n=[],o=ea;o?s++:s--)n.push(s);return n}const xf=function(e){let t=[1,1];for(let r=1;rnew k(a)),e.length===2)[r,n]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>r[c]+a*(n[c]-r[c]));return new k(s,"lab")};else if(e.length===3)[r,n,o]=e.map(a=>a.lab()),t=function(a){const s=[0,1,2].map(c=>(1-a)*(1-a)*r[c]+2*(1-a)*a*n[c]+a*a*o[c]);return new k(s,"lab")};else if(e.length===4){let a;[r,n,o,a]=e.map(s=>s.lab()),t=function(s){const c=[0,1,2].map(i=>(1-s)*(1-s)*(1-s)*r[i]+3*(1-s)*(1-s)*s*n[i]+3*(1-s)*s*s*o[i]+s*s*s*a[i]);return new k(c,"lab")}}else if(e.length>=5){let a,s,c;a=e.map(i=>i.lab()),c=e.length-1,s=xf(c),t=function(i){const u=1-i,l=[0,1,2].map(f=>a.reduce((h,d,b)=>h+s[b]*u**(c-b)*i**b*d[f],0));return new k(l,"lab")}}else throw new RangeError("No point in running bezier with only one color.");return t},Hf=e=>{const t=Rf(e);return t.scale=()=>jt(t),t},{round:Fa}=Math;k.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Fa)},k.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,r)=>r<3?e===!1?t:Fa(t):t)},Object.assign(G,{rgb:(...e)=>new k(...e,"rgb")}),E.format.rgb=(...e)=>{const t=T(e,"rgba");return t[3]===void 0&&(t[3]=1),t},E.autodetect.push({p:3,test:(...e)=>{if(e=T(e,"rgba"),B(e)==="array"&&(e.length===3||e.length===4&&B(e[3])=="number"&&e[3]>=0&&e[3]<=1))return"rgb"}});const me=(e,t,r)=>{if(!me[r])throw new Error("unknown blend mode "+r);return me[r](e,t)},Te=e=>(t,r)=>{const n=G(r).rgb(),o=G(t).rgb();return G.rgb(e(n,o))},Se=e=>(t,r)=>{const n=[];return n[0]=e(t[0],r[0]),n[1]=e(t[1],r[1]),n[2]=e(t[2],r[2]),n},qf=e=>e,Mf=(e,t)=>e*t/255,Of=(e,t)=>e>t?t:e,Nf=(e,t)=>e>t?e:t,Af=(e,t)=>255*(1-(1-e/255)*(1-t/255)),Lf=(e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)),Ef=(e,t)=>255*(1-(1-t/255)/(e/255)),Tf=(e,t)=>e===255?255:(e=255*(t/255)/(1-e/255),e>255?255:e);me.normal=Te(Se(qf)),me.multiply=Te(Se(Mf)),me.screen=Te(Se(Af)),me.overlay=Te(Se(Lf)),me.darken=Te(Se(Of)),me.lighten=Te(Se(Nf)),me.dodge=Te(Se(Tf)),me.burn=Te(Se(Ef));const{pow:Sf,sin:Pf,cos:jf}=Math;function Bf(e=300,t=-1.5,r=1,n=1,o=[0,1]){let a=0,s;B(o)==="array"?s=o[1]-o[0]:(s=0,o=[o,o]);const c=function(i){const u=Ce*((e+120)/360+t*i),l=Sf(o[0]+s*i,n),h=(a!==0?r[0]+i*a:r)*l*(1-l)/2,d=jf(u),b=Pf(u),_=l+h*(-.14861*d+1.78277*b),g=l+h*(-.29227*d-.90649*b),v=l+h*(1.97294*d);return G(En([_*255,g*255,v*255,1]))};return c.start=function(i){return i==null?e:(e=i,c)},c.rotations=function(i){return i==null?t:(t=i,c)},c.gamma=function(i){return i==null?n:(n=i,c)},c.hue=function(i){return i==null?r:(r=i,B(r)==="array"?(a=r[1]-r[0],a===0&&(r=r[1])):a=0,c)},c.lightness=function(i){return i==null?o:(B(i)==="array"?(o=i,s=i[1]-i[0]):(o=[i,i],s=0),c)},c.scale=()=>G.scale(c),c.hue(r),c}const Gf="0123456789abcdef",{floor:If,random:zf}=Math,Ff=(e=zf)=>{let t="#";for(let r=0;r<6;r++)t+=Gf.charAt(If(e()*16));return new k(t,"hex")},{log:Xa,pow:Xf,floor:Kf,abs:Df}=Math;function Ka(e,t=null){const r={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return B(e)==="object"&&(e=Object.values(e)),e.forEach(n=>{t&&B(n)==="object"&&(n=n[t]),n!=null&&!isNaN(n)&&(r.values.push(n),r.sum+=n,nr.max&&(r.max=n),r.count+=1)}),r.domain=[r.min,r.max],r.limits=(n,o)=>Da(r,n,o),r}function Da(e,t="equal",r=7){B(e)=="array"&&(e=Ka(e));const{min:n,max:o}=e,a=e.values.sort((c,i)=>c-i);if(r===1)return[n,o];const s=[];if(t.substr(0,1)==="c"&&(s.push(n),s.push(o)),t.substr(0,1)==="e"){s.push(n);for(let c=1;c 0");const c=Math.LOG10E*Xa(n),i=Math.LOG10E*Xa(o);s.push(n);for(let u=1;u200&&(f=!1)}const b={};for(let g=0;gg-v),s.push(_[0]);for(let g=1;g<_.length;g+=2){const v=_[g];!isNaN(v)&&s.indexOf(v)===-1&&s.push(v)}}return s}const Vf=(e,t)=>{e=new k(e),t=new k(t);const r=e.luminance(),n=t.luminance();return r>n?(r+.05)/(n+.05):(n+.05)/(r+.05)};const Va=.027,Yf=5e-4,Zf=.1,Ya=1.14,Bt=.022,Za=1.414,Jf=(e,t)=>{e=new k(e),t=new k(t),e.alpha()<1&&(e=Ue(t,e,e.alpha(),"rgb"));const r=Ja(...e.rgb()),n=Ja(...t.rgb()),o=r>=Bt?r:r+Math.pow(Bt-r,Za),a=n>=Bt?n:n+Math.pow(Bt-n,Za),s=Math.pow(a,.56)-Math.pow(o,.57),c=Math.pow(a,.65)-Math.pow(o,.62),i=Math.abs(a-o)0?i-Va:i+Va)*100};function Ja(e,t,r){return .2126729*Math.pow(e/255,2.4)+.7151522*Math.pow(t/255,2.4)+.072175*Math.pow(r/255,2.4)}const{sqrt:Re,pow:Z,min:Wf,max:Uf,atan2:Wa,abs:Ua,cos:Gt,sin:Qa,exp:Qf,PI:ec}=Math;function el(e,t,r=1,n=1,o=1){var a=function(he){return 360*he/(2*ec)},s=function(he){return 2*ec*he/360};e=new k(e),t=new k(t);const[c,i,u]=Array.from(e.lab()),[l,f,h]=Array.from(t.lab()),d=(c+l)/2,b=Re(Z(i,2)+Z(u,2)),_=Re(Z(f,2)+Z(h,2)),g=(b+_)/2,v=.5*(1-Re(Z(g,7)/(Z(g,7)+Z(25,7)))),H=i*(1+v),x=f*(1+v),N=Re(Z(H,2)+Z(u,2)),A=Re(Z(x,2)+Z(h,2)),R=(N+A)/2,m=a(Wa(u,H)),p=a(Wa(h,x)),y=m>=0?m:m+360,w=p>=0?p:p+360,C=Ua(y-w)>180?(y+w+360)/2:(y+w)/2,q=1-.17*Gt(s(C-30))+.24*Gt(s(2*C))+.32*Gt(s(3*C+6))-.2*Gt(s(4*C-63));let M=w-y;M=Ua(M)<=180?M:w<=y?M+360:M-360,M=2*Re(N*A)*Qa(s(M)/2);const S=l-c,X=A-N,D=1+.015*Z(d-50,2)/Re(20+Z(d-50,2)),U=1+.045*R,ce=1+.015*R*q,ye=30*Qf(-Z((C-275)/25,2)),le=-(2*Re(Z(R,7)/(Z(R,7)+Z(25,7))))*Qa(2*s(ye)),qe=Re(Z(S/(r*D),2)+Z(X/(n*U),2)+Z(M/(o*ce),2)+le*(X/(n*U))*(M/(o*ce)));return Uf(0,Wf(100,qe))}function tl(e,t,r="lab"){e=new k(e),t=new k(t);const n=e.get(r),o=t.get(r);let a=0;for(let s in n){const c=(n[s]||0)-(o[s]||0);a+=c*c}return Math.sqrt(a)}const rl=(...e)=>{try{return new k(...e),!0}catch{return!1}},nl={cool(){return jt([G.hsl(180,1,.9),G.hsl(250,.7,.4)])},hot(){return jt(["#000","#f00","#ff0","#fff"]).mode("rgb")}},Wn={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]},tc=Object.keys(Wn),rc=new Map(tc.map(e=>[e.toLowerCase(),e])),ol=typeof Proxy=="function"?new Proxy(Wn,{get(e,t){const r=t.toLowerCase();if(rc.has(r))return e[rc.get(r)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tc)}}):Wn,sl=(...e)=>{e=T(e,"cmyk");const[t,r,n,o]=e,a=e.length>4?e[4]:1;return o===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-o),r>=1?0:255*(1-r)*(1-o),n>=1?0:255*(1-n)*(1-o),a]},{max:nc}=Math,al=(...e)=>{let[t,r,n]=T(e,"rgb");t=t/255,r=r/255,n=n/255;const o=1-nc(t,nc(r,n)),a=o<1?1/(1-o):0,s=(1-t-o)*a,c=(1-r-o)*a,i=(1-n-o)*a;return[s,c,i,o]};k.prototype.cmyk=function(){return al(this._rgb)},Object.assign(G,{cmyk:(...e)=>new k(...e,"cmyk")}),E.format.cmyk=sl,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"cmyk"),B(e)==="array"&&e.length===4)return"cmyk"}});const cl=(...e)=>{const t=T(e,"hsla");let r=Je(e)||"lsa";return t[0]=ue(t[0]||0)+"deg",t[1]=ue(t[1]*100)+"%",t[2]=ue(t[2]*100)+"%",r==="hsla"||t.length>3&&t[3]<1?(t[3]="/ "+(t.length>3?t[3]:1),r="hsla"):t.length=3,`${r.substr(0,3)}(${t.join(" ")})`},il=(...e)=>{const t=T(e,"lab");let r=Je(e)||"lab";return t[0]=ue(t[0])+"%",t[1]=ue(t[1]),t[2]=ue(t[2]),r==="laba"||t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(" ")})`},ul=(...e)=>{const t=T(e,"lch");let r=Je(e)||"lab";return t[0]=ue(t[0])+"%",t[1]=ue(t[1]),t[2]=isNaN(t[2])?"none":ue(t[2])+"deg",r==="lcha"||t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(" ")})`},fl=(...e)=>{const t=T(e,"lab");return t[0]=ue(t[0]*100)+"%",t[1]=Tn(t[1]),t[2]=Tn(t[2]),t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(" ")})`},oc=(...e)=>{const[t,r,n,...o]=T(e,"rgb"),[a,s,c]=Vn(t,r,n),[i,u,l]=ja(a,s,c);return[i,u,l,...o.length>0&&o[0]<1?[o[0]]:[]]},ll=(...e)=>{const t=T(e,"lch");return t[0]=ue(t[0]*100)+"%",t[1]=Tn(t[1]),t[2]=isNaN(t[2])?"none":ue(t[2])+"deg",t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(" ")})`},{round:Un}=Math,hl=(...e)=>{const t=T(e,"rgba");let r=Je(e)||"rgb";if(r.substr(0,3)==="hsl")return cl(Ga(t),r);if(r.substr(0,3)==="lab"){const n=dt();xe("d50");const o=il(Bn(t),r);return xe(n),o}if(r.substr(0,3)==="lch"){const n=dt();xe("d50");const o=ul(Fn(t),r);return xe(n),o}return r.substr(0,5)==="oklab"?fl(Vn(t)):r.substr(0,5)==="oklch"?ll(oc(t)):(t[0]=Un(t[0]),t[1]=Un(t[1]),t[2]=Un(t[2]),(r==="rgba"||t.length>3&&t[3]<1)&&(t[3]="/ "+(t.length>3?t[3]:1),r="rgba"),`${r.substr(0,3)}(${t.slice(0,r==="rgb"?3:4).join(" ")})`)},sc=(...e)=>{e=T(e,"lch");const[t,r,n,...o]=e,[a,s,c]=Pa(t,r,n),[i,u,l]=Dn(a,s,c);return[i,u,l,...o.length>0&&o[0]<1?[o[0]]:[]]},He=/((?:-?\d+)|(?:-?\d+(?:\.\d+)?)%|none)/.source,ge=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%?)|none)/.source,It=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%)|none)/.source,fe=/\s*/.source,rt=/\s+/.source,Qn=/\s*,\s*/.source,zt=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?)|none)/.source,nt=/\s*(?:\/\s*((?:[01]|[01]?\.\d+)|\d+(?:\.\d+)?%))?/.source,ac=new RegExp("^rgba?\\("+fe+[He,He,He].join(rt)+nt+"\\)$"),cc=new RegExp("^rgb\\("+fe+[He,He,He].join(Qn)+fe+"\\)$"),ic=new RegExp("^rgba\\("+fe+[He,He,He,ge].join(Qn)+fe+"\\)$"),uc=new RegExp("^hsla?\\("+fe+[zt,It,It].join(rt)+nt+"\\)$"),fc=new RegExp("^hsl?\\("+fe+[zt,It,It].join(Qn)+fe+"\\)$"),lc=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,hc=new RegExp("^lab\\("+fe+[ge,ge,ge].join(rt)+nt+"\\)$"),dc=new RegExp("^lch\\("+fe+[ge,ge,zt].join(rt)+nt+"\\)$"),bc=new RegExp("^oklab\\("+fe+[ge,ge,ge].join(rt)+nt+"\\)$"),pc=new RegExp("^oklch\\("+fe+[ge,ge,zt].join(rt)+nt+"\\)$"),{round:mc}=Math,ot=e=>e.map((t,r)=>r<=2?Be(mc(t),0,255):t),J=(e,t=0,r=100,n=!1)=>(typeof e=="string"&&e.endsWith("%")&&(e=parseFloat(e.substring(0,e.length-1))/100,n?e=t+(e+1)*.5*(r-t):e=t+e*(r-t)),+e),oe=(e,t)=>e==="none"?t:e,eo=e=>{if(e=e.toLowerCase().trim(),e==="transparent")return[0,0,0,0];let t;if(E.format.named)try{return E.format.named(e)}catch{}if((t=e.match(ac))||(t=e.match(cc))){let r=t.slice(1,4);for(let o=0;o<3;o++)r[o]=+J(oe(r[o],0),0,255);r=ot(r);const n=t[4]!==void 0?+J(t[4],0,1):1;return r[3]=n,r}if(t=e.match(ic)){const r=t.slice(1,5);for(let n=0;n<4;n++)r[n]=+J(r[n],0,255);return r}if((t=e.match(uc))||(t=e.match(fc))){const r=t.slice(1,4);r[0]=+oe(r[0].replace("deg",""),0),r[1]=+J(oe(r[1],0),0,100)*.01,r[2]=+J(oe(r[2],0),0,100)*.01;const n=ot(Kn(r)),o=t[4]!==void 0?+J(t[4],0,1):1;return n[3]=o,n}if(t=e.match(lc)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=Kn(r);for(let o=0;o<3;o++)n[o]=mc(n[o]);return n[3]=+t[4],n}if(t=e.match(hc)){const r=t.slice(1,4);r[0]=J(oe(r[0],0),0,100),r[1]=J(oe(r[1],0),-125,125,!0),r[2]=J(oe(r[2],0),-125,125,!0);const n=dt();xe("d50");const o=ot(Pn(r));xe(n);const a=t[4]!==void 0?+J(t[4],0,1):1;return o[3]=a,o}if(t=e.match(dc)){const r=t.slice(1,4);r[0]=J(r[0],0,100),r[1]=J(oe(r[1],0),0,150,!1),r[2]=+oe(r[2].replace("deg",""),0);const n=dt();xe("d50");const o=ot(zn(r));xe(n);const a=t[4]!==void 0?+J(t[4],0,1):1;return o[3]=a,o}if(t=e.match(bc)){const r=t.slice(1,4);r[0]=J(oe(r[0],0),0,1),r[1]=J(oe(r[1],0),-.4,.4,!0),r[2]=J(oe(r[2],0),-.4,.4,!0);const n=ot(Dn(r)),o=t[4]!==void 0?+J(t[4],0,1):1;return n[3]=o,n}if(t=e.match(pc)){const r=t.slice(1,4);r[0]=J(oe(r[0],0),0,1),r[1]=J(oe(r[1],0),0,.4,!1),r[2]=+oe(r[2].replace("deg",""),0);const n=ot(sc(r)),o=t[4]!==void 0?+J(t[4],0,1):1;return n[3]=o,n}};eo.test=e=>ac.test(e)||uc.test(e)||hc.test(e)||dc.test(e)||bc.test(e)||pc.test(e)||cc.test(e)||ic.test(e)||fc.test(e)||lc.test(e)||e==="transparent",k.prototype.css=function(e){return hl(this._rgb,e)};const dl=(...e)=>new k(...e,"css");G.css=dl,E.format.css=eo,E.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&B(e)==="string"&&eo.test(e))return"css"}}),E.format.gl=(...e)=>{const t=T(e,"rgba");return t[0]*=255,t[1]*=255,t[2]*=255,t};const bl=(...e)=>new k(...e,"gl");G.gl=bl,k.prototype.gl=function(){const e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},k.prototype.hex=function(e){return Ea(this._rgb,e)};const pl=(...e)=>new k(...e,"hex");G.hex=pl,E.format.hex=La,E.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&B(e)==="string"&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return"hex"}});const{log:Ft}=Math,gc=e=>{const t=e/100;let r,n,o;return t<66?(r=255,n=t<6?0:-155.25485562709179-.44596950469579133*(n=t-2)+104.49216199393888*Ft(n),o=t<20?0:-254.76935184120902+.8274096064007395*(o=t-10)+115.67994401066147*Ft(o)):(r=351.97690566805693+.114206453784165*(r=t-55)-40.25366309332127*Ft(r),n=325.4494125711974+.07943456536662342*(n=t-50)-28.0852963507957*Ft(n),o=255),[r,n,o,1]},{round:ml}=Math,gl=(...e)=>{const t=T(e,"rgb"),r=t[0],n=t[2];let o=1e3,a=4e4;const s=.4;let c;for(;a-o>s;){c=(a+o)*.5;const i=gc(c);i[2]/i[0]>=n/r?a=c:o=c}return ml(c)};k.prototype.temp=k.prototype.kelvin=k.prototype.temperature=function(){return gl(this._rgb)};const to=(...e)=>new k(...e,"temp");Object.assign(G,{temp:to,kelvin:to,temperature:to}),E.format.temp=E.format.kelvin=E.format.temperature=gc,k.prototype.oklch=function(){return oc(this._rgb)},Object.assign(G,{oklch:(...e)=>new k(...e,"oklch")}),E.format.oklch=sc,E.autodetect.push({p:2,test:(...e)=>{if(e=T(e,"oklch"),B(e)==="array"&&e.length===3)return"oklch"}}),Object.assign(G,{analyze:Ka,average:wf,bezier:Hf,blend:me,brewer:ol,Color:k,colors:We,contrast:Vf,contrastAPCA:Jf,cubehelix:Bf,deltaE:el,distance:tl,input:E,interpolate:Ue,limits:Da,mix:Ue,random:Ff,scale:jt,scales:nl,valid:rl});function vl(e){return+`${Math.ceil(`${e}e+2`)}e-2`}const vc=e=>{const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},_c=(e,t,r)=>{const n=e/255,o=t/255,a=r/255,s=Math.min(n,o,a),c=Math.max(n,o,a),i=c-s;let u=0,l=0,f=0;return i===0?u=0:c===n?u=(o-a)/i%6:c===o?u=(a-n)/i+2:u=(n-o)/i+4,u=Math.round(u*60),u<0&&(u+=360),f=(c+s)/2,l=i===0?0:i/(1-Math.abs(2*f-1)),l=+(l*100).toFixed(1),f=+(f*100).toFixed(1),[u,l,Math.round(f)]},_l=(e,t,r,n)=>{const o=r/100,a=t*Math.min(o,1-o)/100,s=d=>{const b=(d+e/30)%12,_=o-a*Math.max(Math.min(b-3,9-b,1),-1);return Math.round(255*_).toString(16).padStart(2,"0").toUpperCase()},c=s(0),i=s(8),u=s(4),f=((d,b,_)=>Math.min(Math.max(d,b),_))(n,0,1),h=Math.round(f*255).toString(16).padStart(2,"0").toUpperCase();return`#${c}${i}${u}${h}`},yl=(e,t,r=1)=>{const n=vc(e),o=vc(t==="white"?"#FFFFFF":t==="black"?"#000000":t),a=n.map((u,l)=>[(u-o[l])/(255-o[l]),(u-o[l])/(0-o[l])]),s=vl(Math.max(...a.flat().filter(u=>/^-?\d+\.?\d*$/.test(u)))),c=n.map((u,l)=>Math.round((u-o[l]+o[l]*s)/s));if(c.includes(Number.NaN)){const u=_c(n[0],n[1],n[2]);return{h:u[0],s:Math.round(u[1]*r),l:u[2],a:1}}const i=_c(c[0],c[1],c[2]);return{h:i[0],s:Math.round(i[1]*r),l:i[2],a:s}},ro={backgroundColor:"gray",colorSpace:"OKLCH",colorSmoothing:!1,formula:"wcag2",output:"HEX",colors:{gray:[K(215,20,90),K(215,8,50),K(215,6,25)],red:[K(358,100,58),K(350,100,30)],orange:[K(32,100,48),K(12,100,30)],yellow:[K(50,100,50),K(25,100,20)],lime:[K(100,68,50),K(115,86,25)],green:[K(163,87,42),K(168,100,25)],cyan:[K(185,80,45),K(200,98,35)],blue:[K(212,98,46),K(222,95,25)],purple:[K(258,94,64),K(265,100,35)],fuchsia:[K(295,56,50),K(285,80,25)],pink:[K(334,90,50),K(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function K(e,t,r){return G.hsl(e,t/100,r/100).hex()}function wl(e,t){const r=e.colorSpace,n=e.colorSmoothing,o=e.themes[t].ratios,a=new qa({name:"gray",colorKeys:e.colors.gray,colorspace:r,ratios:o,smooth:n}),s=new ae({name:"blue",colorKeys:e.colors.blue,colorspace:r,ratios:o,smooth:n}),c=new ae({name:"cyan",colorKeys:e.colors.cyan,colorspace:r,ratios:o,smooth:n}),i=new ae({name:"fuchsia",colorKeys:e.colors.fuchsia,colorspace:r,ratios:o,smooth:n}),u=new ae({name:"green",colorKeys:e.colors.green,colorspace:r,ratios:o,smooth:n}),l=new ae({name:"lime",colorKeys:e.colors.lime,colorspace:r,ratios:o,smooth:n}),f=new ae({name:"orange",colorKeys:e.colors.orange,colorspace:r,ratios:o,smooth:n}),h=new ae({name:"pink",colorKeys:e.colors.pink,colorspace:r,ratios:o,smooth:n}),d=new ae({name:"purple",colorKeys:e.colors.purple,colorspace:r,ratios:o,smooth:n}),b=new ae({name:"red",colorKeys:e.colors.red,colorspace:r,ratios:o,smooth:n}),_=new ae({name:"yellow",colorKeys:e.colors.yellow,colorspace:r,ratios:o,smooth:n}),g={gray:a,red:b,orange:f,yellow:_,lime:l,green:u,cyan:c,blue:s,purple:d,fuchsia:i,pink:h};return e.colors.custom&&(g.custom=new ae({name:"custom",colorKeys:e.colors.custom,colorspace:r,ratios:o,smooth:n})),new wu({colors:Object.values(g),backgroundColor:g[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function yc(e){const t={};for(const r of Object.keys(e.themes))t[r]=wl(e,r);return t}function kl(e){ro.colors.custom=[e];const t=yc(ro);return Object.fromEntries(Object.entries(t).map(([r,n])=>{const o=n.find(s=>s&&s.name==="custom"),a=Object.fromEntries(o.values.map(({name:s,value:c})=>[s,c]));for(const[s,c]of Object.entries(a)){const i=yl(c,n[0].background);a[`alpha${s.charAt(0).toUpperCase()+s.slice(1)}`]=_l(i.h,i.s,i.l,i.a)}return[r,a]}))}return Fe.generateCustomColors=kl,Fe.generateThemesJson=yc,Fe.hslToHex=K,Fe.leonardoConfig=ro,Object.defineProperty(Fe,Symbol.toStringTag,{value:"Module"}),Fe})({}); diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt index a8ae1cf8f4..2f634b529e 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt @@ -1,12 +1,10 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. */ - /** * !!! WARNING !!! * @@ -14,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated @@ -185,6 +181,9 @@ object CompoundIcons { @Composable fun ErrorSolid(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_error_solid) } + @Composable fun ExitFullScreen(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_exit_full_screen) + } @Composable fun Expand(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_expand) } @@ -218,6 +217,9 @@ object CompoundIcons { @Composable fun Forward(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_forward) } + @Composable fun FullScreen(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_full_screen) + } @Composable fun Grid(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_grid) } @@ -296,6 +298,9 @@ object CompoundIcons { @Composable fun Leave(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_leave) } + @Composable fun LeftPanelClose(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_left_panel_close) + } @Composable fun Link(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_link) } @@ -503,6 +508,12 @@ object CompoundIcons { @Composable fun SignOut(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_sign_out) } + @Composable fun Space(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_space) + } + @Composable fun SpaceSolid(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_space_solid) + } @Composable fun Spinner(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_spinner) } @@ -620,12 +631,6 @@ object CompoundIcons { @Composable fun Windows(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_windows) } - @Composable fun Workspace(): ImageVector { - return ImageVector.vectorResource(R.drawable.ic_compound_workspace) - } - @Composable fun WorkspaceSolid(): ImageVector { - return ImageVector.vectorResource(R.drawable.ic_compound_workspace_solid) - } val all @Composable get() = persistentListOf( Admin(), @@ -681,6 +686,7 @@ object CompoundIcons { EndCall(), Error(), ErrorSolid(), + ExitFullScreen(), Expand(), Explore(), ExportArchive(), @@ -692,6 +698,7 @@ object CompoundIcons { Files(), Filter(), Forward(), + FullScreen(), Grid(), Group(), Guest(), @@ -718,6 +725,7 @@ object CompoundIcons { Keyboard(), Labs(), Leave(), + LeftPanelClose(), Link(), Linux(), ListBulleted(), @@ -787,6 +795,8 @@ object CompoundIcons { Shield(), Sidebar(), SignOut(), + Space(), + SpaceSolid(), Spinner(), Spotlight(), SpotlightView(), @@ -826,8 +836,6 @@ object CompoundIcons { Warning(), WebBrowser(), Windows(), - Workspace(), - WorkspaceSolid(), ) val allResIds get() = persistentListOf( @@ -884,6 +892,7 @@ object CompoundIcons { R.drawable.ic_compound_end_call, R.drawable.ic_compound_error, R.drawable.ic_compound_error_solid, + R.drawable.ic_compound_exit_full_screen, R.drawable.ic_compound_expand, R.drawable.ic_compound_explore, R.drawable.ic_compound_export_archive, @@ -895,6 +904,7 @@ object CompoundIcons { R.drawable.ic_compound_files, R.drawable.ic_compound_filter, R.drawable.ic_compound_forward, + R.drawable.ic_compound_full_screen, R.drawable.ic_compound_grid, R.drawable.ic_compound_group, R.drawable.ic_compound_guest, @@ -921,6 +931,7 @@ object CompoundIcons { R.drawable.ic_compound_keyboard, R.drawable.ic_compound_labs, R.drawable.ic_compound_leave, + R.drawable.ic_compound_left_panel_close, R.drawable.ic_compound_link, R.drawable.ic_compound_linux, R.drawable.ic_compound_list_bulleted, @@ -990,6 +1001,8 @@ object CompoundIcons { R.drawable.ic_compound_shield, R.drawable.ic_compound_sidebar, R.drawable.ic_compound_sign_out, + R.drawable.ic_compound_space, + R.drawable.ic_compound_space_solid, R.drawable.ic_compound_spinner, R.drawable.ic_compound_spotlight, R.drawable.ic_compound_spotlight_view, @@ -1029,7 +1042,5 @@ object CompoundIcons { R.drawable.ic_compound_warning, R.drawable.ic_compound_web_browser, R.drawable.ic_compound_windows, - R.drawable.ic_compound_workspace, - R.drawable.ic_compound_workspace_solid, ) } diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt index fe04e212cc..6136b04d4b 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt @@ -1,19 +1,10 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. */ - -@file:Suppress("all") -package io.element.android.compound.tokens.generated - -import androidx.compose.runtime.Immutable -import androidx.compose.ui.graphics.Color - - /** * !!! WARNING !!! * @@ -21,12 +12,14 @@ import androidx.compose.ui.graphics.Color * DO NOT EDIT MANUALLY. */ +@file:Suppress("all") +package io.element.android.compound.tokens.generated - +import androidx.compose.ui.graphics.Color /** - * This class holds all the semantic tokens of the Compound theme. - */ + * This class holds all the semantic tokens of the Compound theme. + */ data class SemanticColors( /** Background colour for accent or brand actions. State: Hover */ val bgAccentHovered: Color, @@ -50,17 +43,21 @@ data class SemanticColors( val bgActionSecondaryPressed: Color, /** Background colour for secondary actions. State: Rest. */ val bgActionSecondaryRest: Color, + /** Background colour for tertiary actions. State: Hover */ + val bgActionTertiaryHovered: Color, + /** Background colour for tertiary actions. State: Rest */ + val bgActionTertiaryRest: Color, + /** Background colour for tertiary actions. State: Selected */ + val bgActionTertiarySelected: Color, /** Badge accent background colour */ val bgBadgeAccent: Color, /** Badge default background colour */ val bgBadgeDefault: Color, /** Badge info background colour */ val bgBadgeInfo: Color, - /** Default global background for the user interface. -Elevation: Default (Level 0) */ + /** Default global background for the user interface. Elevation: Default (Level 0) */ val bgCanvasDefault: Color, - /** Default global background for the user interface. -Elevation: Level 1. */ + /** Default global background for the user interface. Elevation: Level 1. */ val bgCanvasDefaultLevel1: Color, /** Default background for disabled elements. There's no minimum contrast requirement. */ val bgCanvasDisabled: Color, @@ -86,14 +83,11 @@ Elevation: Level 1. */ val bgDecorative6: Color, /** Subtle background colour for informational elements. State: Rest. */ val bgInfoSubtle: Color, - /** Medium contrast surfaces. -Elevation: Default (Level 2). */ + /** Medium contrast surfaces. Elevation: Default (Level 2). */ val bgSubtlePrimary: Color, - /** Low contrast surfaces. -Elevation: Default (Level 1). */ + /** Low contrast surfaces. Elevation: Default (Level 1). */ val bgSubtleSecondary: Color, - /** Lower contrast surfaces. -Elevation: Level 0. */ + /** Lower contrast surfaces. Elevation: Level 0. */ val bgSubtleSecondaryLevel0: Color, /** Subtle background colour for success state elements. State: Rest. */ val bgSuccessSubtle: Color, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt index 6cbfd5f1fc..60afe79ae2 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated @@ -37,9 +34,12 @@ val compoundColorsDark = SemanticColors( bgActionSecondaryHovered = DarkColorTokens.colorAlphaGray200, bgActionSecondaryPressed = DarkColorTokens.colorAlphaGray300, bgActionSecondaryRest = DarkColorTokens.colorThemeBg, - bgBadgeAccent = DarkColorTokens.colorAlphaGreen300, - bgBadgeDefault = DarkColorTokens.colorAlphaGray300, - bgBadgeInfo = DarkColorTokens.colorAlphaBlue300, + bgActionTertiaryHovered = DarkColorTokens.colorGray300, + bgActionTertiaryRest = DarkColorTokens.colorThemeBg, + bgActionTertiarySelected = DarkColorTokens.colorGray400, + bgBadgeAccent = DarkColorTokens.colorAlphaGreen500, + bgBadgeDefault = DarkColorTokens.colorAlphaGray500, + bgBadgeInfo = DarkColorTokens.colorAlphaBlue500, bgCanvasDefault = DarkColorTokens.colorThemeBg, bgCanvasDefaultLevel1 = DarkColorTokens.colorGray300, bgCanvasDisabled = DarkColorTokens.colorGray200, @@ -89,7 +89,7 @@ val compoundColorsDark = SemanticColors( iconAccentTertiary = DarkColorTokens.colorGreen800, iconCriticalPrimary = DarkColorTokens.colorRed900, iconDisabled = DarkColorTokens.colorGray700, - iconInfoPrimary = DarkColorTokens.colorBlue900, + iconInfoPrimary = DarkColorTokens.colorBlue1100, iconOnSolidPrimary = DarkColorTokens.colorThemeBg, iconPrimary = DarkColorTokens.colorGray1400, iconPrimaryAlpha = DarkColorTokens.colorAlphaGray1400, @@ -112,8 +112,8 @@ val compoundColorsDark = SemanticColors( textDecorative5 = DarkColorTokens.colorPink1100, textDecorative6 = DarkColorTokens.colorOrange1100, textDisabled = DarkColorTokens.colorGray800, - textInfoPrimary = DarkColorTokens.colorBlue900, - textLinkExternal = DarkColorTokens.colorBlue900, + textInfoPrimary = DarkColorTokens.colorBlue1100, + textLinkExternal = DarkColorTokens.colorBlue1100, textOnSolidPrimary = DarkColorTokens.colorThemeBg, textPrimary = DarkColorTokens.colorGray1400, textSecondary = DarkColorTokens.colorGray900, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt index 94bcdabeae..c718caeeeb 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated @@ -37,9 +34,12 @@ val compoundColorsHcDark = SemanticColors( bgActionSecondaryHovered = DarkHcColorTokens.colorAlphaGray200, bgActionSecondaryPressed = DarkHcColorTokens.colorAlphaGray300, bgActionSecondaryRest = DarkHcColorTokens.colorThemeBg, - bgBadgeAccent = DarkHcColorTokens.colorAlphaGreen300, - bgBadgeDefault = DarkHcColorTokens.colorAlphaGray300, - bgBadgeInfo = DarkHcColorTokens.colorAlphaBlue300, + bgActionTertiaryHovered = DarkHcColorTokens.colorGray300, + bgActionTertiaryRest = DarkHcColorTokens.colorThemeBg, + bgActionTertiarySelected = DarkHcColorTokens.colorGray400, + bgBadgeAccent = DarkHcColorTokens.colorAlphaGreen500, + bgBadgeDefault = DarkHcColorTokens.colorAlphaGray500, + bgBadgeInfo = DarkHcColorTokens.colorAlphaBlue500, bgCanvasDefault = DarkHcColorTokens.colorThemeBg, bgCanvasDefaultLevel1 = DarkHcColorTokens.colorGray300, bgCanvasDisabled = DarkHcColorTokens.colorGray200, @@ -89,7 +89,7 @@ val compoundColorsHcDark = SemanticColors( iconAccentTertiary = DarkHcColorTokens.colorGreen800, iconCriticalPrimary = DarkHcColorTokens.colorRed900, iconDisabled = DarkHcColorTokens.colorGray700, - iconInfoPrimary = DarkHcColorTokens.colorBlue900, + iconInfoPrimary = DarkHcColorTokens.colorBlue1100, iconOnSolidPrimary = DarkHcColorTokens.colorThemeBg, iconPrimary = DarkHcColorTokens.colorGray1400, iconPrimaryAlpha = DarkHcColorTokens.colorAlphaGray1400, @@ -112,8 +112,8 @@ val compoundColorsHcDark = SemanticColors( textDecorative5 = DarkHcColorTokens.colorPink1100, textDecorative6 = DarkHcColorTokens.colorOrange1100, textDisabled = DarkHcColorTokens.colorGray800, - textInfoPrimary = DarkHcColorTokens.colorBlue900, - textLinkExternal = DarkHcColorTokens.colorBlue900, + textInfoPrimary = DarkHcColorTokens.colorBlue1100, + textLinkExternal = DarkHcColorTokens.colorBlue1100, textOnSolidPrimary = DarkHcColorTokens.colorThemeBg, textPrimary = DarkHcColorTokens.colorGray1400, textSecondary = DarkHcColorTokens.colorGray900, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt index cc779758df..377997ec79 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated @@ -37,9 +34,12 @@ val compoundColorsLight = SemanticColors( bgActionSecondaryHovered = LightColorTokens.colorAlphaGray200, bgActionSecondaryPressed = LightColorTokens.colorAlphaGray300, bgActionSecondaryRest = LightColorTokens.colorThemeBg, - bgBadgeAccent = LightColorTokens.colorAlphaGreen300, - bgBadgeDefault = LightColorTokens.colorAlphaGray300, - bgBadgeInfo = LightColorTokens.colorAlphaBlue300, + bgActionTertiaryHovered = LightColorTokens.colorGray300, + bgActionTertiaryRest = LightColorTokens.colorThemeBg, + bgActionTertiarySelected = LightColorTokens.colorGray400, + bgBadgeAccent = LightColorTokens.colorAlphaGreen400, + bgBadgeDefault = LightColorTokens.colorAlphaGray400, + bgBadgeInfo = LightColorTokens.colorAlphaBlue400, bgCanvasDefault = LightColorTokens.colorThemeBg, bgCanvasDefaultLevel1 = LightColorTokens.colorThemeBg, bgCanvasDisabled = LightColorTokens.colorGray200, @@ -89,7 +89,7 @@ val compoundColorsLight = SemanticColors( iconAccentTertiary = LightColorTokens.colorGreen800, iconCriticalPrimary = LightColorTokens.colorRed900, iconDisabled = LightColorTokens.colorGray700, - iconInfoPrimary = LightColorTokens.colorBlue900, + iconInfoPrimary = LightColorTokens.colorBlue1100, iconOnSolidPrimary = LightColorTokens.colorThemeBg, iconPrimary = LightColorTokens.colorGray1400, iconPrimaryAlpha = LightColorTokens.colorAlphaGray1400, @@ -112,8 +112,8 @@ val compoundColorsLight = SemanticColors( textDecorative5 = LightColorTokens.colorPink1100, textDecorative6 = LightColorTokens.colorOrange1100, textDisabled = LightColorTokens.colorGray800, - textInfoPrimary = LightColorTokens.colorBlue900, - textLinkExternal = LightColorTokens.colorBlue900, + textInfoPrimary = LightColorTokens.colorBlue1100, + textLinkExternal = LightColorTokens.colorBlue1100, textOnSolidPrimary = LightColorTokens.colorThemeBg, textPrimary = LightColorTokens.colorGray1400, textSecondary = LightColorTokens.colorGray900, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt index 5956b80195..b32a0dd9f0 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated @@ -37,9 +34,12 @@ val compoundColorsHcLight = SemanticColors( bgActionSecondaryHovered = LightHcColorTokens.colorAlphaGray200, bgActionSecondaryPressed = LightHcColorTokens.colorAlphaGray300, bgActionSecondaryRest = LightHcColorTokens.colorThemeBg, - bgBadgeAccent = LightHcColorTokens.colorAlphaGreen300, - bgBadgeDefault = LightHcColorTokens.colorAlphaGray300, - bgBadgeInfo = LightHcColorTokens.colorAlphaBlue300, + bgActionTertiaryHovered = LightHcColorTokens.colorGray300, + bgActionTertiaryRest = LightHcColorTokens.colorThemeBg, + bgActionTertiarySelected = LightHcColorTokens.colorGray400, + bgBadgeAccent = LightHcColorTokens.colorAlphaGreen400, + bgBadgeDefault = LightHcColorTokens.colorAlphaGray400, + bgBadgeInfo = LightHcColorTokens.colorAlphaBlue400, bgCanvasDefault = LightHcColorTokens.colorThemeBg, bgCanvasDefaultLevel1 = LightHcColorTokens.colorThemeBg, bgCanvasDisabled = LightHcColorTokens.colorGray200, @@ -89,7 +89,7 @@ val compoundColorsHcLight = SemanticColors( iconAccentTertiary = LightHcColorTokens.colorGreen800, iconCriticalPrimary = LightHcColorTokens.colorRed900, iconDisabled = LightHcColorTokens.colorGray700, - iconInfoPrimary = LightHcColorTokens.colorBlue900, + iconInfoPrimary = LightHcColorTokens.colorBlue1100, iconOnSolidPrimary = LightHcColorTokens.colorThemeBg, iconPrimary = LightHcColorTokens.colorGray1400, iconPrimaryAlpha = LightHcColorTokens.colorAlphaGray1400, @@ -112,8 +112,8 @@ val compoundColorsHcLight = SemanticColors( textDecorative5 = LightHcColorTokens.colorPink1100, textDecorative6 = LightHcColorTokens.colorOrange1100, textDisabled = LightHcColorTokens.colorGray800, - textInfoPrimary = LightHcColorTokens.colorBlue900, - textLinkExternal = LightHcColorTokens.colorBlue900, + textInfoPrimary = LightHcColorTokens.colorBlue1100, + textLinkExternal = LightHcColorTokens.colorBlue1100, textOnSolidPrimary = LightHcColorTokens.colorThemeBg, textPrimary = LightHcColorTokens.colorGray1400, textSecondary = LightHcColorTokens.colorGray900, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/TypographyTokens.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/TypographyTokens.kt index 27ab3e918c..0f450776ef 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/TypographyTokens.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/TypographyTokens.kt @@ -1,12 +1,10 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. */ - /** * !!! WARNING !!! * @@ -14,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkColorTokens.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkColorTokens.kt index 10b31b5716..04dbf6b9f2 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkColorTokens.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkColorTokens.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated.internal diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkHcColorTokens.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkHcColorTokens.kt index fa55eaf64f..8b2c04a93a 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkHcColorTokens.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/DarkHcColorTokens.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated.internal diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightColorTokens.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightColorTokens.kt index dd42c82d59..c7561c7ce9 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightColorTokens.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightColorTokens.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated.internal diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightHcColorTokens.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightHcColorTokens.kt index 0a6801850d..40c91c5b53 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightHcColorTokens.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/internal/LightHcColorTokens.kt @@ -1,6 +1,5 @@ /* * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * Please see LICENSE files in the repository root for full details. @@ -13,8 +12,6 @@ * DO NOT EDIT MANUALLY. */ - - @file:Suppress("all") package io.element.android.compound.tokens.generated.internal diff --git a/libraries/compound/src/main/res/drawable/ic_compound_exit_full_screen.xml b/libraries/compound/src/main/res/drawable/ic_compound_exit_full_screen.xml new file mode 100644 index 0000000000..2b806f8992 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_exit_full_screen.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_full_screen.xml b/libraries/compound/src/main/res/drawable/ic_compound_full_screen.xml new file mode 100644 index 0000000000..8042ed32c9 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_full_screen.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_left_panel_close.xml b/libraries/compound/src/main/res/drawable/ic_compound_left_panel_close.xml new file mode 100644 index 0000000000..60e11c6f4f --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_left_panel_close.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_space.xml b/libraries/compound/src/main/res/drawable/ic_compound_space.xml new file mode 100644 index 0000000000..53a069c640 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_space.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_space_solid.xml b/libraries/compound/src/main/res/drawable/ic_compound_space_solid.xml new file mode 100644 index 0000000000..34730e87ff --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_space_solid.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_threads.xml b/libraries/compound/src/main/res/drawable/ic_compound_threads.xml index 4fa1e877d1..6d3fd0c853 100644 --- a/libraries/compound/src/main/res/drawable/ic_compound_threads.xml +++ b/libraries/compound/src/main/res/drawable/ic_compound_threads.xml @@ -4,10 +4,10 @@ android:autoMirrored="true" android:viewportWidth="24" android:viewportHeight="24"> - - + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_threads_solid.xml b/libraries/compound/src/main/res/drawable/ic_compound_threads_solid.xml index 4db292231d..b06b67c27e 100644 --- a/libraries/compound/src/main/res/drawable/ic_compound_threads_solid.xml +++ b/libraries/compound/src/main/res/drawable/ic_compound_threads_solid.xml @@ -4,7 +4,7 @@ android:autoMirrored="true" android:viewportWidth="24" android:viewportHeight="24"> - + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_workspace.xml b/libraries/compound/src/main/res/drawable/ic_compound_workspace.xml deleted file mode 100644 index e5629d881a..0000000000 --- a/libraries/compound/src/main/res/drawable/ic_compound_workspace.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/libraries/compound/src/main/res/drawable/ic_compound_workspace_solid.xml b/libraries/compound/src/main/res/drawable/ic_compound_workspace_solid.xml deleted file mode 100644 index 12c582ebb3..0000000000 --- a/libraries/compound/src/main/res/drawable/ic_compound_workspace_solid.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - From 4e043bfa406ca60406f3195c13a52a44197fbabb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 12 Dec 2025 12:21:41 +0100 Subject: [PATCH 57/64] Fix compilation issue. --- .../features/announcement/impl/spaces/SpaceAnnouncementView.kt | 2 +- .../element/android/features/home/impl/HomeNavigationBarItem.kt | 2 +- .../securityandprivacy/impl/root/SecurityAndPrivacyView.kt | 2 +- .../libraries/matrix/ui/components/SpaceHeaderRootView.kt | 2 +- .../android/libraries/matrix/ui/components/SpaceInfoRow.kt | 2 +- .../element/android/libraries/matrix/ui/model/SpaceExtension.kt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt index e0759bc490..3fe6ec4456 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt @@ -81,7 +81,7 @@ private fun SpaceAnnouncementHeader( showBetaLabel = true, subTitle = stringResource(id = R.string.screen_space_announcement_subtitle), iconStyle = BigIcon.Style.Default( - vectorIcon = CompoundIcons.WorkspaceSolid(), + vectorIcon = CompoundIcons.SpaceSolid(), usePrimaryTint = true, ), ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeNavigationBarItem.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeNavigationBarItem.kt index 6a4a5e1688..035e953b23 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeNavigationBarItem.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeNavigationBarItem.kt @@ -28,7 +28,7 @@ enum class HomeNavigationBarItem( isSelected: Boolean, ) = when (this) { Chats -> if (isSelected) CompoundIcons.ChatSolid() else CompoundIcons.Chat() - Spaces -> if (isSelected) CompoundIcons.WorkspaceSolid() else CompoundIcons.Workspace() + Spaces -> if (isSelected) CompoundIcons.SpaceSolid() else CompoundIcons.Space() } companion object { diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt index add719153a..125d84c84d 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt @@ -218,7 +218,7 @@ private fun RoomAccessSection( Text(text = stringResource(R.string.screen_security_and_privacy_room_access_space_members_option_unavailable_description)) }, trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.SpaceMember, enabled = false), - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Workspace())), + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Space())), enabled = false, ) } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderRootView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderRootView.kt index f80cf2d65c..1e8fb864a7 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderRootView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderRootView.kt @@ -42,7 +42,7 @@ fun SpaceHeaderRootView( verticalArrangement = Arrangement.spacedBy(16.dp) ) { BigIcon( - style = BigIcon.Style.Default(CompoundIcons.WorkspaceSolid()) + style = BigIcon.Style.Default(CompoundIcons.SpaceSolid()) ) Text( text = stringResource(CommonStrings.screen_space_list_title), diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceInfoRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceInfoRow.kt index 9709e0e3c6..052d9862a6 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceInfoRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceInfoRow.kt @@ -108,7 +108,7 @@ internal fun SpaceInfoRowPreview() = ElementPreview { SpaceInfoRow( leftText = "Element space", rightText = numberOfRooms(16), - iconVector = CompoundIcons.Workspace(), + iconVector = CompoundIcons.Space(), ) SpaceInfoRow( visibility = SpaceRoomVisibility.Private, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt index f9d4063601..195dfdb40e 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/SpaceExtension.kt @@ -32,7 +32,7 @@ val SpaceRoomVisibility.icon: ImageVector return when (this) { SpaceRoomVisibility.Private -> CompoundIcons.LockSolid() SpaceRoomVisibility.Public -> CompoundIcons.Public() - SpaceRoomVisibility.Restricted -> CompoundIcons.Workspace() + SpaceRoomVisibility.Restricted -> CompoundIcons.Space() } } From 23f3195b2a08b4359c35c526dc2e7d4a111aeeae Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 12 Dec 2025 11:36:01 +0000 Subject: [PATCH 58/64] Update screenshots --- libraries/compound/screenshots/Compound Icons - Dark.png | 4 ++-- libraries/compound/screenshots/Compound Icons - Light.png | 4 ++-- libraries/compound/screenshots/Compound Icons - Rtl.png | 4 ++-- .../screenshots/Compound Semantic Colors - Dark HC.png | 4 ++-- .../compound/screenshots/Compound Semantic Colors - Dark.png | 4 ++-- .../screenshots/Compound Semantic Colors - Light HC.png | 4 ++-- .../compound/screenshots/Compound Semantic Colors - Light.png | 4 ++-- .../compound/screenshots/Compound Vector Icons - Dark.png | 4 ++-- .../compound/screenshots/Compound Vector Icons - Light.png | 4 ++-- ...nnouncement.impl.spaces_SpaceAnnouncementView_Day_0_en.png | 4 ++-- ...ouncement.impl.spaces_SpaceAnnouncementView_Night_0_en.png | 4 ++-- ...crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png | 4 ++-- ...crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png | 3 --- ...ypto.historyvisible_HistoryVisibleStateView_Night_0_en.png | 4 ++-- ...ypto.historyvisible_HistoryVisibleStateView_Night_1_en.png | 3 --- ...historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png | 4 ++-- ...historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png | 3 --- ...storyvisible_MessagesViewWithHistoryVisible_Night_0_en.png | 4 ++-- ...storyvisible_MessagesViewWithHistoryVisible_Night_1_en.png | 3 --- ...ineItemTextViewWithLinkifiedUrlAndNestedParenthesis_en.png | 4 ++-- ...mponents.event_TimelineItemTextViewWithLinkifiedUrl_en.png | 4 ++-- ...es.impl.timeline.components_ThreadSummaryView_Day_0_en.png | 4 ++-- ....impl.timeline.components_ThreadSummaryView_Night_0_en.png | 2 +- ....components_TimelineItemEventRowDisambiguated_Day_0_en.png | 4 ++-- ...omponents_TimelineItemEventRowDisambiguated_Night_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_1_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_0_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_1_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_0_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_1_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_0_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_0_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_10_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_11_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_2_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_3_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_4_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_5_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_6_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_7_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_8_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_9_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_0_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_10_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_11_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_1_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_2_en.png | 2 +- ...ne.components_TimelineItemEventRowWithReply_Night_3_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_4_en.png | 2 +- ...ne.components_TimelineItemEventRowWithReply_Night_5_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_6_en.png | 2 +- ...ne.components_TimelineItemEventRowWithReply_Night_7_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_8_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_9_en.png | 4 ++-- ...ponents_TimelineItemEventRowWithThreadSummary_Day_0_en.png | 4 ++-- ...nents_TimelineItemEventRowWithThreadSummary_Night_0_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_11_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_11_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Day_0_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Day_1_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Night_0_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Night_1_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_0_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_10_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_11_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_12_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_13_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_14_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_15_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_16_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_17_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_18_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_19_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_1_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_2_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_3_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_4_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_5_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_6_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_7_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_8_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_9_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_0_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_10_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_11_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_12_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_13_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_14_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_15_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_16_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_17_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_18_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_19_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_1_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_2_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_3_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_4_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_5_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_6_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_7_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_8_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_9_en.png | 4 ++-- ...s.userprofile.shared_UserProfileHeaderSection_Day_0_en.png | 4 ++-- ...userprofile.shared_UserProfileHeaderSection_Night_0_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_2_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_2_en.png | 4 ++-- ...libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en.png | 4 ++-- ...braries.designsystem.atomic.atoms_BetaLabel_Night_0_en.png | 4 ++-- ...designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en.png | 4 ++-- ...signsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en.png | 4 ++-- ...ignsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en.png | 4 ++-- ...nsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en.png | 4 ++-- ...gnsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en.png | 4 ++-- ...system.atomic.atoms_MatrixBadgeAtomPositive_Night_0_en.png | 4 ++-- ...system.atomic.molecules_ComposerAlertMolecule_Day_3_en.png | 4 ++-- ...system.atomic.molecules_ComposerAlertMolecule_Day_4_en.png | 4 ++-- ...system.atomic.molecules_ComposerAlertMolecule_Day_5_en.png | 4 ++-- ...stem.atomic.molecules_ComposerAlertMolecule_Night_3_en.png | 4 ++-- ...stem.atomic.molecules_ComposerAlertMolecule_Night_4_en.png | 4 ++-- ...stem.atomic.molecules_ComposerAlertMolecule_Night_5_en.png | 4 ++-- ...mponents.preferences_PreferenceCategory_Preferences_en.png | 4 ++-- ...mponents.preferences_PreferenceCheckbox_Preferences_en.png | 4 ++-- ...mponents.preferences_PreferenceDropdown_Preferences_en.png | 4 ++-- ...nsystem.components.preferences_PreferencePage_Day_0_en.png | 4 ++-- ...ystem.components.preferences_PreferencePage_Night_0_en.png | 4 ++-- ...components.preferences_PreferenceSwitch_Preferences_en.png | 4 ++-- .../libraries.designsystem.components_Badge_Day_0_en.png | 4 ++-- .../libraries.designsystem.components_Badge_Night_0_en.png | 4 ++-- ...raries.designsystem.theme.components_AllIcons_Icons_en.png | 4 ++-- ...tcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png | 4 ++-- ...omposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png | 4 ++-- ...raries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png | 4 ++-- ...ries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png | 4 ++-- ...ies.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png | 4 ++-- ...s.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png | 4 ++-- ...xtcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png | 4 ++-- ...composer_TextComposerFormattingNotEncrypted_Night_0_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png | 4 ++-- ...s.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png | 4 ++-- ...s.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png | 4 ++-- ...textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png | 4 ++-- ...textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png | 4 ++-- ...s.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en.png | 4 ++-- ...textcomposer_TextComposerSimpleNotEncrypted_Night_0_en.png | 4 ++-- ...es.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en.png | 4 ++-- ....textcomposer_TextComposerVoiceNotEncrypted_Night_0_en.png | 4 ++-- 168 files changed, 324 insertions(+), 336 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png diff --git a/libraries/compound/screenshots/Compound Icons - Dark.png b/libraries/compound/screenshots/Compound Icons - Dark.png index 52e6ba23ab..d3fb6dc294 100644 --- a/libraries/compound/screenshots/Compound Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c0f668bcd8d511bc80daa1320bdcc1fe6a8f82cd53d91dbab9ffd0d09d72934 -size 210897 +oid sha256:fc758c149db501d0ac5eb235cca1d63b67230aae40356e7ccca4c9d481a9ce17 +size 216981 diff --git a/libraries/compound/screenshots/Compound Icons - Light.png b/libraries/compound/screenshots/Compound Icons - Light.png index 189864a54d..a6728d0947 100644 --- a/libraries/compound/screenshots/Compound Icons - Light.png +++ b/libraries/compound/screenshots/Compound Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85eb26db4406a921c45f143c8ccb59214b2b70cb19359fe9e7eeeecfb733ca74 -size 222592 +oid sha256:db230bfe3d51527959d2a4f7c64a8cc79209dcfb752f077f84c0f5058d94f0bd +size 228829 diff --git a/libraries/compound/screenshots/Compound Icons - Rtl.png b/libraries/compound/screenshots/Compound Icons - Rtl.png index aa1bdac4f5..c3f0b5fb8c 100644 --- a/libraries/compound/screenshots/Compound Icons - Rtl.png +++ b/libraries/compound/screenshots/Compound Icons - Rtl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9acd4fdec8deddbf723184ce5f373ed54e64a68d5b572419059e3feab3a508be -size 223915 +oid sha256:4c6cd3ad1978c6f4e07d62b1edd08c5f32b3c498934d25af43932c50ef309fe0 +size 230519 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png b/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png index 4890b91886..b66b386ed8 100644 --- a/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png +++ b/libraries/compound/screenshots/Compound Semantic Colors - Dark HC.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:578e9b5a38791e2686a7b9ba5c461eb1d1fb29dfbe950bf46c113ad75ceac175 -size 327758 +oid sha256:c846cd10b83361c368bdbb31ed6220cc22693c3cbf52791fb369841af1e9ea48 +size 327701 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Dark.png b/libraries/compound/screenshots/Compound Semantic Colors - Dark.png index 4cc125b4c8..35d684d39b 100644 --- a/libraries/compound/screenshots/Compound Semantic Colors - Dark.png +++ b/libraries/compound/screenshots/Compound Semantic Colors - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4cab40fc0506c8f2a2efafb1199e85f1da3ebacb49b176e9105e3f95175f85ee -size 325565 +oid sha256:05b35fedbd53dec2cc5c4c211a8db1a56055963de69425ddae2cab5aff7e3e75 +size 325750 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png b/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png index 5a8f5a6b32..9061d2b894 100644 --- a/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png +++ b/libraries/compound/screenshots/Compound Semantic Colors - Light HC.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:174f9d4ee70a29c0c8c2a01a15daeb14281530678ff7d7fb19a208bfd789533a -size 309210 +oid sha256:8d98e64eda5d6333067ccc599e99636f618331397207bb7534595e2756edb75e +size 309312 diff --git a/libraries/compound/screenshots/Compound Semantic Colors - Light.png b/libraries/compound/screenshots/Compound Semantic Colors - Light.png index f010626dda..83c00ab51c 100644 --- a/libraries/compound/screenshots/Compound Semantic Colors - Light.png +++ b/libraries/compound/screenshots/Compound Semantic Colors - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7598b98462c015f2bf74b3ea3ad95fc0220b2efb9bb81ac56025cf6a158e3f8a -size 308976 +oid sha256:5ccbf1234065b182939f001eb65eca0a62adae41a2d91ef0307d27b059407178 +size 309084 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Dark.png b/libraries/compound/screenshots/Compound Vector Icons - Dark.png index 30eac13a58..290f09480a 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f2584ffd8e3a4746937cdc3e0baf04a89839061f15d00342e6150c21bf13228 -size 83228 +oid sha256:1d4f46c82f1504a983885a7d177900cd6d6f7729dce6851520cd7e471870ad2d +size 84955 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Light.png b/libraries/compound/screenshots/Compound Vector Icons - Light.png index 41fac03927..01cee66ad7 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Light.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb1854bf504fcab7752c4d51f5fc6cae65511581fb64a1adcdcf6f912d4aa15a -size 89148 +oid sha256:e2c1a78a88fad99c1fd9bc29d802ee8c2bdefec89626cd700c73f4909738aeb5 +size 91022 diff --git a/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png index ec148b5c75..e68a69090d 100644 --- a/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48f54197f74cf0675e04a83efbb278728568024bcec38a8553b623cdba384e50 -size 60460 +oid sha256:8397ea9df5871ea2c71183f59030c73ef7ba102aa75e5609459bae06b662847a +size 60474 diff --git a/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png index 870bdf0bca..ff9a4d740e 100644 --- a/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2e2356a3f8521649d6ad2c10f654142f87141e3f747db5a6f6ba25483c8171a -size 59516 +oid sha256:87029fb2522ab31001a5b1efb12b8f99d0a5217d838d7531894875c44aaced76 +size 59531 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png index d19a140456..0e62152f25 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96bc0c555188cee4b3f3e3e0f28f944a4225e27b9a1069edf2b10a2993ee3080 -size 26078 +oid sha256:5503fe0529183e4235336b86b2566a7780c0acb42a0555259fdc5c2d83af923c +size 26362 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png deleted file mode 100644 index d19a140456..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96bc0c555188cee4b3f3e3e0f28f944a4225e27b9a1069edf2b10a2993ee3080 -size 26078 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png index d21a12dd64..cf08addacb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a103daf8447cb571a0c5010d062a7790aaa0f3dce30f052bf86884708f4881a5 -size 28769 +oid sha256:25f79679d8b15bbd4cd27b79aec1d5a33f7784d73a0b6fcb5d80a3da83b28188 +size 29073 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png deleted file mode 100644 index d21a12dd64..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a103daf8447cb571a0c5010d062a7790aaa0f3dce30f052bf86884708f4881a5 -size 28769 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png index 22d05e61fa..31ddd63f80 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9682cdd7e08e32591fa47f56da5e6ef4cc3a777700931c2c86e9b802a9cf25cb -size 67342 +oid sha256:3a591fbf79b2b97bec5028b4b32b4a28ded3023355dbb446be793cd59701c284 +size 67642 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png deleted file mode 100644 index 22d05e61fa..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9682cdd7e08e32591fa47f56da5e6ef4cc3a777700931c2c86e9b802a9cf25cb -size 67342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png index b2bb8ac3fc..3dd62262e8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d20c04c6385e675bd71d93d2d5d832509b1300a27708245755f263392b33bc8a -size 69457 +oid sha256:220888172844b7a99bed005197f78c6fe1658d8905de5e524d3e0c58b174c150 +size 69851 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png deleted file mode 100644 index b2bb8ac3fc..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d20c04c6385e675bd71d93d2d5d832509b1300a27708245755f263392b33bc8a -size 69457 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrlAndNestedParenthesis_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrlAndNestedParenthesis_en.png index 6bd15db678..12e583aac4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrlAndNestedParenthesis_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrlAndNestedParenthesis_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa94348d573952caea928cef169e6dab0b2e46c8d7328ffd31b385fbf575fd39 -size 20313 +oid sha256:82210d42de0cf0fd4fef8d23a3c3971b8778a916a2af27b3e8e3320de96d5c3f +size 20475 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrl_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrl_en.png index 551c04dedd..0b13dd05c6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrl_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemTextViewWithLinkifiedUrl_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6678b4bfada4177341a7af5a892726522b1771e7a13f421a74b33a474f7b0a8b -size 19552 +oid sha256:50f6dbb2770fc8184c9a410b6a3a1182f26e063075e66a657e81eba8496a3489 +size 19729 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png index 32733b09b6..8a2324db79 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cb3989055cf63e3ee14d8e2d8b2cdcd67b3af1addae78b38ab13ddcf93a232d -size 9740 +oid sha256:2ae7f9c33c329fad507868f5e36a122045fb79e401a2215b487bf3f41f8cc977 +size 9739 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png index 9b9901528b..120ca41bbc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e206a2485736baa2ac8c6dae6847ef381bfa1f36a5b7bda14a7f93a55069f41 +oid sha256:7a0e23b9af1963b9c500c39e6d5ac1fa72623db436c9e21596b69b4cae5dc6bb size 9666 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png index 4850eca991..fe900dffc8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e469e1d16e26b6615191bd26e1ada64c98292572b7d8ab98a423ec3ae355c16 -size 379478 +oid sha256:e516218540c579c2dd9b322b498afc502fd9473b087b416efa43dd8260d056bb +size 379469 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png index 05caec2562..f2ae031f5f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ac5f753b3d3973878b9244d3f59ee3171864506f8a8765a4caad5424512f5e1 -size 377817 +oid sha256:8cf6dd8fbd5f7c7cc66ed09fe29fb6760ba0c2a2d664b129dac9acb80e3c95d9 +size 377818 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png index 4dcd174908..ae5230de8f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0dfc5205d51fe54d92f1586da5b084789639908ffba9cab9f4a9a527441b4de2 -size 364950 +oid sha256:15ef0b45a784088e223a0c9996da6b6299277c02d7934f69bf1148f764390aa8 +size 364949 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png index 8128a86192..81056bda38 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ed58942c843877fbc757a37489fe538a504410382c87cde2bdf8f3b54d3b417 -size 370053 +oid sha256:5bbfe429c79f1a34534041928d5e87efb748d02e1000e759ce1a0ad58efb40db +size 370052 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png index a40fcca299..2cf4424886 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e866c721980fe3f6c3ffb740e6f2262f68c80a76f7f4ab648d54d0e81dc603a -size 363008 +oid sha256:a07e7bd9dd62fe64a558e583f3ad98980d09c7585509efa436e4df5a9d3dcadd +size 363006 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png index 22af9825a8..6aa48c10a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74eb06d02b477a325f50f1618ae549e43d2b72444072b28c0287bd551410e080 -size 368151 +oid sha256:c68ffdebaa08c9277eacad0a16eee158e72ae28d3ce14592174091068f0ea6ea +size 368149 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png index c125d9b881..cb11591308 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a3ac104355ef6ad83d6c4271fb1c666a4c625264144d8ebb577a625e0f5f730 -size 353133 +oid sha256:273d926ab913ac5e44ed986cad5484f14b6c78e3bab3ae6169e97521cc734eeb +size 353127 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png index 3a90e26ac1..b7c6d2ff79 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73cfddbb371d681801710788b443d6b3de733b026bc9421d994435e9191cc2e7 -size 363534 +oid sha256:a534bd9c790747f983831badb8dda126a776d9639ec7f9454e798e96d1be4954 +size 363533 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png index 8fcc1ba614..a1ea6130e0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52c4271018f6ef8dde2f4704c875b50b013c91e3fc9a6821bb22c1778a833ff0 -size 351724 +oid sha256:1848d32a74c570671557ac50dae5e43679a4f79ae20e69489a5140d5508f4ab1 +size 351731 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png index 0430452b23..a936428bd5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:651e870ef260bfce2671d8179d4c2711cde8216fd933df14d55b49b1338defac -size 361233 +oid sha256:5f0a52fb45860dd2ceef51a84a1b3ade90158f4ad9412c8ab5209e484d025022 +size 361217 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png index fbfc33a745..75dd71ad5e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed7ab7efe006792017dfebb212f4169afa51b121f0acc32f594cbf56fc13bf5b -size 369628 +oid sha256:cd9f85eb61c206e7237f148afdafce0df78246916bf1e149dc14cfa7dcf9ad75 +size 369622 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png index b07ca33c78..44b50ff770 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9ae07748ec931966b8be1aefd7dbecf533955d691dc5d2b75ead73b31ff0454 -size 354533 +oid sha256:523655ecb0dcc790c3f5488684f8818e66d67307c0fceb7321793ecbf8d6b5b1 +size 354543 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png index d3a1958dfe..dc49264f75 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:824bb76f7f23573a9bf429a7c46336a5066c9c80c39203be09de17036cf901a1 -size 367900 +oid sha256:06054cadaae544104b0a7ffe7c5c712a68dd1075044b6a6558b732465e74af69 +size 367897 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png index 6d69b0ec43..09d9ab87f2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:060e4a97bd87ff79d5464081684245d37af2733a1440b03f76ced429f0137d05 -size 345006 +oid sha256:ec07a302a034abc4058098981a884a2812b6fbaaefe43910f954efc2becab3fc +size 345007 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png index 54be2d70d9..577a6744e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eca32f762418e4b7e3828f5dd0cb839d7020d6cfab308b0727885195b00c3c01 -size 357521 +oid sha256:b6364afd08f2a1f744143bf8e1aa0a77585cfa8ff2c8b5b0a0eb2e01afbef0e3 +size 357517 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png index 5f3af564d5..d78ec33087 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed1e765f4ba4078e931572fc5df68655cdee951d021762ea41c4d6e867fc960b -size 356674 +oid sha256:af1605ff52a6a6e92154312b00706401889d478c41ebfc7aa75e680412b8f65c +size 356672 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png index 46926bcb25..14b4638e34 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80b986470b115a047156c2d63c026ed5f887cfa4af0488cbb477722a43b57980 -size 364488 +oid sha256:26cbb8ad35bb3746b931aabee1a568c37ec0f59052a36752af482149996fd207 +size 364483 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png index 255ea7812f..a58a3b697e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75c8fd9c2cb9fd654e9593d4763dc6d04184e1ea2f814e79fb6cbec7f231b47f -size 397016 +oid sha256:cac3aea0874bd1c8e3c26bbfe7e6353042d248533e630b69644a02261fb2d7b3 +size 397020 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png index f88757a9c2..ef4fe7217f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dce75ec016354e7e3243fde61f1bdd3520bad5a84bca84a160ec0f4dea857dfc -size 355897 +oid sha256:a63ce064aad609786d444e55379fdab29253310b77012387e168ddfdaa583f55 +size 355891 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png index a2c24e47cd..8a0c80710d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11ae7ffda287e87638c639f6357615e25978d663a5c6e66e699323f352a003ec -size 357733 +oid sha256:9b7bd7fa60c549e0f03d73cd67db352285ce02d050d465505ecee6b3dc535e96 +size 357735 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png index 1283ec7e67..3fc491378c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62ca94e55d4907b37afc1865955f4cab2f3e595827b361bb0612ae020ef3380e -size 364820 +oid sha256:fa0b9eea253b1eb6c855dedc6dc444b482254e4b4d96a895d3e82ee10a9a38c1 +size 364811 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png index 2b66e7a119..bb6eb5eed9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04293e07b3ba253facde1fd495fb1fc5700d9fa91d55e6fc26407bbe80710c9d -size 355148 +oid sha256:e7d978590295705191b23fef236aced625dc85165c23ae703bb9faa7ce2efa6b +size 355139 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png index 23c44e4e2b..e0be8f49d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e497584801b9aedaf49483e718baf913d9de4784a7785d4b1dbc931af15ca2c5 -size 367618 +oid sha256:9d0997895e84028a7433a3e49503e1bb79f675fa9ba5d80735fdff0a1a4a126d +size 367615 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png index 5502b438e6..7e2202e70d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c07b6043cac6215e0f1adb1f341fab2657f5989fc6f775c44103d767cdaa654 -size 352618 +oid sha256:691b5b8844c37c0a70bff7e2edb489c6444e6a3dcdbcd1fb1364d3f429b0ec8a +size 352620 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png index a333a03c2f..7c53094f41 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b26ac3162c11d5ec150548b8e57c60c8be81da5e3360b06fce254a41d6bd46f -size 366046 +oid sha256:a0138339ed9132c2ea93f27bcc163f838e24a94ab4e731d6a7baa3fe1e2c7e3c +size 366045 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png index 7e86609428..60afd00b14 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7bf88755dc4eb1e9750f9556fce89ec3be77a51f608734e5ea535012221632c -size 342592 +oid sha256:7876a6125d45647beb8cc5b5b125556b16560dab6599ed4eba9fd746fd4b17f2 +size 342595 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png index 74f6213244..5cb708dad7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9896599ce680aedd483223ce1a83736545b792e61bdf2b8d231eaf76cb3f23d5 +oid sha256:2eb5334bd16dab1bd9ba111967aac6e29fd6eb3d325fdec6f6ff6b7b3dceaf06 size 355727 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png index 1bd2b6d19e..cf56ea41d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ab6a4c7fdc6c3701c0a2fbd1ff2ac5b023d904bcd61604be63fc74db8809c74 -size 354859 +oid sha256:2f4fbc0a4be27e1f6b42f0f7d447e95662a9acffe079b5ca27b8f38971c67b7d +size 354860 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png index 1b17e5f9a2..650725b8a5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef2b2583e788c1d802d81ead131f67f17d83b5a7e8f8d44f7c5bc9a042b76722 +oid sha256:ce5ef1cdb3b466af1b445020cdf6b5037c0222430a37a6cf2bab42738c75dd83 size 362581 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png index 8743d61fd4..1db9c6d9e9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cbbaadca7fb46fa4f6483eb9760fab96611a2115f98ea6d9f6f62411fc5b4fb -size 395148 +oid sha256:e801e2540bbcc28afccfcc9d57fbc6945b0b1a069dc7b7c9f31790134dc498ac +size 395151 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png index e4a4be9cd6..57b7b4070d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45d46f34b9fb4fb8260bf2154b8bee5112b94524800870ffed2488252ea0ecf9 +oid sha256:284c445b4cf37c26c9dab6b9a00d23fc1fcde5eca3b02bf7149ef50c77f07980 size 353920 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png index 3485c722e6..a3f63b3e46 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:091ea9b69b86dbd001ef78d018fc4f273db1323b999aa3c591c38f8d214812ad -size 356033 +oid sha256:22df78bb78f17d4c87ba31db8d335f6428d85c5ff80c9bd563f5dd6a6f1b762e +size 356037 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png index 342b7415f7..c1c1318e73 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66a0b023dfad07f7026219325d966375bf3f25fa0b3f8192f101828e8b4df2bd -size 363005 +oid sha256:2791382f305e4acda3dc503b9c26f9fbcc2a5f587907cd440aaef0c37e37644f +size 363006 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png index ebb207c6c5..ff67beb656 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:616c6ed62e974a649145ffd0f540e45701f302f4881f6503b240746f1084633f -size 353268 +oid sha256:21b77a16dd2e7d68c4f4cd8f2df9d0ea9cd55edb54dd48131bdedcee9c4e7395 +size 353264 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png index 6b04b74ff7..1e545b50a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f37fa6b14e11126a7cee60f333b2cfabd4b540b548d13467115533f58b7b333 -size 68208 +oid sha256:6ac7ccc7a75706f50fb4af5cd3149665b9aa52ea3a69b23b6e71a9f802cb8699 +size 68204 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png index 690f541b9a..d636453a96 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3b4dc78e6ac7b6296d7b24c0a0f28faf90b4dfb983cf0c970f41157b7ca469b -size 66907 +oid sha256:5f64cfe1b26fc3c5f294e68b91f0f0f785a945cb1cadad57152d3a72b713a9ac +size 66906 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png index ca2c69a01b..672d60c299 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97065ad20dc15bad0e6be815df8a5bd8b0411d11e7189e50a7abd13438f60f4b -size 69292 +oid sha256:d4e22dc6079daafbda97305b48143936228bc16e8c1dd84d46886b2d9f437dca +size 69579 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png index 34738a39fb..75c49364fe 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f65782549d9ae258584413de54a016705b705f05fd653b48c302b62dc3cd0c71 -size 70718 +oid sha256:0b6050f9ca4c5f714f6061c31a1a77147d06ff4b500144cb100fa10e05cc13f3 +size 71108 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png index d131a922fd..0273b0949c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f717db20299c7a563304a00e812810d30edf3a92090bdfd478b044689be90c3e -size 43422 +oid sha256:e4f5154e5b0cc46dedb451a5201377bd6a5f9d00eedead80faac2e42077e69aa +size 43421 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png index adeaf23582..35bec7f802 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:219df263627e37e386f32a5516e94f812a9a49e8094a5da7ed8787e845b00ae6 -size 37457 +oid sha256:622765f7acfe732a8ad0a6b4a802c26ac92926beec5cbb213e16c8c152afa410 +size 37463 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png index 55a3c08314..79f87ba1c8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a31f6f5ebfff32d770502a1469da23aea728693b4b03821f0747ced891307fcd -size 42188 +oid sha256:7e722c3f569138d1ca1e618c4bdd78e79e78a599effcf062cada98ad96c4dea4 +size 42197 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png index 58f05833c3..5cf3b1e3d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1aec8ef33c5f19e1de94a047b03f74ea98427e27f67c0425e87fc79384daaa5 -size 35121 +oid sha256:3cf7db826d0de2e45632e9e7828b5474f9588e07b3344ed75a254687c8758905 +size 35120 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png index 4afce772f4..07d4c6fe34 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:563c1fb871dd46823c24f4372c88e15e92e446b9cf14667f910e19d8cc26adc3 -size 43014 +oid sha256:a7d094485bb16c1e6bec8376cb788aff4c67e73aa103c91e9c588ee7d239b011 +size 43004 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png index ab862d3e1b..28173d1125 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0650642de63c69978d9665a78fa12095d4bb4c4d6cb226dd8de00e1f60376b6 -size 41965 +oid sha256:807fdac63cf66d0e22c3be3bb912fb813dae735ad80cead01a41226063476131 +size 41950 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png index ba95ff1e8a..ce2c6b58bc 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a6f32c806782b4766acd278fa7c7c6b80f3a2f31d6ccff49c01dec6a4463120 -size 40796 +oid sha256:19cad5807c22bb3b5137b94833b9355edd2a4e2dc3bd4e2fec6de47ecd91b2ff +size 40845 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png index 74998495a1..fbce4844b4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e63194ac849e271a3df7994f6b2ad11baa95f071b319b21bb37e2875b99201cd -size 42305 +oid sha256:ea37a3e4130be70df81abd1d91603630852eafa888588441c8caf0c6ffeff6bc +size 42296 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png index f79dda0606..9b6ab6166c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b84c9b52ed4d1845af6fd73a5a965fe872a898e097c45db17656021c00b47f2a -size 42210 +oid sha256:20574055fdf6970508234b241e2ea0af5ebe94b4e408d652591e5a1651d3f152 +size 42203 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png index 5deb2e11c5..e8fea24d29 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7374624c5ee056dd1a5ae4078f883dd844ceeb03715075d0edaa577eadca1a21 -size 42737 +oid sha256:9a3de10ccfb402fcadb87903c9c81aafcee0836eca4aa8d5c19093f8992addcb +size 42727 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png index 2080442169..d7d584fa5b 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86e732f7d44146add5b8a74c62942a1d67794a617115357326bcfd63fbef8a9c -size 43270 +oid sha256:2ba333f2b5d8f8d2483ab2e1d42b1bbc73341bf8777bb2fdae558bb9d5567684 +size 43259 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png index f0352b8831..9b8bde44da 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d1c6c551215f28d3fea257bd8bf696958d2ce9cd165834c451c856b7ede7103 -size 42540 +oid sha256:c6158753a141ac5759592eb50da522ca65cdef9749019ae63a58ff56e34022c8 +size 42530 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png index 24b1842b43..a6565094ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bffb85f5e586cf33e0ff91592e52595ea534771d41ae9ed44cdf37dc8982b749 -size 41812 +oid sha256:d2ed86adef0287ec1ecf024743ce53fdd04df8df6fc3519beef1fac6514a368b +size 41806 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index b2ea0e926c..c955529169 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:577e76d3079fcf609615983a2925506d8b19618d8cc19f9018f0a693ea9a7f4d -size 38944 +oid sha256:2b41b96a24c27b4b4996b9c12f8c9947c72f6ce80a9298a9ca0fbdb34b659862 +size 38998 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 109f7191c8..bfd9888358 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdd0f9ba41246283eea26da43d55363e20e7ac341d4579c7ba5f99f50674b820 -size 38901 +oid sha256:4f07e230e571042b96a6747357b90c692276e5817a784f1bd1fc8a13f7bdc05a +size 38955 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png index 03faf49046..aeda6a9e8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a27a7a44360c29a54875e0c9bad4090802eab311adfe92b454537bec1c63c33d -size 38145 +oid sha256:656740357bfe51573ba3f6faa5387d64076897bf4874671889e5c9e2b4c51e90 +size 38139 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png index 4c500d4520..ac5031e91f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce59a6f27ae108aefaeac5f174ecaca7f45f47578d67b06ec90f19ae5f0857c4 -size 36663 +oid sha256:9673aa3cacb1b04e09f94f265a7c3a0128c205026729cc618fb7552bed9a4bcf +size 36670 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png index 71e939e51d..7920b86025 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45078434e33023bb2f7fc5e5632c39f6f289e14a74a922bafbb5be5d69c59662 -size 42578 +oid sha256:abb3ac4c9ebc66d3f1b6457695147a59965026eb7beda75e2eba22a84449e0c7 +size 42485 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png index 09a3661a75..13ddf88701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43c9bb289d3649f3fb645a6ba148714745ae360fdca19547db26c6a856c3e0be -size 41471 +oid sha256:3315b18fdd823f1e30bd5bdff6c8c32e076f6eb1e7d45d2014dc012fd9bed95a +size 41475 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index 178191874d..1f2df272ef 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:726292bbf99af55d7b8f3c9ee64a5ce5a263ff51112cb12e6bf15834d8c7cb97 -size 38592 +oid sha256:f25d76ec7ae901cea990606f98ce8bfdc4e9d35830ea00bdcda4be39d8ec12b2 +size 38644 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png index d8a3991f39..6e978a0b86 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0756ec085e3d48d62d9bf5a65ffa88608bfadc7a085032e8371a5c628956eeb6 -size 42036 +oid sha256:69384dc3fe2b0343762a7f26b6a88f6557043061d1c52ee6662df7b11965fc64 +size 41973 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png index 3efcf95bc6..d2df6658f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23a551837f3170f0f788c6def95c3cc25788d523b5bd0c5065d7e667fc222717 -size 43203 +oid sha256:0d42f0d35ed1d39ce248466da8e78e334b8af321ae46d2f556cc438b72a5a598 +size 43201 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png index 63478b34f4..3e17b67de8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cb318d9310aca5ac9909e61407091d6d19719702eb90134e69f95a7f888f0b8 -size 42251 +oid sha256:eb28bb52f2525e56a9878a15f4ead5082552f34c949478e9007daa99b11672bd +size 42242 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png index b9a5cfd98b..7fc97a68c7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d0db82cf51a6c11a4076b0b059cab83fb3972f1f2fd198fc7d88473f3d71468 -size 42322 +oid sha256:1a6a449f71ad2b13548c98239197e9b41ff69dd61883165436c2536328f080ce +size 42317 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png index 10d904c88f..27e877354d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0e5449db01008ac93de2622c74ce928398c4b5b72955f6accb8be6227eff10b -size 44019 +oid sha256:7f747dfcc1231f58c0ddf1bbd65a371260ddc235c5154b813b9c160d48adf2fe +size 44008 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png index 41658f0d04..dd7a9d62d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b807776a9fc45a7e3e0269e3c49e3d254a0c352ad2fe5cc4a992eabc003bc009 -size 42957 +oid sha256:85de1a31b77b063d45e3bd8a3d9295258d7aeae1c718110616f3b0d070866115 +size 42941 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png index 6fb32137ed..1028b93a14 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb10e358f851007b69049cb402f1bcb96187ace186d0388ceca159df470c98aa -size 41745 +oid sha256:4da08f2a8b9028b010f5aa6f6723f62b9628e2934ca5f63b006dd4f95aa42c26 +size 41775 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png index e50e4828d6..09265aa6a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84903a3f98030ff665fadfc33f652f90f7f7218b0cfed1d2aeda28a841d8eae9 -size 43286 +oid sha256:004d09f28f9557dc4777ba570519953617a234ee8e81829da6a9e6c1c859e34a +size 43271 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png index facd9bf8ce..aecd669aa9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df98b09223ecccf3f31916e206542e1dd4cabd17164afbaf5146308a35191c98 -size 43176 +oid sha256:4fefa1e43c387aff8b21898d7431683710678d23f75ae66fbd5a9674b6dc6aa9 +size 43166 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png index 6e91a419fe..27ecce85f9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fe0960d489628e9de6d456ef1fb87f7e84612ecc017175e0064f9ca2a3f0ef5 -size 43677 +oid sha256:1545f2842633d9257ac4d04e156136054d83117051836690c769c8c140df4aa7 +size 43668 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png index 4404a8104b..6099e3dfea 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bd079d0f8c7a9f6f51ab19eff354e160bdd595afa35a2b0fa4f850ed324fc83 -size 44285 +oid sha256:750e5212166a2037d7c8781bf3cbc26f43e458045e0adf4bff0556d4c1b0fe35 +size 44271 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png index 8944270170..c37acd6257 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e01dc9e4f2bbe0e828fc989316c4c1273de8ddd63c51597d14b9d82d4eeb37e -size 43526 +oid sha256:745513bbfe1ec194c8245c3dcfaeb622e2035ffb901c221e4417ee68dc562926 +size 43516 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png index 71cc58dc7a..1dfe867624 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20dcb59412950d80583dff0d5bac8fa1380a5cad9dac8e6ed32272fc7be39e8c -size 43033 +oid sha256:fdbaa5a809e49505bd65b3a80d58d34c86349bbd232b19670737cfe71a341626 +size 43009 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index abafac6652..49c174bf4c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4423c2b99ca7270ea2a9496c71742117a6b5a63f4d053810cde5b724cf309827 -size 39819 +oid sha256:09b3d8e59d77fb1a56d2e3fe65ca4653f1ce0e83e2d1ae66af5b2fae894bc2fe +size 39844 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index eec52148c1..ff1e4c85eb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:630106a8a6373edb3ea61ebe9004d1e842185e16fa67c5103e9207f12388197d -size 39702 +oid sha256:7fa29b5231b97749c6768d36f278a53fcf7dff7d3f19d7800a1ec3fd785940dc +size 39727 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png index af4b7e3e4b..3ae4895e73 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:666d69adf97dc13817ec64204ba36f77837bc58593233c6988a9410737e17f0d -size 39243 +oid sha256:de557bc7ff39c13540f6caa70807065a5506f67d983661a247d8da7bee0e8437 +size 39241 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png index 898001307a..50bb5ae415 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a782c4d02d209fcd9625f24dc7008c9d0bd0862646ed518cd5855e015d444cb1 -size 37680 +oid sha256:f1dd2be009cf074cd5192630e69f94fc75ffed71c5da5f6fa41a49dcee5b33d0 +size 37669 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png index 4b5827b560..526d814126 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6bb45bd7efc53d3f7db74f5ed5801a4448d39cb231404c4655b0c9e91f246d4 -size 43446 +oid sha256:02805cb9b7642e8d227b88dd5384efe5e95ea58c5049cae8f60cd6af11fdc19c +size 43388 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png index e47ac6ab05..20e2d596cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eac86b6ff6d16de49e2cd063983e06bf144d796e86ef00e992cd3f1f0d248b47 -size 42371 +oid sha256:9d85ab1c7243b178d24b2716320d6a005f3f56f1f2953e1ca29879af2d923311 +size 42369 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index 546f29bed7..2a4e8a2789 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4e5f3b38e510ebb3bf3e72a3eb28597933b438eb466fd4a5405f61b7d8c199c -size 39363 +oid sha256:51b8a65fa1ea90f0f3227d11dab9e02b6821e159eef5288ed2cfd4d04ba52fb9 +size 39390 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png index 30dd8c4ed6..9420f03ae5 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb1c8acabcb77021ed8dec07dc0bcf8537342da4b99030ad6bcb07f97d48c30b -size 42948 +oid sha256:5ef4eeee1c2d48fd0b4bc2db2b5e63a1669a7b1347340c70bd08f82bfa476a99 +size 42943 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png index 239eeea47d..733da0d460 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07c72b2af77dd3d9b096b800c035ebc9e5e256dafb351232b67aba1cbe8e6d2b -size 44390 +oid sha256:f276d3cc7714d47086eff53cb564d8a9b604cfd0b6dbbcd4eb906326f5b03110 +size 44373 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png index 44be14ec52..7088632f7a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aab42df4fed8f0dc7696f7b871a7d24db2db0d07014131f682c18b3a25a65f45 -size 43295 +oid sha256:4deed8665be752e542a35fa10fbfe52912c439989ae021ac8234f5641a6e952b +size 43284 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png index 2c12e4ece6..cd5e1b9bd4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b4ef80cebe6c2edd5c7a66fc77e7360ffd845936a1984a917dc8f50c66ef89e -size 43307 +oid sha256:494e81f1ca9e65950f3f7811d420154f3df9cb39749341b845ae873fdc0c34b3 +size 43300 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png index 168f2c58b9..1a480242fd 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70699c27896e4f718fa9266da6309f15760d555ccab3e70cb4ff784d200ff548 -size 15947 +oid sha256:a003185cde12085777ea4d8e9644340e6c33d5cfd5f28a334505ddcfb2ff086f +size 15988 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png index 8ffedb6083..0bec1fd952 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:116674e61bc1713dcaebf771f24259943564a72038ee5f44e4f1725a3f4ad264 -size 15297 +oid sha256:dbe0459f90845db50c49a75d93b557242cde82fbc5563d1ba971f307efe6310b +size 15353 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png index e878beb841..5adea69646 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a8932b7cda9041d40739fcfdbf9d41ef949c22ecd81394d5ec5d68bbeca7ba2 -size 24248 +oid sha256:570e2d342a5783c6262ec635ca77a4c9b9dbc350630c20ab6c12b18b2a4a4629 +size 24283 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png index cdf5fb5cab..2b32d0dddf 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fabeea3e8fe50ed61c3ed73e8bc9c16feea9db9e96a30c62e2643c7fd61898c0 -size 23366 +oid sha256:0115719e51a0f718c7071bd01798ee0212c73c04d423e0893a6abbff816a879c +size 23420 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en.png index 9957d3f2a8..3cdd56a15a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6453b165bca4b509d7a2e1749e0534f5f12465de3b32bb0513cf377021a57a5 -size 5080 +oid sha256:6ac466625bd9985cc0c820a99b30fe6e9c0e3ef738cb47d5eec9a92a5ed1cda4 +size 5100 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Night_0_en.png index abea5053c1..ec803d2726 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_BetaLabel_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2431e2c666af3353ae85d9a101d8dde1378b4fa3d1828ff23a7f4753f6fb2725 -size 5112 +oid sha256:40894153477d0d133746def9003533095c1cf18f5284974bfb268790eaef4e4d +size 5122 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en.png index c841a032ed..f255f6b584 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae006adc82d337fe478f01233e7890f583b93470987b69227666aad4c7749a51 -size 7037 +oid sha256:80949f82856fae9017643fb91a9247fbff10360e738e5c1e1c8cb20964319a53 +size 7054 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en.png index a81dfe7f9e..d14e225325 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24267c25c8b258355b9651f71f1446ef2dadc5c868f56d23f63957e9a2db88b5 -size 7134 +oid sha256:b7ee25f4b4fd3faf4b5d50211aa7bbb029c658d329acb51093b39a603a5d9037 +size 7077 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en.png index 73e03f01ff..cbb16b65d3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7739f13ad8e137ee805e7b105c0ef2caac23f6cb57786f9259eae65ea45d8a5e -size 6524 +oid sha256:da8c84bce2caba0a96f884e09b6c272a6a05b3676ca35c85e4d384e983440608 +size 6654 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en.png index 53d3273210..8b1995db1c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4afdd017461f6fbc84d6833401bb929180c858c1ba256167f7fd951cc2244c31 -size 6546 +oid sha256:944fb28c55313433e7ea435c9c5041825814c1209ab1a50067fe56f85386aebb +size 6574 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en.png index 06e37b48fd..a38c890d57 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43d5485f54806c93c3801c9fdf430bce0786fb0f17a11f17b1f7b4f14fbf1021 -size 6087 +oid sha256:4937e2e3776d515f9a1d661da96c0131229772f3965639e1f79d84cb4a7645ea +size 6132 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Night_0_en.png index 2fa9e9f05b..e96ca6adf3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7b729ccbd27f32162efe06f1f806d0483cf98b3d47175a0fbb7a88b2fb5e1c4 -size 5892 +oid sha256:86c742e833d91d47bdf3410b7c24a369225bc43f222adb578c7abb3babfe9e1e +size 5986 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en.png index d7f6563f39..6985721c59 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f6d00c045200e5f98d31b06afd5517ee2da41080281c6d8601ea0169a8b32f1 -size 17187 +oid sha256:b876487f0e69c5a52679254306610ac11cbc094e23ca9919cc67c073ce8d02d8 +size 17395 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en.png index 9b74cddfa1..b3e49c2d38 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee64a1ca25439b8dec91e873238f52d62fcd4683c7d4d619b8a053fa0b6040ab -size 19185 +oid sha256:7c58cc25cbc6cd4375aaf010b97c016a17887da201ee9e00e5a28777a938e825 +size 19374 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en.png index fd1e0d7ac3..c0cde40f12 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dfece8ca4d27aa8bb0a96711f4492a7661dd9c1a00a483f120c7fd25a2abd524 -size 19146 +oid sha256:6867123a35845631c71a206f6711d19f98949b627fe08a56edca906d0cf39d65 +size 19357 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en.png index 14f3d254a0..f4282a639e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e410c37f7044dd47d56f965c1c65294d639c2c7d614e67acaaa90df4121f6e48 -size 20253 +oid sha256:d2cfb17927107faff4eed8544f0673d806e7bf93c84ba0cf536bd3108d510739 +size 20592 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en.png index 16e14a6ce9..b1a3f054bd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a03040b73e680faf99faa8c4cf92d0ba64353346e3c80a00934e0986bbf570ac -size 22509 +oid sha256:406041edf077219d0006397adb4135a0b0ff5cf012982225f8a8d65e5b538214 +size 22886 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en.png index 16eef7e0a7..f6b4b1cf78 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b080c7768f8f954afad03d5c334207692fcf1f4e8af7d41fe0d2fced384fe9b9 -size 22130 +oid sha256:3f6bcebbcdba8ef2e472d8d76549631508d3c36a4a9ff3fe0a8a6fae41f06a26 +size 22518 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png index f5694840fe..104fca8396 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b41f7235c9aa037dea64a67f87ff688d4b229f1b5a46bd563f57a7b6c690d9f -size 24926 +oid sha256:321c0b750862d017100c61f7c4e5656fcc6d8566e0cebd81586dc6891d971b76 +size 24932 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png index 1b4ee926d1..97c8f9a589 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20a85881942bff954dbf326116eca8c2c1d9b2dae3c7a8adde7f17de01c6051b -size 65875 +oid sha256:cf70f35d11eb71737f0d33bbdad1073a3ce15bbb6534f4cda3a8c8b8a21f3da8 +size 65858 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png index 99527960b1..1d7613430e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73749a1655e26374776fa7e8aa83582b969cd40259a5ff580710a2b19acdddb6 -size 32072 +oid sha256:00eb9c6756c353ac82144c391617a515d871940c32d0604d86203f8568e9e5e2 +size 32077 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png index 1d6a5b52a9..b145a008b0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf28d2f2f6881f4abf14fe8228b05cbb9194685be7a1bbb14832932b302bdf89 -size 22324 +oid sha256:f44fa660c80894392dffe711573d536ab8e71b82411f339b45bd29b1823d4919 +size 22325 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png index 5b56b809ed..a3ffd3de6b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b56433b754cdc8bb335acc1ca97acfe7c55474976f657b984f4f34477e2f9dbd -size 21555 +oid sha256:442c03aa8abe7e43ccbb1c736349d606353833c3b33535797b3b2840d46b7a6d +size 21554 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png index ae07f25c42..f3671582ac 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebc0ab69be80185ce7987b412d47bf01c8df140a346bd64a983b6c51fdb0b23f -size 35700 +oid sha256:fd6ac8137997251a9f8800a9988d0fbca7d8adfb1e7a862513e09dd02faa931f +size 35693 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Day_0_en.png index dfbf9ff253..0e350840c4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b0f8614dde547fb8e3ae607840e97dbd33f9d0ba179174a3b22dca715ee18a1 -size 6025 +oid sha256:0a81766956178672485c43d1a904e7d3e14ae767c0e0d26ac2b4bdce13c0559e +size 6090 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Night_0_en.png index 1009cfd194..3ea800f130 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_Badge_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7382ba4a96f23194e5ba732e600b9f8571f014085b98ad5e450f020f07959fe -size 5854 +oid sha256:37f1b0274f4f011736797196e268d5c07c19449001faeb1ee4e9950c2f956c6f +size 5954 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png index d91c25f8b6..f6d53a9aaa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a9147ee3d19edc25ca2723ce63fe0ceea0d071a2c2aec27f0035c862ff216ec -size 102540 +oid sha256:22f7a2f98e8a7deaacaaeb75233cf1cb006c79c8e108b3c000190ac7ab006083 +size 103743 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png index bfe5178d57..2bbe3e0435 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6434eccd77ea3b9caa1368499c08d4f7f796132c217c90df335004547d42103d -size 35663 +oid sha256:194e43d76e485ce80195018876ff9f1baeb1770c13c88388cc8adaeb192b9367 +size 35904 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png index a0a19059c8..25f1737a6d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc6ae5ce0f90c7bfaa76aa0d10e23fabade20a2a23c112f5bceeb66aff585dd1 -size 34552 +oid sha256:4e40c4eba4117cfbc37f2a7dbebfa2cb3f6a81b12507fd3c2deb9df2d40b4754 +size 34349 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png index fa55a464bb..a684be36f4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e956a7bd54ffee6dea722ff5c8e5a602f797ed82f0f4010cbd721cfed015f002 -size 51477 +oid sha256:94672cc5b4e0a4fbce2fe3053636605a7984b6cab3bef41cdc1f6b174a35252e +size 51851 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png index 6400d5d479..9efb85ed8f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65d838a4214cb8f5f05bdf8d45b3641c283c9abf9ba4490df2ac08812ccfa0af -size 49793 +oid sha256:ca6f44470098e77a72f5b171d36d793b63234dfade5cb6e688832e6ca3308275 +size 49451 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png index 0210d92d65..7e5c3f7c9f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07dde3fb17519070b77161696e914b84fc22aae9ba3f0450ee90f2d97f958856 -size 63523 +oid sha256:49f2eddd77c7a5e7a9307c79068962432a06542c327ad984e931c3de9dbf93f8 +size 63577 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png index 50cb131812..05e2660879 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37a468d82a264f1daf018045d39def3159b7109c0ad658494fb545fd545c2cb4 -size 60915 +oid sha256:6507cecb7cb8234523c458ede4aa86d6efe818ce59917d9880e13e899118d343 +size 60992 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png index d4b2df8fe4..4698ec2b86 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58d71f16891297f6edd291d20860fea05bd6ffc1ed53082337b4b0106f20a334 -size 64466 +oid sha256:fd0cc87122d0a95938e3a345d256897dcd4a6f76d0fc3f025b5dff62799e9aec +size 64538 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png index 84f226777b..374c8d58d8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9fc8659a0e124f417a15b4be2e1871c41acdb593b2584a86eefb2b75073da61d -size 61481 +oid sha256:feb109a35370f31716f4209dba88ae2b10c31cb612cd5045fcf8fe61a519d258 +size 61541 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png index 630f6fa3a0..a9768e6f92 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d36612b8e2ca7f59ab05b4b4118012c2725da9ebbc7df63352c70375451bd13 -size 73958 +oid sha256:184eec76d1b81bbcb0da05f190df652e0acc99b511f39b6efd64848ac0265333 +size 74011 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png index d95da7f0c6..4d9e3852b7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9672fa099af849fd75e4c6a8a5d01682e1e5a0283958c6abe2adc122ad5e2763 -size 60519 +oid sha256:8b58254ab6455b9cb669f585e55d63b3ea2d0d1863dc9cc33cfcf7efeb9c9aeb +size 60569 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png index d7ffa82c24..e1f56a9a7b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fedd88e24489233b32e215b671f238467816f6ccc5bf634925ec845d32ffed90 -size 73376 +oid sha256:de0965032145efc6dd7a2eeb62cf61a38f7c178a8b8da9aa3ff38f8408698241 +size 73436 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png index 075a41d8ad..1f689785c4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37e4dda90892ae77976eeb7c78c58e236c96970f46e305a2a9e5814841990a5b -size 82106 +oid sha256:096674378b59fff410c6788ba29914bc4711d0f78f6bd82caf63b1e4494c97bd +size 82156 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png index 289a88628c..a63e418a77 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:992291c170b880009c4efd872a92d19d06476f506bb748b5d5bfe4018c87d01b -size 63075 +oid sha256:4d35305c3c04c597092b1d7cd35718cc6e8b3ccf262f36a5e309321d2575a1c8 +size 63135 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png index 42e2287129..79e9391ba7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd1d0f3a07d29610650691389071444fdd2117fc62ccf52619ea43edc65e9169 -size 61984 +oid sha256:1dec29ccf1d615eeea8527a9faac5547b4f41bf7bd0e43708f549f0ef9e3f128 +size 62034 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png index 1219e15937..f547f8a6b2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca4142324fe63d5a0c3b06a9af710ba3484209a2b938115a68e35d7785cd28dc -size 68983 +oid sha256:a55fd94dff2318b2dde74c7db1df8dbdbcfead6d897ff60fbdcbc1e016588bf7 +size 69042 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png index 643df1809a..d9c304aef6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c672e86ebd42326d6373a55b9fd5b3dab8d5845af76d0b15ff0cc478a7f68be6 -size 90870 +oid sha256:30919bba4348eedd2491874053ae23d9ac27a9aefdea56611564b4a4df8aac8a +size 90920 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png index 2eb532fa42..eb8c2523d5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83d739bb6b0840e44142b986f04bae377761c59b1093f329c5392caa8f6e1a03 -size 61413 +oid sha256:30b2ec608ba0da25348d72ed3e5cb8bf939b4b17969e1bc8d0afe2a36a107b83 +size 61464 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png index d2f52adc69..ef397e5d6b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:592397176013d373cc1e10b200a804edc1bd9298ee8d6deb28a78a44e1e4787a -size 62569 +oid sha256:407dc99e70a309c124964570a1b5f0c272c6b44f6f099d06a87d4e5aafc3d925 +size 62615 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png index ec4f1a0002..7926c0c712 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b50323e3ff9f7b0ec0d8eae7ca0ed889c1beb274934a31e6f6f97d8fda2a15bb -size 68751 +oid sha256:523ccef98d598f6c92b95fe1682eecfc7e68e76d34a34c64f6be92ce94bf650c +size 68802 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png index 06c15ea1e1..8f22c38553 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c98826a30218349b4fe2f12cb60c25f27eb9852153a58a5638f76ad5a036e00 -size 60929 +oid sha256:140983f21a45088f5ae2c9616f4b66533c79b26029dd7f589683106e6aa0931b +size 60980 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png index 1306534870..6db788f931 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35b2efddf5636cde7c38237f4021554e7d97dbc533ec319bd3b8cfe87eabf42d -size 71784 +oid sha256:8acf2059f390b026e192c4e30ac2e374197b88011c7d0c0886270f7d41285e18 +size 71843 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png index f7a80fd218..4b599055d9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2e81ef71f7329b67791f9bcc8faea5ea57f1a65106fc24dd1daf059c7beb7af -size 58663 +oid sha256:9edaf14c0b0db2d9e809ee49e1a3735ade58a72e662e04feb39204b7fcf5b382 +size 58693 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png index d8d8daf3d6..f6c1f38e3f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0f17910535315498aefbea2bb6ab090a7d86896558ce9fc360bcb065502acb6 -size 71231 +oid sha256:95895c181425f9569e6c18414667130a2c272e6fdffa45486b2e56f68d8a2bed +size 71289 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png index 3ea53f7f2c..d3cb1edec3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:178c5a54819558973cac3b0a581c42278bdf0f86b21d21187a64fbf6dc0184a7 -size 79661 +oid sha256:9405692b572aca986d5bdf4c70182789776a6a99eb6c72bdbb32446ad03f3cfd +size 79714 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png index a4f31dc1db..3eb9e16d55 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8bbe99e3f3686d38176ac7a3833ced49e05023025aa287c1cb4c8d0f7ae992b -size 61150 +oid sha256:024388bfae5dcd6ff96b8bbcf37037f9c339d4d7a514ad3d096a89330fcade6b +size 61206 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png index a772709fc1..38c13a155e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4da6aa4ff5b063a0eb0bec7550a4306f22427f0a10dd65b7a3a03419dac43d47 -size 60118 +oid sha256:d6c45be7f090c67756caad58816d22a44182407b9b6fd22d594711d61d194baf +size 60166 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png index 3e06d26688..86c24fe574 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a01f535e55351ea42980bb7afa918bbd58bc41bede32ff73bb402eb5c4db7b58 -size 66848 +oid sha256:8d96404fceabc8945bef767daf670470f073b3bd214003990a38baa29ff5fd5b +size 66897 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png index a6685f1f13..ab5e7d6ce0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8896aaf421365ce42a2f7b83dfa71fe7c541a99053dc47649140881698613fc -size 87845 +oid sha256:34512dd365f1e270c269a6e1ed85394ad34a07de124d770896b752ab993276bd +size 87890 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png index 017eea5ad2..52209b5ca6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63dc10fed81ee563b5779f552419035af304663e5475abf16f390e9cb50715a5 -size 59524 +oid sha256:c0270681b59abdb38682a9ac5aad7919392c5444fdda6fc86d75c8115ba1c4dd +size 59573 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png index 9dbfe5d5a2..619c713d14 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25f1e03b14fc39ea069bcb1fda30d49e839dca025523ead7590990831a0b9188 -size 60651 +oid sha256:b43b7277eeaee8243ba47ccd9e88b89e1e1f8500cd2399b9f8e61bdb20e04033 +size 60695 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png index df2cda9dde..326b358f51 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bb9258874c2cbea357264ac2044a44a2742671319d19300c648e84809442f4a -size 66517 +oid sha256:e9ed04cda8b0a500d4d8d2bfe4d34edcb8ffd9e70ef0d0b4f381ef4af0432d55 +size 66563 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png index a374e89168..63f4a611c9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c546ed7f7120d1de974507fc28e3b7e7a479c71958b739180699947c60f69d2d -size 59132 +oid sha256:db0017e0d9005c8c419461dcbd8821f4559b6ff1a5e3c8fe5cf6701cc0821da8 +size 59178 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en.png index 8f6cf01450..dd72a06454 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efc225d678533e384bb0faf6daeb385f35b72b27ef2e6c7420d5794966920c3b -size 56765 +oid sha256:3467181fd666dd8200c25366392f43a4d80ea051a18d3b525bb7e78dee6757bd +size 56785 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en.png index 2f51e7b55a..e637616fa7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c76814aa7953eb75dcb0a1fddcb4b9dc755c863003dc8acfc0e41701f9db95f2 -size 54185 +oid sha256:bb37d793986aabf523d90cbf90d3873d51deda4117d340d3a931cc6a5b5aca80 +size 54246 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en.png index 186753469b..8301d09a79 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98dbb0ac81d2079ac41f107b78e6fb7ccbf1f53fcd9e95e8716fb05ca1b14ea3 -size 36091 +oid sha256:09faeef5f5864f93d81f271a67826acf417b228987c6f918b95b31f91a468cb1 +size 36097 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en.png index bb102c7bcb..943d0abc8e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c454bf724b6875610870eec156f0c544e84baf9c6e9a755b965f692f498a1b1e -size 34222 +oid sha256:246d4bf81c16bbbcfc82dd23b23bb1471e3d5e078bc7ecaba3c68d2ab3bb75c2 +size 34307 From e7cfe1d456eb4bb9fe863521316d0f1aa146b6bc Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Dec 2025 17:44:21 +0100 Subject: [PATCH 59/64] design: CheckableUserRow uses Checkbox --- .../libraries/matrix/ui/components/CheckableUserRow.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt index fbaa827ea9..917b03f309 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt @@ -11,8 +11,9 @@ package io.element.android.libraries.matrix.ui.components import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment @@ -20,10 +21,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.atomic.atoms.SelectedIndicatorAtom import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.theme.components.Checkbox import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -63,11 +64,12 @@ fun CheckableUserRow( ) } } - SelectedIndicatorAtom( - modifier = Modifier.padding(end = 24.dp), + Checkbox( + onCheckedChange = onCheckedChange, checked = checked, enabled = enabled, ) + Spacer(modifier = Modifier.width(4.dp)) } } From fc0f1af52ef4f07581e8c264fc95fd5a1b7bb3f2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Dec 2025 17:44:42 +0100 Subject: [PATCH 60/64] design: update vertical padding of the UserRow --- .../libraries/matrix/ui/components/UnresolvedUserRow.kt | 4 +--- .../element/android/libraries/matrix/ui/components/UserRow.kt | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt index 56e88bf3a3..32fa641a63 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable @@ -45,8 +44,7 @@ fun UnresolvedUserRow( Row( modifier = modifier .fillMaxWidth() - .heightIn(min = 56.dp) - .padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 8.dp), + .padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp), verticalAlignment = Alignment.CenterVertically ) { Avatar( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt index 932cab9a49..9bcf0b323f 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt @@ -11,7 +11,6 @@ package io.element.android.libraries.matrix.ui.components import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -37,8 +36,7 @@ internal fun UserRow( Row( modifier = modifier .fillMaxWidth() - .heightIn(min = 56.dp) - .padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp), + .padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp), verticalAlignment = Alignment.CenterVertically ) { Avatar( From 7fd8ae5c517dd02a3e258298bc8f09dc275234e8 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 12 Dec 2025 17:05:45 +0000 Subject: [PATCH 61/64] Update screenshots --- .../features.invitepeople.impl_InvitePeopleView_Day_5_en.png | 4 ++-- .../features.invitepeople.impl_InvitePeopleView_Day_6_en.png | 4 ++-- .../features.invitepeople.impl_InvitePeopleView_Day_7_en.png | 4 ++-- ...features.invitepeople.impl_InvitePeopleView_Night_5_en.png | 4 ++-- ...features.invitepeople.impl_InvitePeopleView_Night_6_en.png | 4 ++-- ...features.invitepeople.impl_InvitePeopleView_Night_7_en.png | 4 ++-- ...crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png | 3 --- ...ypto.historyvisible_HistoryVisibleStateView_Night_1_en.png | 3 --- ...historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png | 3 --- ...storyvisible_MessagesViewWithHistoryVisible_Night_1_en.png | 3 --- ...ts.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en.png | 4 ++-- ...ts.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en.png | 4 ++-- ...ts.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en.png | 4 ++-- ...ts.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en.png | 4 ++-- ...ts.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en.png | 4 ++-- ....receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en.png | 4 ++-- ....receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en.png | 4 ++-- ....receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en.png | 4 ++-- ....receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en.png | 4 ++-- ....receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_0_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_1_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_3_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_5_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_6_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_0_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_1_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_3_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_4_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_6_en.png | 4 ++-- ...res.preferences.impl.root_MultiAccountSection_Day_0_en.png | 4 ++-- ...s.preferences.impl.root_MultiAccountSection_Night_0_en.png | 4 ++-- ...s.roomdetails.impl.members_RoomMemberListView_Day_2_en.png | 4 ++-- ...s.roomdetails.impl.members_RoomMemberListView_Day_3_en.png | 4 ++-- ...s.roomdetails.impl.members_RoomMemberListView_Day_4_en.png | 4 ++-- ...s.roomdetails.impl.members_RoomMemberListView_Day_5_en.png | 4 ++-- ...roomdetails.impl.members_RoomMemberListView_Night_2_en.png | 4 ++-- ...roomdetails.impl.members_RoomMemberListView_Night_3_en.png | 4 ++-- ...roomdetails.impl.members_RoomMemberListView_Night_4_en.png | 4 ++-- ...roomdetails.impl.members_RoomMemberListView_Night_5_en.png | 4 ++-- ...tchat.impl.components_SearchMultipleUsersResultItem_en.png | 4 ++-- ...tartchat.impl.components_SearchSingleUserResultItem_en.png | 4 ++-- ...atures.startchat.impl.components_UserListView_Day_5_en.png | 4 ++-- ...atures.startchat.impl.components_UserListView_Day_6_en.png | 4 ++-- ...atures.startchat.impl.components_UserListView_Day_9_en.png | 4 ++-- ...ures.startchat.impl.components_UserListView_Night_5_en.png | 4 ++-- ...ures.startchat.impl.components_UserListView_Night_6_en.png | 4 ++-- ...ures.startchat.impl.components_UserListView_Night_9_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Day_1_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Day_2_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Day_3_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Night_1_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Night_2_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Night_3_en.png | 4 ++-- ...ibraries.accountselect.impl_AccountSelectView_Day_1_en.png | 4 ++-- ...raries.accountselect.impl_AccountSelectView_Night_1_en.png | 4 ++-- ...aries.matrix.ui.components_CheckableResolvedUserRow_en.png | 4 ++-- ...ies.matrix.ui.components_CheckableUnresolvedUserRow_en.png | 4 ++-- .../libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png | 4 ++-- .../libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png | 4 ++-- ...ibraries.matrix.ui.components_MatrixUserRow_Night_0_en.png | 4 ++-- ...ibraries.matrix.ui.components_MatrixUserRow_Night_1_en.png | 4 ++-- .../libraries.matrix.ui.components_UnresolvedUserRow_en.png | 4 ++-- 65 files changed, 122 insertions(+), 134 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png index e08a8add02..26cdab67d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ce85ac67e6ff108ba0d333e43d5ee0f8017602b7c271945de779b15d39f4884 -size 38233 +oid sha256:639cb5bcb5a74d1cdb94703c42189d1a5d9fd2b9d9f49c23cd47bb340a830710 +size 37829 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_6_en.png index b06373ab5c..91e9bcc3dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04086fce6b3b8b17a8736903c1975e3b08fb2273ca6c41fe71000b61ce7f0950 -size 32559 +oid sha256:651042b5628da42cdb4d7d8fb465ba279a12d78d8f51a688eeee90bc413002d0 +size 32992 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_7_en.png index e4c273afd6..09e1bb63ae 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b796eb0b26e073beeff1ac1f87e8e403e39c6030d092fc3f18b29d26e34d57af -size 25476 +oid sha256:b2e674fec4e26de21c82e020f9c9a7b693599ff98c1aa4d5c846c0179db3e1bf +size 25727 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png index 5649bb84ae..0fca502f1c 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3497c9641b660ff1de9a54e1051f9ee6fcebc31a631f681082d28834c1273df -size 38989 +oid sha256:e3a65959829bbf2c2e2f2842b78f620e417a0edaa5996f7a53f24b6cc997f9ab +size 38491 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_6_en.png index 40e5dce4ed..c6fc626fa3 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49c325c609a49cc5a843c257a0cf7977d2fac8916404d0e1f94b58274546ef73 -size 32660 +oid sha256:ca72547eaa183851897287859b5be5fe8dad13f2d69a374d7e62477de171f37b +size 33060 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_7_en.png index e9b761b471..df9f13f8b4 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66220acd53b2e0e60c710605d79f316c961dc10d281be650bdf50114c04be758 -size 25030 +oid sha256:8d49358838af8128be8b8a1e06712a5656460e247db0ed496186cc5017a31ac4 +size 25307 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png deleted file mode 100644 index d19a140456..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96bc0c555188cee4b3f3e3e0f28f944a4225e27b9a1069edf2b10a2993ee3080 -size 26078 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png deleted file mode 100644 index d21a12dd64..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_HistoryVisibleStateView_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a103daf8447cb571a0c5010d062a7790aaa0f3dce30f052bf86884708f4881a5 -size 28769 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png deleted file mode 100644 index 22d05e61fa..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9682cdd7e08e32591fa47f56da5e6ef4cc3a777700931c2c86e9b802a9cf25cb -size 67342 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png deleted file mode 100644 index b2bb8ac3fc..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.historyvisible_MessagesViewWithHistoryVisible_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d20c04c6385e675bd71d93d2d5d832509b1300a27708245755f263392b33bc8a -size 69457 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en.png index d99f4f4bf2..24cd69292a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e10ab8535d37d714ce4ec7392fed1e3ecaab3f459c1bcc872601bed6d57fc69 -size 11417 +oid sha256:64b472e04eca6203aa2563e65b0f54af3b4baa9da1706a4ecf4a0609697d48d9 +size 11403 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en.png index ea1c9353b8..517f2db0e7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e97d19ae75ab72b57ec48bf6c39bf1f742e25ef5acbb20a7583ba697ae4d745 -size 16881 +oid sha256:fdc697787133723238c5b228b53c76b94e8a159b63df9068189398439d179353 +size 16904 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en.png index 4243e92aaf..35ea429edc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f58353935619cb6551f737a95381bdb4a1736fd77054886cd908044110c6dd03 -size 21967 +oid sha256:f4a48c30efc2dc278c5c9aa6274899f0c669fc7d5433fafd737681bc3486bdd2 +size 22025 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en.png index 1b2abb045c..eb3bb61a96 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6ae65c60453959b99624c3b51c6b84b721ef9999bd0313e6c785c9d5bb82c00 -size 26218 +oid sha256:ddd99012579e28dc0d52dedcfa097825d3ada4548c4a3d3595a6fa9347168bf4 +size 26295 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en.png index 0401898572..f9e54b9351 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a00ac9b95359013527bafc8f244b55ed02a75cde8a81a16815e121575a4b6ae -size 31544 +oid sha256:1a086cf3f75b8e525e41684e5366a5d416ae04cd43a093c8f2f09f6d1509b3f2 +size 31717 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en.png index ef64f0eff5..fca1afde50 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1efb80a24b556fdeea528de1b5afb004100616bf3163c7b5c5b184a2ff82a84e -size 11080 +oid sha256:f4891d5825449f0362bad22f16cb8ffd9c9332312f9528d0acf23a8db146f37b +size 11055 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en.png index d468d2491a..56d6e2edb9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70b76a4cab9419ac6e49352982c203a87db6f7cb44091f29a8abf24584db2292 -size 16208 +oid sha256:d2d1dcdd63d79289f6d56ecf3b108e147791e218cef96c598bdfcf0e51f15ddd +size 16273 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en.png index 009bda75c5..082b848111 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00fce403745ec69a35aa00ca423cd42633e2870504806857d13ffc7d920846fc -size 21474 +oid sha256:17ca7249652b4fd0263cedd75782e8f57277feecb0d77976b8d428d1621506b0 +size 21525 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en.png index e1f610cad0..6d88f73cc6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cba66ab8e687a3f7fd904fda4001bb5bee26d8825d5d19cf700aefad98637d6e -size 26307 +oid sha256:87501fc77eb9026ff8b4a703eb85c93b31fcf7c0d0cbfde7afe9b6dd0110d068 +size 26460 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en.png index b9a11d8f1c..037728612a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:417f719ea18b93aa1ced2c2fe0cd73c2558170a16df8370edf2c66491337b607 -size 31734 +oid sha256:9cf2adb5e8ac9f8bca87e6b5e1a8b5f59dacd6ee470d8a3b5bb5c2e6233e1709 +size 31937 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en.png index 076b23e094..cbe9ac4af5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9e3e250938e4dec52652a16f5457c005d9a112ee4ca169d6dcdcb0d8682987f -size 58911 +oid sha256:9f6981c35088873ccc506975aec10c62ecd706ae4fa73f11a3fbb7a786e8ca5d +size 53394 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en.png index 7ad29e0567..ed83508084 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f74e0fd4c913c895b3edfb6ee8b75f5034230d2462947e7cedcf13aa749ecd1 -size 58628 +oid sha256:44935e8bb95a3c4967cbe23de7e067519e9123edff1129276da7cc73067d83a4 +size 57956 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en.png index a9dde01586..7703f26bb4 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4084d378d7972223d258df063df13998b2fafae02bfc6f585472808dbf66955a -size 55264 +oid sha256:ad5a2a0849cd17e90124a20fa99e79e05182a518d6f9789f16e0a83e1c06bf1a +size 50695 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 1b61c9177b..74796eabbf 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c57c0986de2480dee08b62b48ccbb8eab5fd3271d0d0c0b9e3d3d7b9cebd678 -size 61750 +oid sha256:3b04ccd9f43fa8283e62d43de910bcf68ceba81cec88fc1e20710252e0828c85 +size 56290 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png index f12c58ca40..062db915ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:912a4cc70e1385a661738ad8a44f6ef684079754b704b259ac2122f1d1370ed7 -size 61266 +oid sha256:19b57b52597b1663725a6681facb0e98351b4bcc482b21722539762ef4e26e21 +size 55782 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en.png index 076b23e094..cbe9ac4af5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9e3e250938e4dec52652a16f5457c005d9a112ee4ca169d6dcdcb0d8682987f -size 58911 +oid sha256:9f6981c35088873ccc506975aec10c62ecd706ae4fa73f11a3fbb7a786e8ca5d +size 53394 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en.png index 1aebfc1e25..ae2d011dc0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08596a989d560562dcaf95bf822d437b54273c8b05e194bd876e41db8278960c -size 60062 +oid sha256:26da644c71f1fed42bffedc56d1bf23c5454aaa8bb8679fe705567670f9c0e69 +size 54576 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en.png index 1db31f192d..96b3bfc0c5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b6b52039677271c7b20709734393061fe8ce2e3df07683cefb98d28f6f74aef -size 59297 +oid sha256:8838ca5825b2f21eff9332f2b9a21d04f5cc8ef22bb809116a19b5e47863f0f6 +size 59050 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en.png index 4df9e1a5de..3a3cc98686 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59758683e591affc670a7f738aea5e8e41a8743d32154611da0558e9c9290c35 -size 53072 +oid sha256:baebdfc57e32a6cb4e7a9dc96123056428a9304fd70d3b121c9f463d287a5ee8 +size 48584 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index b960fb2898..a81ef5cd17 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71c6926e36b400cc8842fae1029bf5240339ead2f49b31e06adcbc7cc43e1d96 -size 61757 +oid sha256:2d7121455aa0fe2cfb095d3c0a649813473752a0cf9c588059792f97badd1a3e +size 56285 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 322b173f32..db65f781ce 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22c9d278e5b933512a72b9af164e5e4b0385821d64d2b597d7e8655184c8ead0 -size 61501 +oid sha256:8fe4eb205597b6e39a99e78c4eaf8fc7805509ffea6176b02881e179f5269306 +size 56034 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en.png index 1aebfc1e25..ae2d011dc0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08596a989d560562dcaf95bf822d437b54273c8b05e194bd876e41db8278960c -size 60062 +oid sha256:26da644c71f1fed42bffedc56d1bf23c5454aaa8bb8679fe705567670f9c0e69 +size 54576 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png index 62de6e4458..78dbf9344d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c806de6d6f7c84f87ebadab6606d3d6352a8094a17cf02ee897072e3918ebdd -size 58279 +oid sha256:7065bbf0444b299bd8f024f1f1c9143a1b7ef5b20eba22d95a573f059e5f502d +size 54175 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png index 8e49010186..6914065701 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9c4bb59ec7ba0ed437f6fd19d96ed50328fecde7d1aa026e1a076bdf34376db -size 59229 +oid sha256:d55ace579493a40e9bafe3e212918010f9b285ee3ea0dd5ada6c25d21e3aa622 +size 55288 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_2_en.png index c4d6e129cd..36bb8cffea 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8b5970490e96a693655df832f9c4bf83dd55a8b06da27b48881d9f61b2dfd9c -size 55110 +oid sha256:1b654ef6029e31f4c5de17ee69807cd10ca307804939efae3c8a5859eb94c8e8 +size 53744 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_3_en.png index dfbbd46e39..9a15041143 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5ff0c767c13a80f8305096982d1fb92800d3a25fb50115c631fd3916fd7f52c -size 30180 +oid sha256:0dfa48cfb76e2c62e9eef83d5d3c3ffb1006b0d68a6898f79117e137ae55f942 +size 30267 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_4_en.png index eff729cb56..2275ac754f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b7049a6865a0ea4529cc43d16a27b9107e26d6583f429affe8327840b84ac2a -size 56050 +oid sha256:8b281cb130783d24f386536badeae5d669aeabe7f74f65042b13202dfce14960 +size 54623 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_5_en.png index 83c58ce783..636e5f40e7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b4a208d39a5f6040d17da5290a8f2f81cd917aa02c8e38b092fc79497e1e563 -size 18394 +oid sha256:f74dd5cf34442fe490ef8277851a330c21b1456105d64dcbbc30015631cfe83f +size 18568 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_2_en.png index d4d2263960..8f4f9a52aa 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:889734242ce96bfc206ae1421ab9c1cbccbcb11f99889445ea27833cbd057a0a -size 55231 +oid sha256:b5f222a27028cf852b3c92985b2ed70c406adf950fd4a9c3fe11885ede4b458d +size 53832 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_3_en.png index 4f5dba242e..5a6ac97cf8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5fa0396ed5afbb31ef60cbc74c3369e3eb306f0b4eb168424165c6246ea7cdca -size 29276 +oid sha256:8385e865dbfd322194631f9716761b66d94b86b47d351e777b653818a0a6fc3a +size 29291 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_4_en.png index dcd18cf977..f470fc5e23 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bb86c6fea38d0e798cffa5fee0610a32048aeb1d3427cd9b5b749dfacee0e55 -size 56063 +oid sha256:4dbfe0a0cc6a956b6288a82912e2de32a9555ced9a31a67ee63fed29b09b78fa +size 54701 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_5_en.png index 612b340865..d53880f9da 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.members_RoomMemberListView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6d55832abbcffc4d84b7139fbfb19d4c96a5ebcc9233ff139c5aae6b9f406d9 -size 17831 +oid sha256:a7826ffc4183453ef0d969f92cc1a034e0405732910c203213daf68a9870327a +size 17991 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png index c8a69b5b23..bad2ab5865 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cff8d671701fb10f9eced75ad665e8610169a75d29e9698a3ee77da2e7c2e53e -size 82800 +oid sha256:0924b8f2a751ed562e73a259d7e28b341b20e4760004f1af11b2965355aa208e +size 82663 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png index 29aa563c1d..9cd5f8301d 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7458d0f821af41610a30d3f044a7ddf8c84e65d405227a6db987280c39e506e4 -size 42396 +oid sha256:e95c5ea5faf80c0e6c74bba083bce824b9e5853378c0c731cc14c1f53829da9e +size 42992 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_5_en.png index 92f01aaa4a..8d83e1e828 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56ed064ba1b8dd3a1fd7238197eed66e7f15f4bcb290958131994f671dec2799 -size 38436 +oid sha256:8fd6daaaf9b3d2ce8708c12f64eadf905874de008edba5415e2d452d1cc5906e +size 38504 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_6_en.png index 8e4175320b..ffa3c3ccf1 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54337827a41fe2a2003874c3a068a4e8279fc1196e0f44b968ad9adfefe3598b -size 54763 +oid sha256:85cf2d191cb255838a25dec2b69899b096170c65463e81a34261df533b861eb1 +size 53062 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_9_en.png index bf3985b806..4f6d627398 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90138507cc2a34102c353c9e4d8c8af54ec547f92bc32b1158d980719d2f57e6 -size 37193 +oid sha256:543e5d99df73c97b6e1fcfa184e865568d9cea4d23c2ab92a9f64be66ae303d8 +size 38127 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_5_en.png index 53fc154850..3aa6cceb27 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d303fe75dcd58dd7961378cf03bde8ad5dbed7a0e437d5cd829d7963e89cca1 -size 39113 +oid sha256:de723755b90c8cacce16e27a16dcc9103e27bad86f492fd540745d90eabd7984 +size 39352 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_6_en.png index 21e05536d2..9a5c16673a 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69196aa9bf0d856a4a58f7ce5177f80e0ef58a138d501e58d3aa22215d979f03 -size 55735 +oid sha256:ece00a0efbaaef3ffa2a6cd21542a4d9f37fd722ddad8f52a2b5c5b22afaec5e +size 54275 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_9_en.png index 7556dca7b7..e467ac0551 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_UserListView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e14260ce5a9453b13bdbf6d6310fc4ea094e70e4fd27b6c84ea42f1fa24bf26c -size 37148 +oid sha256:fe7d54ea6d6bd3f74ab93360042afdad0def7b704c023b896a427d4e5e038f82 +size 37831 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png index 92a8f6edc5..b581fb7b5e 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:860e69982f2f4604f766012b223901a074d1dae69a7b62d47c27bee948be9625 -size 19774 +oid sha256:5e7c8f6b2beaf11a388c1c1eea86882836a8dc992dda0a616718e28ea10e9218 +size 19831 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png index 8aa5ec8c06..98e770a0e3 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47af637bd7dd4c178e212cde67b652381cba2bff1f0802bc8e17e792aba9bf5e -size 26628 +oid sha256:a80c27eeeb0b6d7bcae6dce55c1b76e8339a87e12ff9e489e4b94f7f8cfad048 +size 26686 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png index 7646b26049..8cba1edf39 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:584e0aa699195c24dbf9e096837975f10d65cb9134b5e27f5ceb0940f58693b2 -size 53162 +oid sha256:6d6ed05f8651e3a080a4faf8a77e8f80bc56cd52452e64e279af80098216b913 +size 50201 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png index a863215e63..00a76e245b 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f9aee160678ab11d9fa7c149f0399c296c796202160753f6f9eb2259d4d362d -size 18664 +oid sha256:2c6313c54b31b1bb0d01d3d8a144ee42a9ad8e48be5e38546d8330b7c83c51fd +size 18729 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png index 642e9454ea..c48b02266d 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:003981330bc57f34df10934331f1001cd3968209393b4adc34e61afd784e9b36 -size 24938 +oid sha256:4c494394f5d6485ebdea10c9aa04057eb9e5d05680be5a10eaa1cf13e08833cb +size 25000 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png index b7ca611ad7..1a33369536 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1196280397ffa9ba440b31a022a95bb2ee8734507d7a75eb4cf4c134b536205 -size 52796 +oid sha256:bcf1370e3cd3bee3c2ae0607d3a4d21f1e6f4aa9f3558c63f918e4cc64f126a6 +size 49709 diff --git a/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Day_1_en.png index 626008fa6c..2c3d86ccf7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de56ceb6ae4d4accaec97891cca6785a0ee02571748f83b9fa83b8b10582dd81 -size 49075 +oid sha256:2fb60b8f3e1e7a412434b7914d8c68c5266d598e9fa4f3f1a3b243a16dc7da4c +size 43723 diff --git a/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Night_1_en.png index 6742836144..3897f6c49c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.accountselect.impl_AccountSelectView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:109e7536b35f9396266b64fd84083bbfddc82caa47de3500bebe4cce9a71d1a7 -size 49924 +oid sha256:14e02b252ef0fd343b0d4cc6f7745a36dc15351ead4d3920a9e78b0fd329f04b +size 44581 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png index 837bf8922a..2622790d8a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e52b296963423635bd42274768882d3aa30a6f2865c18f3999356d9cc815154 -size 50445 +oid sha256:afef26d6f1eaae9c9990095ff76081796ab408b611fc6d5e54eaf4e5149d5416 +size 50236 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png index 710791d0b0..2fde0deb9d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c36cacfcdf856303fa981fe90271bbda2583d363aadd44b88eb8556d6cb09b12 -size 108348 +oid sha256:58e898ed1ed67402f639f61628729bbabad0142c9047aeacf3e1312ef2d1a469 +size 103204 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png index c3a2cefc62..1743c14ddc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ae8f733f41116d35d039edc8243e11eb4175b1485cbfb72b02d0e4d1caf07af -size 9587 +oid sha256:3d5708861e397d6d20cf6900e4fa566dc86961eeadea6ceeb13f15f5f9e93caf +size 9796 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png index afd7a35b27..26913e3446 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eace16f819a0fa1aa10a859315d86c639abc51367295e8ea2d2d3826415152e1 -size 9569 +oid sha256:bc971461b2e57aef9021633759cdf7e3771d52bd9d9a23631765da0e4ece028f +size 9495 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png index adbd45547a..77fea21917 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c128b9907bb834a08569f8cb6c93c2c97249f813a405b4dff0cfa35b23793112 -size 9663 +oid sha256:d45fb1723e9b0a1a45618f68d18697ec8e5cabeab1224447913a366510aff352 +size 9828 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png index 05615cc2e0..d66fba44a3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24bb6401edef8bd83a6f5d6854a50c13039553b042db690dc5e1763f364764b9 -size 9529 +oid sha256:99964776c4a2be5d5fbbc9d600516fd758238c382e9ae4a7e49bf91193d10898 +size 9420 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png index a998c229dc..441b38a3b8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:441264fe4ba673ab069b38d45243bbff77e2a17f99fd849d9c8b6cd30486e54d -size 55142 +oid sha256:228ec3cb50e9bf8079a1e484bcc36b84dadd3ffd0c790257a98f05b48e3e423d +size 55445 From aaf788b4486f49f0c14bfa2a4d3880221bda289f Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 15 Dec 2025 10:25:08 +0100 Subject: [PATCH 62/64] Fix crash when calling `Room.predecessorRoom` when the room is destroyed (#5894) * Fix crash when calling `Client.predecessorRoom` when the room is destroyed * Handle the root cause of this crash: destroying the room on activity recreation --- .../room/joined/JoinedRoomLoadedFlowNode.kt | 15 +++++++++++++-- .../libraries/matrix/impl/room/RustBaseRoom.kt | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index 5a6ef9133b..0b3ba57776 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -8,7 +8,9 @@ package io.element.android.appnav.room.joined +import android.app.Activity import android.os.Parcelable +import androidx.activity.compose.LocalActivity import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.lifecycle.lifecycleScope @@ -96,6 +98,9 @@ class JoinedRoomLoadedFlowNode( private val callback: Callback = callback() override val graph = roomGraphFactory.create(inputs.room) + // This is an ugly hack to check activity recreation + private var currentActivity: Activity? = null + init { lifecycle.subscribe( onCreate = { @@ -115,8 +120,12 @@ class JoinedRoomLoadedFlowNode( }, onDestroy = { Timber.v("OnDestroy") - activeRoomsHolder.removeRoom(inputs.room.sessionId, inputs.room.roomId) - inputs.room.destroy() + // If we're just going through an activity recreation there's no need to destroy the Room object + // Destroying it would actually cause an issue where its methods can no longer be called + if (currentActivity?.isChangingConfigurations != true) { + activeRoomsHolder.removeRoom(inputs.room.sessionId, inputs.room.roomId) + inputs.room.destroy() + } appNavigationStateService.onLeavingRoom(id) } ) @@ -289,6 +298,8 @@ class JoinedRoomLoadedFlowNode( @Composable override fun View(modifier: Modifier) { + currentActivity = LocalActivity.current + BackstackView() } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index be7f6240ee..4fabff8cc0 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -85,7 +85,9 @@ class RustBaseRoom( }.stateIn(roomCoroutineScope, started = SharingStarted.Lazily, initialValue = initialRoomInfo) override fun predecessorRoom(): PredecessorRoom? { - return innerRoom.predecessorRoom()?.map() + return runCatchingExceptions { innerRoom.predecessorRoom()?.map() } + .onFailure { Timber.e(it, "Could not get predecessor room") } + .getOrNull() } override suspend fun subscribeToSync() = roomSyncSubscriber.subscribe(roomId) From d4c7cb77fbad023c8dc7f3fc2cb0ddc511bddfc1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 10:45:59 +0000 Subject: [PATCH 63/64] fix(deps): update dependency com.android.tools.build:gradle to v8.13.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1ed3ea4f4e..b5a2607c01 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ [versions] # Project -android_gradle_plugin = "8.13.1" +android_gradle_plugin = "8.13.2" # When updateing this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.2.20" kotlinpoet = "2.2.0" From 0476cbd4d928e0dabf1ff8c9da01779413410485 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Dec 2025 18:09:06 +0100 Subject: [PATCH 64/64] misc(power level) : expose RoomMemberModerationPermissions after PR review --- .../messages/impl/MessagesStateProvider.kt | 7 ++--- .../impl/members/RoomMemberListState.kt | 2 +- .../members/RoomMemberListStateProvider.kt | 7 +++-- .../api/RoomMemberModerationPermissions.kt | 29 +++++++++++++++++++ .../api/RoomMemberModerationState.kt | 3 +- .../impl/InternalRoomMemberModerationState.kt | 4 +-- ...ternalRoomMemberModerationStateProvider.kt | 7 ++--- .../impl/RoomMemberModerationPresenter.kt | 19 ++++-------- .../impl/RoomMemberModerationPresenterTest.kt | 4 +-- 9 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationPermissions.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 7831265fd0..cec9f68b45 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -41,6 +41,7 @@ import io.element.android.features.messages.impl.timeline.protection.aTimelinePr import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.aStandByCallState import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -164,11 +165,9 @@ fun aMessagesState( ) fun aRoomMemberModerationState( - canKick: Boolean = false, - canBan: Boolean = false, + permissions: RoomMemberModerationPermissions = RoomMemberModerationPermissions.DEFAULT, ) = object : RoomMemberModerationState { - override val canKick: Boolean = canKick - override val canBan: Boolean = canBan + override val permissions: RoomMemberModerationPermissions = permissions override val eventSink: (RoomMemberModerationEvents) -> Unit = {} } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt index 007d276dd3..7c928fb27a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListState.kt @@ -26,7 +26,7 @@ data class RoomMemberListState( val moderationState: RoomMemberModerationState, val eventSink: (RoomMemberListEvents) -> Unit, ) { - val showBannedSection: Boolean = moderationState.canBan && roomMembers.dataOrNull()?.banned?.isNotEmpty() == true + val showBannedSection: Boolean = moderationState.permissions.canBan && roomMembers.dataOrNull()?.banned?.isNotEmpty() == true } enum class SelectedSection { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt index 580db7667a..b37738c30f 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.roomdetails.impl.members import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.map @@ -99,8 +100,10 @@ fun aRoomMemberModerationState( canKick: Boolean = false, ): RoomMemberModerationState { return object : RoomMemberModerationState { - override val canKick: Boolean = canKick - override val canBan: Boolean = canBan + override val permissions: RoomMemberModerationPermissions = RoomMemberModerationPermissions( + canBan = canBan, + canKick = canKick, + ) override val eventSink: (RoomMemberModerationEvents) -> Unit = {} } } diff --git a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationPermissions.kt b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationPermissions.kt new file mode 100644 index 0000000000..223456de69 --- /dev/null +++ b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationPermissions.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roommembermoderation.api + +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +data class RoomMemberModerationPermissions( + val canKick: Boolean, + val canBan: Boolean, +) { + companion object { + val DEFAULT = RoomMemberModerationPermissions( + canKick = false, + canBan = false, + ) + } +} + +fun RoomPermissions.roomMemberModerationPermissions(): RoomMemberModerationPermissions { + return RoomMemberModerationPermissions( + canKick = canOwnUserKick(), + canBan = canOwnUserBan(), + ) +} diff --git a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt index 85f3e8ec19..c9ee958f6f 100644 --- a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt +++ b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationState.kt @@ -12,8 +12,7 @@ import androidx.compose.runtime.Immutable @Immutable interface RoomMemberModerationState { - val canKick: Boolean - val canBan: Boolean + val permissions: RoomMemberModerationPermissions val eventSink: (RoomMemberModerationEvents) -> Unit } diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt index fe48ece1fd..f45a277992 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationState.kt @@ -10,14 +10,14 @@ package io.element.android.features.roommembermoderation.impl import io.element.android.features.roommembermoderation.api.ModerationActionState import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList data class InternalRoomMemberModerationState( - override val canKick: Boolean, - override val canBan: Boolean, + override val permissions: RoomMemberModerationPermissions, val selectedUser: MatrixUser?, val actions: ImmutableList, val kickUserAsyncAction: AsyncAction, diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt index d90f352cfa..120a299a7d 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.roommembermoderation.api.ModerationAction import io.element.android.features.roommembermoderation.api.ModerationActionState import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser @@ -83,8 +84,7 @@ fun anAlice() = MatrixUser( ) fun aRoomMembersModerationState( - canKick: Boolean = false, - canBan: Boolean = false, + permissions: RoomMemberModerationPermissions = RoomMemberModerationPermissions.DEFAULT, selectedUser: MatrixUser? = null, actions: List = emptyList(), kickUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, @@ -92,8 +92,7 @@ fun aRoomMembersModerationState( unbanUserAsyncAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (RoomMemberModerationEvents) -> Unit = {}, ) = InternalRoomMemberModerationState( - canKick = canKick, - canBan = canBan, + permissions = permissions, selectedUser = selectedUser, actions = actions.toImmutableList(), kickUserAsyncAction = kickUserAsyncAction, diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt index 96749ba5ac..16a11aee96 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenter.kt @@ -21,7 +21,9 @@ import im.vector.app.features.analytics.plan.RoomModeration import io.element.android.features.roommembermoderation.api.ModerationAction import io.element.android.features.roommembermoderation.api.ModerationActionState import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.features.roommembermoderation.api.RoomMemberModerationState +import io.element.android.features.roommembermoderation.api.roomMemberModerationPermissions import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runUpdatingState @@ -55,11 +57,8 @@ class RoomMemberModerationPresenter( override fun present(): RoomMemberModerationState { val coroutineScope = rememberCoroutineScope() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() - val permissions by room.permissionsAsState(Permissions()) { perms -> - Permissions( - canKick = perms.canOwnUserKick(), - canBan = perms.canOwnUserBan(), - ) + val permissions by room.permissionsAsState(RoomMemberModerationPermissions.DEFAULT) { perms -> + perms.roomMemberModerationPermissions() } val currentUserMemberPowerLevel = room.userPowerLevelAsState(syncUpdateFlow.value) @@ -136,8 +135,7 @@ class RoomMemberModerationPresenter( } return InternalRoomMemberModerationState( - canKick = permissions.canKick, - canBan = permissions.canBan, + permissions = permissions, selectedUser = selectedUser, actions = moderationActions.value, kickUserAsyncAction = kickUserAsyncAction.value, @@ -149,7 +147,7 @@ class RoomMemberModerationPresenter( private fun computeModerationActions( member: RoomMember?, - permissions: Permissions, + permissions: RoomMemberModerationPermissions, currentUserMemberPowerLevel: Long, ): ImmutableList { return buildList { @@ -209,11 +207,6 @@ class RoomMemberModerationPresenter( ) } - private data class Permissions( - val canKick: Boolean = false, - val canBan: Boolean = false, - ) - private fun CoroutineScope.runActionAndWaitForMembershipChange( action: MutableState>, block: suspend () -> Result diff --git a/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt b/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt index 4ce50a2488..3f59151eea 100644 --- a/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt +++ b/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationPresenterTest.kt @@ -13,6 +13,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.roommembermoderation.api.ModerationAction import io.element.android.features.roommembermoderation.api.ModerationActionState import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents +import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -49,8 +50,7 @@ class RoomMemberModerationPresenterTest { val room = aJoinedRoom() createRoomMemberModerationPresenter(room = room).test { val initialState = awaitState() - assertThat(initialState.canKick).isFalse() - assertThat(initialState.canBan).isFalse() + assertThat(initialState.permissions).isEqualTo(RoomMemberModerationPermissions.DEFAULT) assertThat(initialState.selectedUser).isNull() assertThat(initialState.banUserAsyncAction).isEqualTo(AsyncAction.Uninitialized) assertThat(initialState.kickUserAsyncAction).isEqualTo(AsyncAction.Uninitialized)